summaryrefslogtreecommitdiffstats
path: root/models
diff options
context:
space:
mode:
authorRomulus Urakagi Tsai <urakagi@gmail.com>2020-02-13 09:02:26 +0000
committerRomulus Urakagi Tsai <urakagi@gmail.com>2020-02-13 09:02:26 +0000
commit4b196d537896f39fb76090020cb5851a699546eb (patch)
tree28e2e025ce90645ed360bb8c26ab39e6f40214e4 /models
parentb34ed58289a3dae5838d3b621260938a3ecf52d5 (diff)
parent3fcde252f705f9527f7190517082a047714a4eec (diff)
downloadwekan-4b196d537896f39fb76090020cb5851a699546eb.tar.gz
wekan-4b196d537896f39fb76090020cb5851a699546eb.tar.bz2
wekan-4b196d537896f39fb76090020cb5851a699546eb.zip
Merge branch 'master' of https://github.com/wekan/wekan into lib-change
Diffstat (limited to 'models')
-rw-r--r--models/accountSettings.js12
-rw-r--r--models/boards.js283
-rw-r--r--models/cards.js16
-rw-r--r--models/checklists.js11
-rw-r--r--models/export.js18
-rw-r--r--models/settings.js8
-rw-r--r--models/swimlanes.js8
-rw-r--r--models/users.js10
-rw-r--r--models/wekanCreator.js2
9 files changed, 342 insertions, 26 deletions
diff --git a/models/accountSettings.js b/models/accountSettings.js
index f61614b8..a20303f5 100644
--- a/models/accountSettings.js
+++ b/models/accountSettings.js
@@ -82,4 +82,16 @@ if (Meteor.isServer) {
});
}
+AccountSettings.helpers({
+ allowEmailChange() {
+ return AccountSettings.findOne('accounts-allowEmailChange').booleanValue;
+ },
+ allowUserNameChange() {
+ return AccountSettings.findOne('accounts-allowUserNameChange').booleanValue;
+ },
+ allowUserDelete() {
+ return AccountSettings.findOne('accounts-allowUserDelete').booleanValue;
+ },
+});
+
export default AccountSettings;
diff --git a/models/boards.js b/models/boards.js
index 85a7558c..8862f301 100644
--- a/models/boards.js
+++ b/models/boards.js
@@ -185,6 +185,7 @@ Boards.attachSchema(
isActive: true,
isNoComments: false,
isCommentOnly: false,
+ isWorker: false,
},
];
}
@@ -222,6 +223,13 @@ Boards.attachSchema(
type: Boolean,
optional: true,
},
+ 'members.$.isWorker': {
+ /**
+ * Is the member only allowed to move card, assign himself to card and comment
+ */
+ type: Boolean,
+ optional: true,
+ },
permission: {
/**
* visibility of the board
@@ -270,6 +278,7 @@ Boards.attachSchema(
optional: true,
defaultValue: null,
},
+
subtasksDefaultListId: {
/**
* The default List ID assigned to subtasks.
@@ -278,6 +287,19 @@ Boards.attachSchema(
optional: true,
defaultValue: null,
},
+
+ dateSettingsDefaultBoardId: {
+ type: String,
+ optional: true,
+ defaultValue: null,
+ },
+
+ dateSettingsDefaultListId: {
+ type: String,
+ optional: true,
+ defaultValue: null,
+ },
+
allowsSubtasks: {
/**
* Does the board allows subtasks?
@@ -285,6 +307,127 @@ Boards.attachSchema(
type: Boolean,
defaultValue: true,
},
+
+ allowsAttachments: {
+ /**
+ * Does the board allows attachments?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsChecklists: {
+ /**
+ * Does the board allows checklists?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsComments: {
+ /**
+ * Does the board allows comments?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsDescriptionTitle: {
+ /**
+ * Does the board allows description title?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsDescriptionText: {
+ /**
+ * Does the board allows description text?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsActivities: {
+ /**
+ * Does the board allows comments?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsLabels: {
+ /**
+ * Does the board allows labels?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsAssignee: {
+ /**
+ * Does the board allows assignee?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsMembers: {
+ /**
+ * Does the board allows members?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsRequestedBy: {
+ /**
+ * Does the board allows requested by?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsAssignedBy: {
+ /**
+ * Does the board allows requested by?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsReceivedDate: {
+ /**
+ * Does the board allows received date?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsStartDate: {
+ /**
+ * Does the board allows start date?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsEndDate: {
+ /**
+ * Does the board allows end date?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
+ allowsDueDate: {
+ /**
+ * Does the board allows due date?
+ */
+ type: Boolean,
+ defaultValue: true,
+ },
+
presentParentTask: {
/**
* Controls how to present the parent task:
@@ -409,8 +552,12 @@ Boards.helpers({
},
lists() {
- const enabled = Meteor.user().hasSortBy();
- return enabled ? this.newestLists() : this.draggableLists();
+ //currentUser = Meteor.user();
+ //if (currentUser) {
+ // enabled = Meteor.user().hasSortBy();
+ //}
+ //return enabled ? this.newestLists() : this.draggableLists();
+ return this.draggableLists();
},
newestLists() {
@@ -534,6 +681,7 @@ Boards.helpers({
isActive: true,
isAdmin: false,
isNoComments: true,
+ isWorker: false,
});
},
@@ -543,6 +691,17 @@ Boards.helpers({
isActive: true,
isAdmin: false,
isCommentOnly: true,
+ isWorker: false,
+ });
+ },
+
+ hasWorker(memberId) {
+ return !!_.findWhere(this.members, {
+ userId: memberId,
+ isActive: true,
+ isAdmin: false,
+ isCommentOnly: false,
+ isWorker: true,
});
},
@@ -686,6 +845,39 @@ Boards.helpers({
return Boards.findOne(this.getDefaultSubtasksBoardId());
},
+ //Date Settings option such as received date, start date and so on.
+ getDefaultDateSettingsBoardId() {
+ if (
+ this.dateSettingsDefaultBoardId === null ||
+ this.dateSettingsDefaultBoardId === undefined
+ ) {
+ this.dateSettingsDefaultBoardId = Boards.insert({
+ title: `^${this.title}^`,
+ permission: this.permission,
+ members: this.members,
+ color: this.color,
+ description: TAPi18n.__('default-dates-board', {
+ board: this.title,
+ }),
+ });
+
+ Swimlanes.insert({
+ title: TAPi18n.__('default'),
+ boardId: this.dateSettingsDefaultBoardId,
+ });
+ Boards.update(this._id, {
+ $set: {
+ dateSettingsDefaultBoardId: this.dateSettingsDefaultBoardId,
+ },
+ });
+ }
+ return this.dateSettingsDefaultBoardId;
+ },
+
+ getDefaultDateSettingsBoard() {
+ return Boards.findOne(this.getDefaultDateSettingsBoardId());
+ },
+
getDefaultSubtasksListId() {
if (
this.subtasksDefaultListId === null ||
@@ -704,6 +896,24 @@ Boards.helpers({
return Lists.findOne(this.getDefaultSubtasksListId());
},
+ getDefaultDateSettingsListId() {
+ if (
+ this.dateSettingsDefaultListId === null ||
+ this.dateSettingsDefaultListId === undefined
+ ) {
+ this.dateSettingsDefaultListId = Lists.insert({
+ title: TAPi18n.__('queue'),
+ boardId: this._id,
+ });
+ this.setDateSettingsDefaultListId(this.dateSettingsDefaultListId);
+ }
+ return this.dateSettingsDefaultListId;
+ },
+
+ getDefaultDateSettingsList() {
+ return Lists.findOne(this.getDefaultDateSettingsListId());
+ },
+
getDefaultSwimline() {
let result = Swimlanes.findOne({ boardId: this._id });
if (result === undefined) {
@@ -845,6 +1055,7 @@ Boards.mutations({
isActive: true,
isNoComments: false,
isCommentOnly: false,
+ isWorker: false,
},
},
};
@@ -877,6 +1088,7 @@ Boards.mutations({
isAdmin,
isNoComments,
isCommentOnly,
+ isWorker,
currentUserId = Meteor.userId(),
) {
const memberIndex = this.memberIndex(memberId);
@@ -890,6 +1102,7 @@ Boards.mutations({
[`members.${memberIndex}.isAdmin`]: isAdmin,
[`members.${memberIndex}.isNoComments`]: isNoComments,
[`members.${memberIndex}.isCommentOnly`]: isCommentOnly,
+ [`members.${memberIndex}.isWorker`]: isWorker,
},
};
},
@@ -898,6 +1111,66 @@ Boards.mutations({
return { $set: { allowsSubtasks } };
},
+ setAllowsMembers(allowsMembers) {
+ return { $set: { allowsMembers } };
+ },
+
+ setAllowsChecklists(allowsChecklists) {
+ return { $set: { allowsChecklists } };
+ },
+
+ setAllowsAssignee(allowsAssignee) {
+ return { $set: { allowsAssignee } };
+ },
+
+ setAllowsAssignedBy(allowsAssignedBy) {
+ return { $set: { allowsAssignedBy } };
+ },
+
+ setAllowsRequestedBy(allowsRequestedBy) {
+ return { $set: { allowsRequestedBy } };
+ },
+
+ setAllowsAttachments(allowsAttachments) {
+ return { $set: { allowsAttachments } };
+ },
+
+ setAllowsLabels(allowsLabels) {
+ return { $set: { allowsLabels } };
+ },
+
+ setAllowsComments(allowsComments) {
+ return { $set: { allowsComments } };
+ },
+
+ setAllowsDescriptionTitle(allowsDescriptionTitle) {
+ return { $set: { allowsDescriptionTitle } };
+ },
+
+ setAllowsDescriptionText(allowsDescriptionText) {
+ return { $set: { allowsDescriptionText } };
+ },
+
+ setAllowsActivities(allowsActivities) {
+ return { $set: { allowsActivities } };
+ },
+
+ setAllowsReceivedDate(allowsReceivedDate) {
+ return { $set: { allowsReceivedDate } };
+ },
+
+ setAllowsStartDate(allowsStartDate) {
+ return { $set: { allowsStartDate } };
+ },
+
+ setAllowsEndDate(allowsEndDate) {
+ return { $set: { allowsEndDate } };
+ },
+
+ setAllowsDueDate(allowsDueDate) {
+ return { $set: { allowsDueDate } };
+ },
+
setSubtasksDefaultBoardId(subtasksDefaultBoardId) {
return { $set: { subtasksDefaultBoardId } };
},
@@ -1277,6 +1550,7 @@ if (Meteor.isServer) {
* @param {boolean} [isActive] is the board active (default true)
* @param {boolean} [isNoComments] disable comments (default false)
* @param {boolean} [isCommentOnly] only enable comments (default false)
+ * @param {boolean} [isWorker] only move cards, assign himself to card and comment (default false)
* @param {string} [permission] "private" board <== Set to "public" if you
* want public Wekan board
* @param {string} [color] the color of the board
@@ -1296,6 +1570,7 @@ if (Meteor.isServer) {
isActive: req.body.isActive || true,
isNoComments: req.body.isNoComments || false,
isCommentOnly: req.body.isCommentOnly || false,
+ isWorker: req.body.isWorker || false,
},
],
permission: req.body.permission || 'private',
@@ -1399,6 +1674,7 @@ if (Meteor.isServer) {
* @param {boolean} isAdmin admin capability
* @param {boolean} isNoComments NoComments capability
* @param {boolean} isCommentOnly CommentsOnly capability
+ * @param {boolean} isWorker Worker capability
*/
JsonRoutes.add('POST', '/api/boards/:boardId/members/:memberId', function(
req,
@@ -1407,7 +1683,7 @@ if (Meteor.isServer) {
try {
const boardId = req.params.boardId;
const memberId = req.params.memberId;
- const { isAdmin, isNoComments, isCommentOnly } = req.body;
+ const { isAdmin, isNoComments, isCommentOnly, isWorker } = req.body;
Authentication.checkBoardAccess(req.userId, boardId);
const board = Boards.findOne({ _id: boardId });
function isTrue(data) {
@@ -1422,6 +1698,7 @@ if (Meteor.isServer) {
isTrue(isAdmin),
isTrue(isNoComments),
isTrue(isCommentOnly),
+ isTrue(isWorker),
req.userId,
);
diff --git a/models/cards.js b/models/cards.js
index 86d22c53..fac8922c 100644
--- a/models/cards.js
+++ b/models/cards.js
@@ -205,7 +205,8 @@ Cards.attachSchema(
},
assignees: {
/**
- * who assignees of the card (user IDs)
+ * who is assignee of the card (user ID),
+ * maximum one ID of assignee in array.
*/
type: [String],
optional: true,
@@ -1996,15 +1997,22 @@ if (Meteor.isServer) {
* @param {string} description the description of the new card
* @param {string} swimlaneId the swimlane ID of the new card
* @param {string} [members] the member IDs list of the new card
- * @param {string} [assignees] the assignee IDs list of the new card
+ * @param {string} [assignees] the array of maximum one ID of assignee of the new card
* @return_type {_id: string}
*/
JsonRoutes.add('POST', '/api/boards/:boardId/lists/:listId/cards', function(
req,
res,
) {
- Authentication.checkUserId(req.userId);
+ // Check user is logged in
+ Authentication.checkLoggedIn(req.userId);
const paramBoardId = req.params.boardId;
+ // Check user has permission to add card to the board
+ const board = Boards.findOne({
+ _id: paramBoardId,
+ });
+ const addPermission = allowIsBoardMemberCommentOnly(req.userId, board);
+ Authentication.checkAdminOrCondition(req.userId, addPermission);
const paramListId = req.params.listId;
const paramParentId = req.params.parentId;
const currentCards = Cards.find(
@@ -2082,7 +2090,7 @@ if (Meteor.isServer) {
* @param {string} [labelIds] the new list of label IDs attached to the card
* @param {string} [swimlaneId] the new swimlane ID of the card
* @param {string} [members] the new list of member IDs attached to the card
- * @param {string} [assignees] the new list of assignee IDs attached to the card
+ * @param {string} [assignees] the array of maximum one ID of assignee attached to the card
* @param {string} [requestedBy] the new requestedBy field of the card
* @param {string} [assignedBy] the new assignedBy field of the card
* @param {string} [receivedAt] the new receivedAt field of the card
diff --git a/models/checklists.js b/models/checklists.js
index 3b50cda6..cf73e500 100644
--- a/models/checklists.js
+++ b/models/checklists.js
@@ -283,8 +283,15 @@ if (Meteor.isServer) {
'POST',
'/api/boards/:boardId/cards/:cardId/checklists',
function(req, res) {
- Authentication.checkUserId(req.userId);
-
+ // Check user is logged in
+ Authentication.checkLoggedIn(req.userId);
+ const paramBoardId = req.params.boardId;
+ // Check user has permission to add checklist to the card
+ const board = Boards.findOne({
+ _id: paramBoardId,
+ });
+ const addPermission = allowIsBoardMemberCommentOnly(req.userId, board);
+ Authentication.checkAdminOrCondition(req.userId, addPermission);
const paramCardId = req.params.cardId;
const id = Checklists.insert({
title: req.body.title,
diff --git a/models/export.js b/models/export.js
index c93a8bda..35e55804 100644
--- a/models/export.js
+++ b/models/export.js
@@ -24,7 +24,6 @@ if (Meteor.isServer) {
JsonRoutes.add('get', '/api/boards/:boardId/export', function(req, res) {
const boardId = req.params.boardId;
let user = null;
-
const loginToken = req.query.authToken;
if (loginToken) {
const hashToken = Accounts._hashLoginToken(loginToken);
@@ -35,7 +34,6 @@ if (Meteor.isServer) {
Authentication.checkUserId(req.userId);
user = Users.findOne({ _id: req.userId, isAdmin: true });
}
-
const exporter = new Exporter(boardId);
if (exporter.canExport(user)) {
JsonRoutes.sendResult(res, {
@@ -137,8 +135,11 @@ export class Exporter {
// [Old] for attachments we only export IDs and absolute url to original doc
// [New] Encode attachment to base64
+
const getBase64Data = function(doc, callback) {
- let buffer = new Buffer(0);
+ let buffer = Buffer.allocUnsafe(0);
+ buffer.fill(0);
+
// callback has the form function (err, res) {}
const tmpFile = path.join(
os.tmpdir(),
@@ -149,14 +150,16 @@ export class Exporter {
readStream.on('data', function(chunk) {
buffer = Buffer.concat([buffer, chunk]);
});
+
readStream.on('error', function(err) {
- callback(err, null);
+ callback(null, null);
});
readStream.on('end', function() {
// done
fs.unlink(tmpFile, () => {
//ignored
});
+
callback(null, buffer.toString('base64'));
});
readStream.pipe(tmpWriteable);
@@ -165,11 +168,14 @@ export class Exporter {
result.attachments = Attachments.find({ 'meta.boardId': byBoard.boardId })
.fetch()
.map(attachment => {
+ let filebase64 = null;
+ filebase64 = getBase64DataSync(attachment);
+
return {
_id: attachment._id,
cardId: attachment.cardId,
- // url: FlowRouter.url(attachment.url()),
- file: getBase64DataSync(attachment),
+ //url: FlowRouter.url(attachment.url()),
+ file: filebase64,
name: attachment.original.name,
type: attachment.original.type,
};
diff --git a/models/settings.js b/models/settings.js
index 8eb02c5b..63bcd7f3 100644
--- a/models/settings.js
+++ b/models/settings.js
@@ -33,14 +33,6 @@ Settings.attachSchema(
type: String,
optional: true,
},
- customHTMLafterBodyStart: {
- type: String,
- optional: true,
- },
- customHTMLbeforeBodyEnd: {
- type: String,
- optional: true,
- },
displayAuthenticationMethod: {
type: Boolean,
optional: true,
diff --git a/models/swimlanes.js b/models/swimlanes.js
index 831f1eff..aa7016f7 100644
--- a/models/swimlanes.js
+++ b/models/swimlanes.js
@@ -174,8 +174,12 @@ Swimlanes.helpers({
},
lists() {
- const enabled = Meteor.user().hasSortBy();
- return enabled ? this.newestLists() : this.draggableLists();
+ //currentUser = Meteor.user();
+ //if (currentUser) {
+ // enabled = Meteor.user().hasSortBy();
+ //}
+ //return enabled ? this.newestLists() : this.draggableLists();
+ return this.draggableLists();
},
newestLists() {
// sorted lists from newest to the oldest, by its creation date or its cards' last modification date
diff --git a/models/users.js b/models/users.js
index 83a224ba..7e23835c 100644
--- a/models/users.js
+++ b/models/users.js
@@ -352,6 +352,16 @@ if (Meteor.isClient) {
return board && board.hasCommentOnly(this._id);
},
+ isNotWorker() {
+ const board = Boards.findOne(Session.get('currentBoard'));
+ return board && board.hasMember(this._id) && !board.hasWorker(this._id);
+ },
+
+ isWorker() {
+ const board = Boards.findOne(Session.get('currentBoard'));
+ return board && board.hasWorker(this._id);
+ },
+
isBoardAdmin() {
const board = Boards.findOne(Session.get('currentBoard'));
return board && board.hasAdmin(this._id);
diff --git a/models/wekanCreator.js b/models/wekanCreator.js
index 175c156d..c5591a0b 100644
--- a/models/wekanCreator.js
+++ b/models/wekanCreator.js
@@ -443,7 +443,7 @@ export class WekanCreator {
} else if (att.file) {
// FIXME: Change to new file library
file.attachData(
- new Buffer(att.file, 'base64'),
+ Buffer.from(att.file, 'base64'),
{
type: att.type,
},