mirror of
https://github.com/wekan/wekan.git
synced 2026-11-05 09:40:20 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c62396e389 | ||
|
|
d52e85f298 | ||
|
|
05ebae7329 | ||
|
|
b697bb656e | ||
|
|
4d7de2adce | ||
|
|
8a9528e787 | ||
|
|
6c6cba51fa | ||
|
|
28e23f9d87 | ||
|
|
e31192e97e | ||
|
|
26b7137b5c | ||
|
|
912200a2ec | ||
|
|
c42d0d7423 | ||
|
|
3da66a0fe3 | ||
|
|
41e1f8fbc3 | ||
|
|
130ac3c917 | ||
|
|
3774060d32 | ||
|
|
d8c8856548 | ||
|
|
efec00a550 | ||
|
|
3d3cf1d551 | ||
|
|
c52d17b6fb | ||
|
|
c0b9ef5990 | ||
|
|
e303159b98 | ||
|
|
f274b3c26b | ||
|
|
81fdc9a865 | ||
|
|
f40c9804f8 | ||
|
|
4d13d51038 | ||
|
|
5c4421dc38 | ||
|
|
76ef6a81ab | ||
|
|
a7b43d5b57 | ||
|
|
e4f50d4713 | ||
|
|
1e71237627 | ||
|
|
678c8f6bf6 | ||
|
|
786c27bbec | ||
|
|
710643d8cb | ||
|
|
e595aba189 | ||
|
|
ea67e94c47 | ||
|
|
b2c2067f7d | ||
|
|
4fc2d7b935 | ||
|
|
b1b9dd208b | ||
|
|
ee2f7c077f | ||
|
|
a385d6f4fd | ||
|
|
7031b7a3c7 | ||
|
|
0f0a5fba1f | ||
|
|
1d7af3f011 | ||
|
|
6fd85f97b3 | ||
|
|
a6d17f3813 | ||
|
|
4e830ea416 | ||
|
|
fc5c936272 | ||
|
|
b2af684c4d | ||
|
|
0446999c63 | ||
|
|
6920c39752 |
No files matched your search
@@ -1,3 +1,51 @@
|
||||
# v4.92 2021-02-03 Wekan release
|
||||
|
||||
This release adds the following improvements:
|
||||
|
||||
- [Import user mapping improvements](https://github.com/wekan/wekan/pull/3510).
|
||||
Thanks to jrsupplee.
|
||||
- Added Createtoken API.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/3520),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/3774060d32abcfee17dc1c31958d4673794d8619).
|
||||
Thanks to magicbelette and xet7.
|
||||
- Sorted archives.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/3518),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/3da66a0fe30c2b54b63e5d098232b375d899925e).
|
||||
Thanks to bronger, jrsupplee and xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/05ebae7329ba0dd3fe9b04cd63b1f983830cdeee).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Don't reload page when returning default sort](https://github.com/wekan/wekan/pull/3509).
|
||||
Thanks to jrsupplee.
|
||||
- [Avatar overlaped notifications](https://github.com/wekan/wekan/pull/3516).
|
||||
Thanks to mfilser.
|
||||
- [Hopeful fix for i18n not working in `onRendered()`](https://github.com/wekan/wekan/pull/3519).
|
||||
Thanks to jrsupplee.
|
||||
- [Disable some console.log code, that is only needed while developing](https://github.com/wekan/wekan/commit/f40c9804f848fdb91229c5718ad97495337109ba).
|
||||
Thanks to xet7.
|
||||
- [Try fix removed nonexistent document error](https://github.com/wekan/wekan/commit/f274b3c26be60813829dcf2b0e68a8dd876ff614).
|
||||
Thanks to Brulf, TheMasterFX and xet7.
|
||||
- [Fixed Cards and CustomFields sorted alphabetically](https://github.com/wekan/wekan/pull/3521).
|
||||
Thanks to mfilser.
|
||||
- [Notifications avatar overlaped at mobile view](https://github.com/wekan/wekan/pull/3523).
|
||||
Thanks to mfilser.
|
||||
|
||||
and improves some security related info:
|
||||
|
||||
- [Added badge for CII Best Practices](https://github.com/wekan/wekan/commit/ee2f7c077fe56d6fedb8b75ae3cba6bab56f9363).
|
||||
Thanks to CII and xet7.
|
||||
- [Added PGP public key for sending security vulnerability reports](https://github.com/wekan/wekan/commit/a385d6f4fd76e2bb0f374963848513b9373d6b5a).
|
||||
Thanks to xet7.
|
||||
- [Updated security report email address](https://github.com/wekan/wekan/commit/7031b7a3c77acc0ddeabe436572dd4057001e9f5).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.91 2021-01-29 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
[](https://david-dm.org/wekan/wekan)
|
||||
[](https://www.openhub.net/p/wekan)
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwekan%2Fwekan?ref=badge_shield)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/4619)
|
||||
|
||||
## [Translate Wekan at Transifex](https://transifex.com/wekan/wekan)
|
||||
|
||||
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
Security is very important to us. If you discover any issue regarding security, please disclose
|
||||
the information responsibly by sending an email to security (at) wekan.team and not by
|
||||
the information responsibly by sending an email to support (at) wekan.team using
|
||||
[this PGP public key](support-at-wekan.team_pgp-publickey.asc) and not by
|
||||
creating a GitHub issue. We will respond swiftly to fix verifiable security issues.
|
||||
|
||||
We thank you with a place at our hall of fame page, that is
|
||||
at https://wekan.github.io/hall-of-fame . Others have just posted public GitHub issue,
|
||||
so they are not at that hall-of-fame page.
|
||||
at https://wekan.github.io/hall-of-fame
|
||||
|
||||
## How should reports be formatted?
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v4.91.0"
|
||||
appVersion: "v4.92.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -11,7 +11,7 @@ BlazeComponent.extendComponent({
|
||||
return Boards.find(
|
||||
{ archived: true },
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -176,6 +176,7 @@
|
||||
border-radius: 50%
|
||||
height: 28px
|
||||
width: @height
|
||||
margin: 0px 0px 4px 0px
|
||||
|
||||
.assignee
|
||||
float: right
|
||||
|
||||
@@ -22,6 +22,8 @@ template(name="importMapMembers")
|
||||
if usersLoaded.get
|
||||
.map-members
|
||||
p {{_ 'import-members-map'}}
|
||||
p.import-members-map-note
|
||||
| {{_ 'import-members-map-note' }}
|
||||
.mapping-list
|
||||
each members
|
||||
a.mapping-item.js-select-member(class="{{#if wekanId}}filled{{/if}}")
|
||||
|
||||
@@ -169,10 +169,13 @@ BlazeComponent.extendComponent({
|
||||
this._refreshMembers(
|
||||
this.members().map(member => {
|
||||
if (!member.wekanId) {
|
||||
const user = Users.findOne({ username: member.username });
|
||||
let user = Users.findOne({ username: member.username });
|
||||
if (!user) {
|
||||
user = Users.findOne({ importUsernames: member.username });
|
||||
}
|
||||
if (user) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('found username:', user.username);
|
||||
// console.log('found username:', user.username);
|
||||
member.wekanId = user._id;
|
||||
}
|
||||
}
|
||||
|
||||
Vendored
+4
@@ -47,3 +47,7 @@
|
||||
|
||||
a.show-mapping
|
||||
text-decoration underline
|
||||
|
||||
.import-members-map-note
|
||||
font-size: 90%
|
||||
font-weight: bold
|
||||
@@ -60,7 +60,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
dueCardsView() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('sort:', Utils.dueCardsView());
|
||||
//console.log('sort:', Utils.dueCardsView());
|
||||
return Utils.dueCardsView();
|
||||
},
|
||||
|
||||
|
||||
@@ -78,12 +78,10 @@ BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
Meteor.subscribe('setting');
|
||||
|
||||
this.colorMap = {};
|
||||
for (const color of Boards.simpleSchema()._schema['labels.$.color']
|
||||
.allowedValues) {
|
||||
this.colorMap[TAPi18n.__(`color-${color}`)] = color;
|
||||
}
|
||||
// // eslint-disable-next-line no-console
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('lang:', TAPi18n.getLanguage());
|
||||
this.colorMap = Boards.colorMap();
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('colorMap:', this.colorMap);
|
||||
|
||||
if (Session.get('globalQuery')) {
|
||||
@@ -116,7 +114,7 @@ BlazeComponent.extendComponent({
|
||||
if (this.queryParams) {
|
||||
const sessionData = this.getSessionData();
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('selector:', sessionData.getSelector());
|
||||
// console.log('selector:', sessionData.getSelector());
|
||||
// console.log('session data:', sessionData);
|
||||
const cards = Cards.find({ _id: { $in: sessionData.cards } });
|
||||
this.queryErrors = sessionData.errors;
|
||||
@@ -178,7 +176,7 @@ BlazeComponent.extendComponent({
|
||||
searchAllBoards(query) {
|
||||
query = query.trim();
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('query:', query);
|
||||
//console.log('query:', query);
|
||||
|
||||
this.query.set(query);
|
||||
|
||||
@@ -296,13 +294,14 @@ BlazeComponent.extendComponent({
|
||||
if (m.groups.operator) {
|
||||
op = m.groups.operator.toLowerCase();
|
||||
} else {
|
||||
op = m.groups.abbrev;
|
||||
op = m.groups.abbrev.toLowerCase();
|
||||
}
|
||||
if (operatorMap.hasOwnProperty(op)) {
|
||||
let value = m.groups.value;
|
||||
if (operatorMap[op] === 'labels') {
|
||||
if (value in this.colorMap) {
|
||||
value = this.colorMap[value];
|
||||
// console.log('found color:', value);
|
||||
}
|
||||
} else if (
|
||||
['dueAt', 'createdAt', 'modifiedAt'].includes(operatorMap[op])
|
||||
@@ -388,7 +387,7 @@ BlazeComponent.extendComponent({
|
||||
params.text = text;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('params:', params);
|
||||
console.log('params:', params);
|
||||
|
||||
this.queryParams = params;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
.notification
|
||||
display: flex
|
||||
float: none
|
||||
padding: 12px 8px 8px
|
||||
padding: 15px 8px 8px
|
||||
color: black
|
||||
border-bottom: 1px solid #dbdbdb
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
.read-status
|
||||
width: 30px
|
||||
padding: 0px 10px 0px 0px
|
||||
|
||||
input
|
||||
width: 24px
|
||||
@@ -28,13 +29,19 @@
|
||||
color: #bbb
|
||||
|
||||
.details
|
||||
width: calc(100% - 30px)
|
||||
|
||||
.activity
|
||||
display: flex
|
||||
|
||||
a.member
|
||||
margin: 0px 0px 0px 0px
|
||||
padding: 0px
|
||||
|
||||
svg
|
||||
padding: 3px
|
||||
|
||||
.activity-desc
|
||||
width: 100%;
|
||||
margin: 0px 0px 0px 5px
|
||||
|
||||
.activity-comment
|
||||
display: block
|
||||
@@ -55,3 +62,14 @@
|
||||
.remove
|
||||
a:hover
|
||||
color #eb4646 !important
|
||||
|
||||
@media screen and (max-width: 800px)
|
||||
#notifications-drawer
|
||||
.notification
|
||||
height: auto
|
||||
|
||||
.details
|
||||
.activity
|
||||
a.member
|
||||
height: 36px
|
||||
width: 36px
|
||||
@@ -2,7 +2,7 @@ belize = #2980b9
|
||||
|
||||
section#notifications-drawer
|
||||
position: fixed
|
||||
top: 28px
|
||||
top: 48px
|
||||
right: 0
|
||||
width: 400px
|
||||
background-color: #fafafa
|
||||
@@ -17,7 +17,7 @@ section#notifications-drawer
|
||||
|
||||
.header
|
||||
position: fixed
|
||||
top 28px
|
||||
top 48px
|
||||
right 0
|
||||
width calc(400px - 32px)
|
||||
padding: 8px 16px
|
||||
@@ -63,7 +63,7 @@ section#notifications-drawer
|
||||
|
||||
ul.notifications
|
||||
display: block
|
||||
padding: 0px 16px
|
||||
padding: 0px 16px 0px 16px
|
||||
margin: 0
|
||||
height: calc(100vh - 102px)
|
||||
height: calc(100vh - 122px)
|
||||
overflow-y: scroll
|
||||
@@ -110,6 +110,7 @@ template(name="peopleGeneral")
|
||||
th {{_ 'createdAt'}}
|
||||
th {{_ 'active'}}
|
||||
th {{_ 'authentication-method'}}
|
||||
th {{_ 'import-usernames'}}
|
||||
th
|
||||
+newUserRow
|
||||
each user in peopleList
|
||||
@@ -257,6 +258,10 @@ template(name="peopleRow")
|
||||
td <s>{{_ userData.authenticationMethod }}</s>
|
||||
else
|
||||
td {{_ userData.authenticationMethod }}
|
||||
if userData.loginDisabled
|
||||
td <s>{{ userData.importUsernamesString }}</s>
|
||||
else
|
||||
td {{ userData.importUsernamesString }}
|
||||
td
|
||||
a.edit-user
|
||||
i.fa.fa-edit
|
||||
@@ -346,6 +351,9 @@ template(name="editUserPopup")
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
|
||||
else
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" required)
|
||||
label
|
||||
| {{_ 'import-usernames'}}
|
||||
input.js-import-usernames(type="text" value=user.importUsernames)
|
||||
label
|
||||
| {{_ 'verified'}}
|
||||
select.select-verified.js-profile-email-verified
|
||||
@@ -444,6 +452,9 @@ template(name="newUserPopup")
|
||||
// input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
|
||||
//else
|
||||
input.js-profile-email(type="email" value="" required)
|
||||
label
|
||||
| {{_ 'import-usernames'}}
|
||||
input.js-import-usernames(type="text" value="")
|
||||
label
|
||||
| {{_ 'admin'}}
|
||||
select.select-role.js-profile-isadmin
|
||||
|
||||
@@ -143,7 +143,7 @@ BlazeComponent.extendComponent({
|
||||
const orgs = Org.find(this.findOrgsOptions.get(), {
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberOrgs.set(org.count(false));
|
||||
this.numberOrgs.set(orgs.count(false));
|
||||
return orgs;
|
||||
},
|
||||
teamList() {
|
||||
@@ -421,6 +421,9 @@ Template.editUserPopup.events({
|
||||
const authentication = templateInstance
|
||||
.find('.js-authenticationMethod')
|
||||
.value.trim();
|
||||
const importUsernames = templateInstance
|
||||
.find('.js-import-usernames')
|
||||
.value.trim();
|
||||
|
||||
const isChangePassword = password.length > 0;
|
||||
const isChangeUserName = username !== user.username;
|
||||
@@ -441,6 +444,7 @@ Template.editUserPopup.events({
|
||||
isAdmin: isAdmin === 'true',
|
||||
loginDisabled: isActive === 'true',
|
||||
authenticationMethod: authentication,
|
||||
importUsernames: Users.parseImportUsernames(importUsernames),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -563,6 +567,9 @@ Template.newUserPopup.events({
|
||||
const isAdmin = templateInstance.find('.js-profile-isadmin').value.trim();
|
||||
const isActive = templateInstance.find('.js-profile-isactive').value.trim();
|
||||
const email = templateInstance.find('.js-profile-email').value.trim();
|
||||
const importUsernames = templateInstance
|
||||
.find('.js-import-usernames')
|
||||
.value.trim();
|
||||
|
||||
Meteor.call(
|
||||
'setCreateUser',
|
||||
@@ -572,6 +579,7 @@ Template.newUserPopup.events({
|
||||
isAdmin,
|
||||
isActive,
|
||||
email.toLowerCase(),
|
||||
importUsernames,
|
||||
function(error) {
|
||||
const usernameMessageElement = templateInstance.$('.username-taken');
|
||||
const emailMessageElement = templateInstance.$('.email-taken');
|
||||
|
||||
@@ -14,6 +14,11 @@ template(name="archivesSidebar")
|
||||
if currentUser.isBoardMember
|
||||
unless isWorker
|
||||
p.quiet
|
||||
if this.archivedAt
|
||||
| {{_ 'archived-at' }}
|
||||
|
|
||||
| {{ moment this.archivedAt 'LLL' }}
|
||||
br
|
||||
a.js-restore-card {{_ 'restore'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
@@ -37,6 +42,11 @@ template(name="archivesSidebar")
|
||||
if currentUser.isBoardMember
|
||||
unless isWorker
|
||||
p.quiet
|
||||
if this.archivedAt
|
||||
| {{_ 'archived-at' }}
|
||||
|
|
||||
| {{ moment this.archivedAt 'LLL' }}
|
||||
br
|
||||
a.js-restore-list {{_ 'restore'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
@@ -58,6 +68,11 @@ template(name="archivesSidebar")
|
||||
if currentUser.isBoardMember
|
||||
unless isWorker
|
||||
p.quiet
|
||||
if this.archivedAt
|
||||
| {{_ 'archived-at' }}
|
||||
|
|
||||
| {{ moment this.archivedAt 'LLL' }}
|
||||
br
|
||||
a.js-restore-swimlane {{_ 'restore'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
|
||||
@@ -34,6 +34,8 @@ BlazeComponent.extendComponent({
|
||||
return Cards.find({
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
}, {
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
});
|
||||
},
|
||||
|
||||
@@ -41,6 +43,8 @@ BlazeComponent.extendComponent({
|
||||
return Lists.find({
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
}, {
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
});
|
||||
},
|
||||
|
||||
@@ -48,6 +52,8 @@ BlazeComponent.extendComponent({
|
||||
return Swimlanes.find({
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
}, {
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
+17
-17
@@ -4,24 +4,24 @@
|
||||
|
||||
Meteor.startup(() => {
|
||||
TAPi18n.conf.i18n_files_route = Meteor._relativeToSiteRootUrl('/tap-i18n');
|
||||
Tracker.autorun(() => {
|
||||
const currentUser = Meteor.user();
|
||||
let language;
|
||||
if (currentUser) {
|
||||
language = currentUser.profile && currentUser.profile.language;
|
||||
}
|
||||
const currentUser = Meteor.user();
|
||||
let language;
|
||||
if (currentUser) {
|
||||
language = currentUser.profile && currentUser.profile.language;
|
||||
}
|
||||
|
||||
if (!language) {
|
||||
if (navigator.languages) {
|
||||
language = navigator.languages[0];
|
||||
} else {
|
||||
language = navigator.language || navigator.userLanguage;
|
||||
}
|
||||
if (!language) {
|
||||
if (navigator.languages) {
|
||||
language = navigator.languages[0];
|
||||
} else {
|
||||
language = navigator.language || navigator.userLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
if (language) {
|
||||
TAPi18n.setLanguage(language);
|
||||
T9n.setLanguage(language);
|
||||
}
|
||||
});
|
||||
if (language) {
|
||||
TAPi18n.setLanguage(language);
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('language set!');
|
||||
T9n.setLanguage(language);
|
||||
}
|
||||
});
|
||||
@@ -48,8 +48,6 @@ Utils = {
|
||||
let sort = window.localStorage.getItem('myCardsSort');
|
||||
|
||||
if (!sort || !['board', 'dueAt'].includes(sort)) {
|
||||
window.localStorage.setItem('myCardsSort', 'board');
|
||||
location.reload();
|
||||
sort = 'board';
|
||||
}
|
||||
|
||||
@@ -81,8 +79,6 @@ Utils = {
|
||||
let view = window.localStorage.getItem('dueCardsView');
|
||||
|
||||
if (!view || !['me', 'all'].includes(view)) {
|
||||
window.localStorage.setItem('dueCardsView', 'me');
|
||||
location.reload();
|
||||
view = 'me';
|
||||
}
|
||||
|
||||
|
||||
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+4
-1
@@ -384,6 +384,7 @@
|
||||
"import-csv-placeholder": "Paste your valid CSV/TSV data here",
|
||||
"import-map-members": "Map members",
|
||||
"import-members-map": "Your imported board has some members. Please map the members you want to import to your users",
|
||||
"import-members-map-note": "Note: Unmapped members will be assigned to the current user.",
|
||||
"import-show-user-mapping": "Review members mapping",
|
||||
"import-user-select": "Pick your existing user you want to use as this member",
|
||||
"importMapMembersAddPopup-title": "Select member",
|
||||
@@ -530,6 +531,7 @@
|
||||
"custom-login-logo-link-url": "Custom Login Logo Link URL",
|
||||
"text-below-custom-login-logo": "Text below Custom Login Logo",
|
||||
"username": "Username",
|
||||
"import-usernames": "Import Usernames",
|
||||
"view-it": "View it",
|
||||
"warn-list-archived": "warning: this card is in an list at Archive",
|
||||
"watch": "Watch",
|
||||
@@ -949,5 +951,6 @@
|
||||
"excel-font": "Arial",
|
||||
"number": "Number",
|
||||
"label-colors": "Label Colors",
|
||||
"label-names": "Label Names"
|
||||
"label-names": "Label Names",
|
||||
"archived-at": "archived at"
|
||||
}
|
||||
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+953
-951
File diff suppressed because it is too large.
Load diff
+20
-1
@@ -43,6 +43,13 @@ Boards.attachSchema(
|
||||
}
|
||||
},
|
||||
},
|
||||
archivedAt: {
|
||||
/**
|
||||
* Latest archiving time of the board
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
createdAt: {
|
||||
/**
|
||||
* Creation time of the board
|
||||
@@ -1042,7 +1049,7 @@ Boards.helpers({
|
||||
|
||||
Boards.mutations({
|
||||
archive() {
|
||||
return { $set: { archived: true } };
|
||||
return { $set: { archived: true, archivedAt: new Date() } };
|
||||
},
|
||||
|
||||
restore() {
|
||||
@@ -1318,6 +1325,18 @@ Boards.userBoardIds = (userId, archived = false, selector = {}) => {
|
||||
});
|
||||
};
|
||||
|
||||
Boards.colorMap = () => {
|
||||
const colors = {};
|
||||
for (const color of Boards.labelColors()) {
|
||||
colors[TAPi18n.__(`color-${color}`)] = color;
|
||||
}
|
||||
return colors;
|
||||
};
|
||||
|
||||
Boards.labelColors = () => {
|
||||
return _.clone(Boards.simpleSchema()._schema['labels.$.color'].allowedValues);
|
||||
};
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Boards.allow({
|
||||
insert: Meteor.userId,
|
||||
|
||||
@@ -168,9 +168,6 @@ if (Meteor.isServer) {
|
||||
listId: card.listId,
|
||||
swimlaneId: card.swimlaneId,
|
||||
});
|
||||
});
|
||||
|
||||
CardComments.after.remove((userId, doc) => {
|
||||
const activity = Activities.findOne({ commentId: doc._id });
|
||||
if (activity) {
|
||||
Activities.remove(activity._id);
|
||||
|
||||
+14
-3
@@ -26,6 +26,13 @@ Cards.attachSchema(
|
||||
}
|
||||
},
|
||||
},
|
||||
archivedAt: {
|
||||
/**
|
||||
* latest archiving date
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
parentId: {
|
||||
/**
|
||||
* ID of the parent card
|
||||
@@ -724,9 +731,12 @@ Cards.helpers({
|
||||
definition,
|
||||
};
|
||||
});
|
||||
if (ret.definition !== undefined) {
|
||||
ret.sort((a, b) => a.definition.name.localeCompare(b.definition.name));
|
||||
}
|
||||
ret.sort(
|
||||
(a, b) =>
|
||||
a.definition.name !== undefined &&
|
||||
b.definition.name !== undefined &&
|
||||
a.definition.name.localeCompare(b.definition.name),
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
@@ -1446,6 +1456,7 @@ Cards.mutations({
|
||||
return {
|
||||
$set: {
|
||||
archived: true,
|
||||
archivedAt: new Date(),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@@ -385,8 +385,8 @@ export class ExporterExcel {
|
||||
}
|
||||
//add data +8 hours
|
||||
function addTZhours(jdate) {
|
||||
let curdate = new Date(jdate);
|
||||
let checkCorrectDate = moment(curdate);
|
||||
const curdate = new Date(jdate);
|
||||
const checkCorrectDate = moment(curdate);
|
||||
if (checkCorrectDate.isValid()) {
|
||||
return curdate;
|
||||
} else {
|
||||
|
||||
+9
-1
@@ -32,6 +32,13 @@ Lists.attachSchema(
|
||||
}
|
||||
},
|
||||
},
|
||||
archivedAt: {
|
||||
/**
|
||||
* latest archiving date
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
boardId: {
|
||||
/**
|
||||
* the board associated to this list
|
||||
@@ -292,7 +299,7 @@ Lists.mutations({
|
||||
return card.archive();
|
||||
});
|
||||
}
|
||||
return { $set: { archived: true } };
|
||||
return { $set: { archived: true, archivedAt: new Date() } };
|
||||
},
|
||||
|
||||
restore() {
|
||||
@@ -384,6 +391,7 @@ if (Meteor.isServer) {
|
||||
Meteor.startup(() => {
|
||||
Lists._collection._ensureIndex({ modifiedAt: -1 });
|
||||
Lists._collection._ensureIndex({ boardId: 1 });
|
||||
Lists._collection._ensureIndex({ archivedAt: -1 });
|
||||
});
|
||||
|
||||
Lists.after.insert((userId, doc) => {
|
||||
|
||||
+8
-1
@@ -23,6 +23,13 @@ Swimlanes.attachSchema(
|
||||
}
|
||||
},
|
||||
},
|
||||
archivedAt: {
|
||||
/**
|
||||
* latest archiving date of the swimlane
|
||||
*/
|
||||
type: Date,
|
||||
optional: true,
|
||||
},
|
||||
boardId: {
|
||||
/**
|
||||
* the ID of the board the swimlane is attached to
|
||||
@@ -259,7 +266,7 @@ Swimlanes.mutations({
|
||||
return list.archive();
|
||||
});
|
||||
}
|
||||
return { $set: { archived: true } };
|
||||
return { $set: { archived: true, archivedAt: new Date() } };
|
||||
},
|
||||
|
||||
restore() {
|
||||
|
||||
+62
-3
@@ -338,6 +338,13 @@ Users.attachSchema(
|
||||
type: Number,
|
||||
optional: true,
|
||||
},
|
||||
importUsernames: {
|
||||
/**
|
||||
* username for imported
|
||||
*/
|
||||
type: [String],
|
||||
optional: true,
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -433,7 +440,18 @@ if (Meteor.isClient) {
|
||||
});
|
||||
}
|
||||
|
||||
Users.parseImportUsernames = usernamesString => {
|
||||
return usernamesString.trim().split(new RegExp('\\s*[,;]\\s*'));
|
||||
};
|
||||
|
||||
Users.helpers({
|
||||
importUsernamesString() {
|
||||
if (this.importUsernames) {
|
||||
return this.importUsernames.join(', ');
|
||||
}
|
||||
return '';
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
{ 'members.userId': this._id },
|
||||
@@ -779,7 +797,15 @@ Meteor.methods({
|
||||
|
||||
if (Meteor.isServer) {
|
||||
Meteor.methods({
|
||||
setCreateUser(fullname, username, password, isAdmin, isActive, email) {
|
||||
setCreateUser(
|
||||
fullname,
|
||||
username,
|
||||
password,
|
||||
isAdmin,
|
||||
isActive,
|
||||
email,
|
||||
importUsernames,
|
||||
) {
|
||||
if (Meteor.user() && Meteor.user().isAdmin) {
|
||||
check(fullname, String);
|
||||
check(username, String);
|
||||
@@ -787,6 +813,7 @@ if (Meteor.isServer) {
|
||||
check(isAdmin, String);
|
||||
check(isActive, String);
|
||||
check(email, String);
|
||||
check(importUsernames, Array);
|
||||
|
||||
const nUsersWithUsername = Users.find({ username }).count();
|
||||
const nUsersWithEmail = Users.find({ email }).count();
|
||||
@@ -803,10 +830,10 @@ if (Meteor.isServer) {
|
||||
email: email.toLowerCase(),
|
||||
from: 'admin',
|
||||
});
|
||||
user = Users.findOne(username) || Users.findOne({ username });
|
||||
const user = Users.findOne(username) || Users.findOne({ username });
|
||||
if (user) {
|
||||
Users.update(user._id, {
|
||||
$set: { 'profile.fullname': fullname },
|
||||
$set: { 'profile.fullname': fullname, importUsernames },
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1733,6 +1760,38 @@ if (Meteor.isServer) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @operation create_user_token
|
||||
*
|
||||
* @summary Create a user token
|
||||
*
|
||||
* @description Only the admin user (the first user) can call the REST API.
|
||||
*
|
||||
* @param {string} userId the ID of the user to create token for.
|
||||
* @return_type {_id: string}
|
||||
*/
|
||||
JsonRoutes.add('POST', '/api/createtoken/:userId', function(req, res) {
|
||||
try {
|
||||
Authentication.checkUserId(req.userId);
|
||||
const id = req.params.userId;
|
||||
const token = Accounts._generateStampedLoginToken();
|
||||
Accounts._insertLoginToken(id, token);
|
||||
|
||||
JsonRoutes.sendResult(res, {
|
||||
code: 200,
|
||||
data: {
|
||||
_id: id,
|
||||
authToken: token.token,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
JsonRoutes.sendResult(res, {
|
||||
code: 200,
|
||||
data: error,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default Users;
|
||||
Generated
+7
-7
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v4.91.0",
|
||||
"version": "v4.92.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -819,9 +819,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"ajv": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.3.tgz",
|
||||
"integrity": "sha512-R50QRlXSxqXcQP5SvKUrw8VZeypvo12i2IX0EeR5PiZ7bEKeHWgzgo264LDadUsCU42lTJVhFikTqJwNeH34gQ==",
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-7.0.4.tgz",
|
||||
"integrity": "sha512-xzzzaqgEQfmuhbhAoqjJ8T/1okb6gAzXn/eQRNpAN1AEUoHJTNF9xCDRTtf/s3SKldtZfa+RJeTs+BQq+eZ/sw==",
|
||||
"requires": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
@@ -4324,9 +4324,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"mongodb": {
|
||||
"version": "3.6.3",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.3.tgz",
|
||||
"integrity": "sha512-rOZuR0QkodZiM+UbQE5kDsJykBqWi0CL4Ec2i1nrGrUI3KO11r6Fbxskqmq3JK2NH7aW4dcccBuUujAP0ERl5w==",
|
||||
"version": "3.6.4",
|
||||
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.6.4.tgz",
|
||||
"integrity": "sha512-Y+Ki9iXE9jI+n9bVtbTOOdK0B95d6wVGSucwtBkvQ+HIvVdTCfpVRp01FDC24uhC/Q2WXQ8Lpq3/zwtB5Op9Qw==",
|
||||
"requires": {
|
||||
"bl": "^2.2.1",
|
||||
"bson": "^1.1.4",
|
||||
|
||||
+3
-3
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "wekan",
|
||||
"version": "v4.91.0",
|
||||
"version": "v4.92.0",
|
||||
"description": "Open-Source kanban",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -57,7 +57,7 @@
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@root/request": "^1.7.0",
|
||||
"ajv": "^7.0.3",
|
||||
"ajv": "^7.0.4",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"bcrypt": "^5.0.0",
|
||||
"bson": "^4.2.2",
|
||||
@@ -72,7 +72,7 @@
|
||||
"markdown-it": "^12.0.4",
|
||||
"markdown-it-emoji": "^2.0.0",
|
||||
"meteor-node-stubs": "^1.0.1",
|
||||
"mongodb": "^3.6.3",
|
||||
"mongodb": "^3.6.4",
|
||||
"os": "^0.1.1",
|
||||
"page": "^1.11.5",
|
||||
"papaparse": "^5.3.0",
|
||||
|
||||
+265
-5
@@ -1524,7 +1524,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
|
||||
<ul class="toc-list-h1">
|
||||
|
||||
<li>
|
||||
<a href="#wekan-rest-api" class="toc-h1 toc-link" data-title="Wekan REST API v4.91">Wekan REST API v4.91</a>
|
||||
<a href="#wekan-rest-api" class="toc-h1 toc-link" data-title="Wekan REST API v4.92">Wekan REST API v4.92</a>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -1854,6 +1854,11 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#create_user_token" class="toc-h2 toc-link" data-title="create_user_token">create_user_token</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="#get_current_user" class="toc-h2 toc-link" data-title="get_current_user">get_current_user</a>
|
||||
|
||||
@@ -2037,7 +2042,7 @@ var n=this.pipeline.run(e.tokenizer(t)),r=new e.Vector,i=[],o=this._fields.reduc
|
||||
<div class="page-wrapper">
|
||||
<div class="dark-box"></div>
|
||||
<div class="content">
|
||||
<h1 id="wekan-rest-api">Wekan REST API v4.91</h1>
|
||||
<h1 id="wekan-rest-api">Wekan REST API v4.92</h1>
|
||||
<blockquote>
|
||||
<p>Scroll down for code samples, example requests and responses. Select a language for code samples from the tabs above or the mobile navigation menu.</p>
|
||||
</blockquote>
|
||||
@@ -3282,6 +3287,7 @@ System.out.println(response.toString());
|
||||
<span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"slug"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"archived"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archivedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"modifiedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"stars"</span>: <span class="hljs-number">0</span>,
|
||||
@@ -8086,6 +8092,7 @@ System.out.println(response.toString());
|
||||
<pre class="highlight tab tab-json"><code>{
|
||||
<span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"archived"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archivedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"parentId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"listId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"swimlaneId"</span>: <span class="hljs-string">"string"</span>,
|
||||
@@ -12192,6 +12199,7 @@ System.out.println(response.toString());
|
||||
<span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"starred"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archived"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archivedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"boardId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"swimlaneId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
@@ -12968,6 +12976,209 @@ System.out.println(response.toString());
|
||||
To perform this operation, you must be authenticated by means of one of the following methods:
|
||||
UserSecurity
|
||||
</aside>
|
||||
<h2 id="create_user_token">create_user_token</h2>
|
||||
<p><a id="opIdcreate_user_token"></a></p>
|
||||
<blockquote>
|
||||
<p>Code samples</p>
|
||||
</blockquote>
|
||||
<pre class="highlight tab tab-shell"><code><span class="hljs-comment"># You can also use wget</span>
|
||||
curl -X POST /api/createtoken/{user} \
|
||||
-H <span class="hljs-string">'Accept: application/json'</span> \
|
||||
-H <span class="hljs-string">'Authorization: API_KEY'</span>
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-http"><code><span class="hljs-keyword">POST</span> <span class="hljs-string">/api/createtoken/{user}</span> HTTP/1.1
|
||||
|
||||
<span class="http"><span class="hljs-attribute">Accept</span>: application/json
|
||||
|
||||
<span class="undefined"></span></span></code></pre>
|
||||
<pre class="highlight tab tab-javascript"><code><span class="hljs-keyword">var</span> headers = {
|
||||
<span class="hljs-string">'Accept'</span>:<span class="hljs-string">'application/json'</span>,
|
||||
<span class="hljs-string">'Authorization'</span>:<span class="hljs-string">'API_KEY'</span>
|
||||
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
<span class="hljs-attr">url</span>: <span class="hljs-string">'/api/createtoken/{user}'</span>,
|
||||
<span class="hljs-attr">method</span>: <span class="hljs-string">'post'</span>,
|
||||
|
||||
<span class="hljs-attr">headers</span>: headers,
|
||||
<span class="hljs-attr">success</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>) </span>{
|
||||
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(data));
|
||||
}
|
||||
})
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-javascript--nodejs"><code><span class="hljs-keyword">const</span> fetch = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node-fetch'</span>);
|
||||
|
||||
<span class="hljs-keyword">const</span> headers = {
|
||||
<span class="hljs-string">'Accept'</span>:<span class="hljs-string">'application/json'</span>,
|
||||
<span class="hljs-string">'Authorization'</span>:<span class="hljs-string">'API_KEY'</span>
|
||||
|
||||
};
|
||||
|
||||
fetch(<span class="hljs-string">'/api/createtoken/{user}'</span>,
|
||||
{
|
||||
<span class="hljs-attr">method</span>: <span class="hljs-string">'POST'</span>,
|
||||
|
||||
<span class="hljs-attr">headers</span>: headers
|
||||
})
|
||||
.then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">res</span>) </span>{
|
||||
<span class="hljs-keyword">return</span> res.json();
|
||||
}).then(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">body</span>) </span>{
|
||||
<span class="hljs-built_in">console</span>.log(body);
|
||||
});
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-ruby"><code><span class="hljs-keyword">require</span> <span class="hljs-string">'rest-client'</span>
|
||||
<span class="hljs-keyword">require</span> <span class="hljs-string">'json'</span>
|
||||
|
||||
headers = {
|
||||
<span class="hljs-string">'Accept'</span> => <span class="hljs-string">'application/json'</span>,
|
||||
<span class="hljs-string">'Authorization'</span> => <span class="hljs-string">'API_KEY'</span>
|
||||
}
|
||||
|
||||
result = RestClient.post <span class="hljs-string">'/api/createtoken/{user}'</span>,
|
||||
<span class="hljs-symbol">params:</span> {
|
||||
}, <span class="hljs-symbol">headers:</span> headers
|
||||
|
||||
p JSON.parse(result)
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-python"><code><span class="hljs-keyword">import</span> requests
|
||||
headers = {
|
||||
<span class="hljs-string">'Accept'</span>: <span class="hljs-string">'application/json'</span>,
|
||||
<span class="hljs-string">'Authorization'</span>: <span class="hljs-string">'API_KEY'</span>
|
||||
}
|
||||
|
||||
r = requests.post(<span class="hljs-string">'/api/createtoken/{user}'</span>, params={
|
||||
|
||||
}, headers = headers)
|
||||
|
||||
<span class="hljs-keyword">print</span> r.json()
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-java"><code>URL obj = <span class="hljs-keyword">new</span> URL(<span class="hljs-string">"/api/createtoken/{user}"</span>);
|
||||
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
|
||||
con.setRequestMethod(<span class="hljs-string">"POST"</span>);
|
||||
<span class="hljs-keyword">int</span> responseCode = con.getResponseCode();
|
||||
BufferedReader in = <span class="hljs-keyword">new</span> BufferedReader(
|
||||
<span class="hljs-keyword">new</span> InputStreamReader(con.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = <span class="hljs-keyword">new</span> StringBuffer();
|
||||
<span class="hljs-keyword">while</span> ((inputLine = in.readLine()) != <span class="hljs-keyword">null</span>) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
System.out.println(response.toString());
|
||||
|
||||
</code></pre>
|
||||
<pre class="highlight tab tab-go"><code><span class="hljs-keyword">package</span> main
|
||||
|
||||
<span class="hljs-keyword">import</span> (
|
||||
<span class="hljs-string">"bytes"</span>
|
||||
<span class="hljs-string">"net/http"</span>
|
||||
)
|
||||
|
||||
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
|
||||
|
||||
headers := <span class="hljs-keyword">map</span>[<span class="hljs-keyword">string</span>][]<span class="hljs-keyword">string</span>{
|
||||
<span class="hljs-string">"Accept"</span>: []<span class="hljs-keyword">string</span>{<span class="hljs-string">"application/json"</span>},
|
||||
<span class="hljs-string">"Authorization"</span>: []<span class="hljs-keyword">string</span>{<span class="hljs-string">"API_KEY"</span>},
|
||||
|
||||
}
|
||||
|
||||
data := bytes.NewBuffer([]<span class="hljs-keyword">byte</span>{jsonReq})
|
||||
req, err := http.NewRequest(<span class="hljs-string">"POST"</span>, <span class="hljs-string">"/api/createtoken/{user}"</span>, data)
|
||||
req.Header = headers
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
<span class="hljs-comment">// ...</span>
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
<p><code>POST /api/createtoken/{user}</code></p>
|
||||
<p><em>Create a user token</em></p>
|
||||
<p>Only the admin user (the first user) can call the REST API.</p>
|
||||
<h3 id="create_user_token-parameters">Parameters</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>In</th>
|
||||
<th>Type</th>
|
||||
<th>Required</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>user</td>
|
||||
<td>path</td>
|
||||
<td>string</td>
|
||||
<td>true</td>
|
||||
<td>the ID of the user to create token for.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h4 id="detailed-descriptions">Detailed descriptions</h4>
|
||||
<p><strong>user</strong>: the ID of the user to create token for.</p>
|
||||
<blockquote>
|
||||
<p>Example responses</p>
|
||||
</blockquote>
|
||||
<blockquote>
|
||||
<p>200 Response</p>
|
||||
</blockquote>
|
||||
<pre class="highlight tab tab-json"><code>{
|
||||
<span class="hljs-attr">"_id"</span>: <span class="hljs-string">"string"</span>
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="create_user_token-responses">Responses</h3>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Status</th>
|
||||
<th>Meaning</th>
|
||||
<th>Description</th>
|
||||
<th>Schema</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>200</td>
|
||||
<td><a href="https://tools.ietf.org/html/rfc7231#section-6.3.1">OK</a></td>
|
||||
<td>200 response</td>
|
||||
<td>Inline</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 id="create_user_token-responseschema">Response Schema</h3>
|
||||
<p>Status Code <strong>200</strong></p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Type</th>
|
||||
<th>Required</th>
|
||||
<th>Restrictions</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>» _id</td>
|
||||
<td>string</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>none</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<aside class="warning">
|
||||
To perform this operation, you must be authenticated by means of one of the following methods:
|
||||
UserSecurity
|
||||
</aside>
|
||||
<h2 id="get_current_user">get_current_user</h2>
|
||||
<p><a id="opIdget_current_user"></a></p>
|
||||
<blockquote>
|
||||
@@ -13148,7 +13359,10 @@ System.out.println(response.toString());
|
||||
<span class="hljs-attr">"sessionData"</span>: {
|
||||
<span class="hljs-attr">"totalHits"</span>: <span class="hljs-number">0</span>,
|
||||
<span class="hljs-attr">"lastHit"</span>: <span class="hljs-number">0</span>
|
||||
}
|
||||
},
|
||||
<span class="hljs-attr">"importUsernames"</span>: [
|
||||
<span class="hljs-string">"string"</span>
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="get_current_user-responses">Responses</h3>
|
||||
@@ -13809,7 +14023,10 @@ System.out.println(response.toString());
|
||||
<span class="hljs-attr">"sessionData"</span>: {
|
||||
<span class="hljs-attr">"totalHits"</span>: <span class="hljs-number">0</span>,
|
||||
<span class="hljs-attr">"lastHit"</span>: <span class="hljs-number">0</span>
|
||||
}
|
||||
},
|
||||
<span class="hljs-attr">"importUsernames"</span>: [
|
||||
<span class="hljs-string">"string"</span>
|
||||
]
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="get_user-responses">Responses</h3>
|
||||
@@ -14892,6 +15109,7 @@ System.out.println(response.toString());
|
||||
<pre class="highlight tab tab-json"><code>{
|
||||
<span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"archived"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archivedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"boardId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"sort"</span>: <span class="hljs-number">0</span>,
|
||||
@@ -15142,6 +15360,7 @@ UserSecurity
|
||||
<span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"slug"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"archived"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archivedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"modifiedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"stars"</span>: <span class="hljs-number">0</span>,
|
||||
@@ -15231,6 +15450,13 @@ UserSecurity
|
||||
<td>Is the board archived?</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>archivedAt</td>
|
||||
<td>string|null</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>Latest archiving time of the board</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>createdAt</td>
|
||||
<td>string</td>
|
||||
<td>true</td>
|
||||
@@ -15880,6 +16106,7 @@ UserSecurity
|
||||
<pre class="highlight tab tab-json"><code>{
|
||||
<span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"archived"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archivedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"parentId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"listId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"swimlaneId"</span>: <span class="hljs-string">"string"</span>,
|
||||
@@ -15957,6 +16184,13 @@ UserSecurity
|
||||
<td>is the card archived</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>archivedAt</td>
|
||||
<td>string|null</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>latest archiving date</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>parentId</td>
|
||||
<td>string|null</td>
|
||||
<td>false</td>
|
||||
@@ -16787,6 +17021,7 @@ UserSecurity
|
||||
<span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"starred"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archived"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archivedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"boardId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"swimlaneId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
@@ -16838,6 +17073,13 @@ UserSecurity
|
||||
<td>is the list archived</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>archivedAt</td>
|
||||
<td>string|null</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>latest archiving date</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>boardId</td>
|
||||
<td>string</td>
|
||||
<td>true</td>
|
||||
@@ -17058,6 +17300,7 @@ UserSecurity
|
||||
<pre class="highlight tab tab-json"><code>{
|
||||
<span class="hljs-attr">"title"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"archived"</span>: <span class="hljs-literal">true</span>,
|
||||
<span class="hljs-attr">"archivedAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"boardId"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
|
||||
<span class="hljs-attr">"sort"</span>: <span class="hljs-number">0</span>,
|
||||
@@ -17096,6 +17339,13 @@ UserSecurity
|
||||
<td>is the swimlane archived?</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>archivedAt</td>
|
||||
<td>string|null</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>latest archiving date of the swimlane</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>boardId</td>
|
||||
<td>string</td>
|
||||
<td>true</td>
|
||||
@@ -17305,7 +17555,10 @@ UserSecurity
|
||||
<span class="hljs-attr">"sessionData"</span>: {
|
||||
<span class="hljs-attr">"totalHits"</span>: <span class="hljs-number">0</span>,
|
||||
<span class="hljs-attr">"lastHit"</span>: <span class="hljs-number">0</span>
|
||||
}
|
||||
},
|
||||
<span class="hljs-attr">"importUsernames"</span>: [
|
||||
<span class="hljs-string">"string"</span>
|
||||
]
|
||||
}
|
||||
|
||||
</code></pre>
|
||||
@@ -17406,6 +17659,13 @@ UserSecurity
|
||||
<td>none</td>
|
||||
<td>profile settings</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>importUsernames</td>
|
||||
<td>[string]|null</td>
|
||||
<td>false</td>
|
||||
<td>none</td>
|
||||
<td>username for imported</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2 id="tocsusersemails">UsersEmails</h2>
|
||||
|
||||
+60
-1
@@ -1,7 +1,7 @@
|
||||
swagger: '2.0'
|
||||
info:
|
||||
title: Wekan REST API
|
||||
version: v4.91
|
||||
version: v4.92
|
||||
description: |
|
||||
The REST API allows you to control and extend Wekan with ease.
|
||||
|
||||
@@ -2136,6 +2136,37 @@ paths:
|
||||
type: string
|
||||
listId:
|
||||
type: string
|
||||
/api/createtoken/{user}:
|
||||
post:
|
||||
operationId: create_user_token
|
||||
summary: Create a user token
|
||||
description: |
|
||||
Only the admin user (the first user) can call the REST API.
|
||||
tags:
|
||||
- Users
|
||||
consumes:
|
||||
- multipart/form-data
|
||||
- application/json
|
||||
parameters:
|
||||
- name: user
|
||||
in: path
|
||||
description: |
|
||||
the ID of the user to create token for.
|
||||
type: string
|
||||
required: true
|
||||
produces:
|
||||
- application/json
|
||||
security:
|
||||
- UserSecurity: []
|
||||
responses:
|
||||
'200':
|
||||
description: |-
|
||||
200 response
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
_id:
|
||||
type: string
|
||||
/api/user:
|
||||
get:
|
||||
operationId: get_current_user
|
||||
@@ -2361,6 +2392,11 @@ definitions:
|
||||
description: |
|
||||
Is the board archived?
|
||||
type: boolean
|
||||
archivedAt:
|
||||
description: |
|
||||
Latest archiving time of the board
|
||||
type: string
|
||||
x-nullable: true
|
||||
createdAt:
|
||||
description: |
|
||||
Creation time of the board
|
||||
@@ -2702,6 +2738,11 @@ definitions:
|
||||
description: |
|
||||
is the card archived
|
||||
type: boolean
|
||||
archivedAt:
|
||||
description: |
|
||||
latest archiving date
|
||||
type: string
|
||||
x-nullable: true
|
||||
parentId:
|
||||
description: |
|
||||
ID of the parent card
|
||||
@@ -3122,6 +3163,11 @@ definitions:
|
||||
description: |
|
||||
is the list archived
|
||||
type: boolean
|
||||
archivedAt:
|
||||
description: |
|
||||
latest archiving date
|
||||
type: string
|
||||
x-nullable: true
|
||||
boardId:
|
||||
description: |
|
||||
the board associated to this list
|
||||
@@ -3224,6 +3270,11 @@ definitions:
|
||||
description: |
|
||||
is the swimlane archived?
|
||||
type: boolean
|
||||
archivedAt:
|
||||
description: |
|
||||
latest archiving date of the swimlane
|
||||
type: string
|
||||
x-nullable: true
|
||||
boardId:
|
||||
description: |
|
||||
the ID of the board the swimlane is attached to
|
||||
@@ -3346,6 +3397,14 @@ definitions:
|
||||
profile settings
|
||||
$ref: "#/definitions/UsersSessiondata"
|
||||
x-nullable: true
|
||||
importUsernames:
|
||||
description: |
|
||||
username for imported
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
x-nullable: true
|
||||
x-nullable: true
|
||||
required:
|
||||
- createdAt
|
||||
- modifiedAt
|
||||
|
||||
@@ -22,10 +22,10 @@ const pkgdef :Spk.PackageDefinition = (
|
||||
appTitle = (defaultText = "Wekan"),
|
||||
# The name of the app as it is displayed to the user.
|
||||
|
||||
appVersion = 491,
|
||||
appVersion = 492,
|
||||
# Increment this for every release.
|
||||
|
||||
appMarketingVersion = (defaultText = "4.91.0~2021-01-29"),
|
||||
appMarketingVersion = (defaultText = "4.92.0~2021-02-03"),
|
||||
# Human-readable presentation of the app version.
|
||||
|
||||
minUpgradableAppVersion = 0,
|
||||
|
||||
@@ -63,8 +63,11 @@ Meteor.publish('archivedBoards', function() {
|
||||
archived: 1,
|
||||
slug: 1,
|
||||
title: 1,
|
||||
createdAt: 1,
|
||||
modifiedAt: 1,
|
||||
archivedAt: 1,
|
||||
},
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -200,11 +200,7 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) {
|
||||
comments: [],
|
||||
};
|
||||
|
||||
this.colorMap = {};
|
||||
for (const color of Boards.simpleSchema()._schema['labels.$.color']
|
||||
.allowedValues) {
|
||||
this.colorMap[TAPi18n.__(`color-${color}`)] = color;
|
||||
}
|
||||
this.colorMap = Boards.colorMap();
|
||||
}
|
||||
|
||||
hasErrors() {
|
||||
@@ -234,7 +230,11 @@ Meteor.publish('globalSearch', function(sessionId, queryParams) {
|
||||
});
|
||||
});
|
||||
this.notFound.labels.forEach(label => {
|
||||
messages.push({ tag: 'label-not-found', value: label, color: true });
|
||||
messages.push({
|
||||
tag: 'label-not-found',
|
||||
value: label,
|
||||
color: Boards.labelColors().includes(label),
|
||||
});
|
||||
});
|
||||
this.notFound.users.forEach(user => {
|
||||
messages.push({ tag: 'user-username-not-found', value: user });
|
||||
|
||||
@@ -20,6 +20,7 @@ Meteor.publish('people', function(query, limit) {
|
||||
createdAt: 1,
|
||||
loginDisabled: 1,
|
||||
authenticationMethod: 1,
|
||||
importUsernames: 1,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -4,8 +4,18 @@ Meteor.publish('user-miniprofile', function(usernames) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('usernames:', usernames);
|
||||
return Users.find(
|
||||
{ username: { $in: usernames } },
|
||||
{ fields: Users.safeFields },
|
||||
{
|
||||
$or: [
|
||||
{ username: { $in: usernames } },
|
||||
{ importUsernames: { $in: usernames } },
|
||||
],
|
||||
},
|
||||
{
|
||||
fields: {
|
||||
...Users.safeFields,
|
||||
importUsernames: 1,
|
||||
},
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: OpenPGP.js v4.10.8
|
||||
Comment: https://openpgpjs.org
|
||||
|
||||
xjMEX3HbABYJKwYBBAHaRw8BAQdAQ2UBWCK1H3/z7gMgwVudRL+NlwJVCPw+
|
||||
Vsp9PGSLh9jNJ3N1cHBvcnRAd2VrYW4udGVhbSA8c3VwcG9ydEB3ZWthbi50
|
||||
ZWFtPsKPBBAWCgAgBQJfcdsABgsJBwgDAgQVCAoCBBYCAQACGQECGwMCHgEA
|
||||
IQkQRkG8ZpPn6f4WIQRI5gPihwJLiXfveDBGQbxmk+fp/kCXAQD/JXsgVq4d
|
||||
9sKmYDGHpCaIfsO//6cmiCGz3Mf5SDc0ygD/WpJO31Fyu6pfr3nWe4n50H93
|
||||
lXXz937+K1bB9rfqugDOOARfcdsAEgorBgEEAZdVAQUBAQdALydXPub/n7hx
|
||||
8qYjZa2tzBvcz5KkdnIxOoB+vaQZFQwDAQgHwngEGBYIAAkFAl9x2wACGwwA
|
||||
IQkQRkG8ZpPn6f4WIQRI5gPihwJLiXfveDBGQbxmk+fp/uyXAQCRLPksHCJ6
|
||||
RTl7HrtSS9lkeOmh32u+Rnjijn970PYIIQEAiGgXoJGBTzyVil9aPeqfWFK+
|
||||
0hvTsnNY3JT3K84OmQQ=
|
||||
=SNk3
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
Reference in new issue
Block a user