Prettier & eslint project style update

This commit is contained in:
Justin Reynolds 2019-06-28 12:52:09 -05:00
parent a0a482aa8e
commit 3eb4d2c341
116 changed files with 6216 additions and 5240 deletions

View file

@ -2,15 +2,20 @@
// server
import { AccountsLockout } from 'meteor/lucasantoniassi:accounts-lockout';
(new AccountsLockout({
new AccountsLockout({
knownUsers: {
failuresBeforeLockout: process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE || 3,
failuresBeforeLockout:
process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE || 3,
lockoutPeriod: process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD || 60,
failureWindow: process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW || 15,
failureWindow:
process.env.ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW || 15,
},
unknownUsers: {
failuresBeforeLockout: process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE || 3,
lockoutPeriod: process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD || 60,
failureWindow: process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW || 15,
failuresBeforeLockout:
process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE || 3,
lockoutPeriod:
process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD || 60,
failureWindow:
process.env.ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW || 15,
},
})).startup();
}).startup();

View file

@ -1,21 +1,20 @@
import Fiber from 'fibers';
Meteor.startup(() => {
// Node Fibers 100% CPU usage issue
// https://github.com/wekan/wekan-mongodb/issues/2#issuecomment-381453161
// https://github.com/meteor/meteor/issues/9796#issuecomment-381676326
// https://github.com/sandstorm-io/sandstorm/blob/0f1fec013fe7208ed0fd97eb88b31b77e3c61f42/shell/server/00-startup.js#L99-L129
Fiber.poolSize = 1e9;
Accounts.validateLoginAttempt(function (options) {
Accounts.validateLoginAttempt(function(options) {
const user = options.user || {};
return !user.loginDisabled;
});
Authentication = {};
Authentication.checkUserId = function (userId) {
Authentication.checkUserId = function(userId) {
if (userId === undefined) {
const error = new Meteor.Error('Unauthorized', 'Unauthorized');
error.statusCode = 401;
@ -28,13 +27,12 @@ Meteor.startup(() => {
error.statusCode = 403;
throw error;
}
};
// This will only check if the user is logged in.
// The authorization checks for the user will have to be done inside each API endpoint
Authentication.checkLoggedIn = function(userId) {
if(userId === undefined) {
if (userId === undefined) {
const error = new Meteor.Error('Unauthorized', 'Unauthorized');
error.statusCode = 401;
throw error;
@ -44,7 +42,7 @@ Meteor.startup(() => {
// An admin should be authorized to access everything, so we use a separate check for admins
// This throws an error if otherReq is false and the user is not an admin
Authentication.checkAdminOrCondition = function(userId, otherReq) {
if(otherReq) return;
if (otherReq) return;
const admin = Users.findOne({ _id: userId, isAdmin: true });
if (admin === undefined) {
const error = new Meteor.Error('Forbidden', 'Forbidden');
@ -58,14 +56,16 @@ Meteor.startup(() => {
Authentication.checkLoggedIn(userId);
const board = Boards.findOne({ _id: boardId });
const normalAccess = board.permission === 'public' || board.members.some((e) => e.userId === userId);
const normalAccess =
board.permission === 'public' ||
board.members.some(e => e.userId === userId);
Authentication.checkAdminOrCondition(userId, normalAccess);
};
if (Meteor.isServer) {
if(process.env.OAUTH2_CLIENT_ID !== '') {
ServiceConfiguration.configurations.upsert( // eslint-disable-line no-undef
if (process.env.OAUTH2_CLIENT_ID !== '') {
ServiceConfiguration.configurations.upsert(
// eslint-disable-line no-undef
{ service: 'oidc' },
{
$set: {
@ -76,15 +76,14 @@ Meteor.startup(() => {
authorizationEndpoint: process.env.OAUTH2_AUTH_ENDPOINT,
userinfoEndpoint: process.env.OAUTH2_USERINFO_ENDPOINT,
tokenEndpoint: process.env.OAUTH2_TOKEN_ENDPOINT,
idTokenWhitelistFields: process.env.OAUTH2_ID_TOKEN_WHITELIST_FIELDS || [],
idTokenWhitelistFields:
process.env.OAUTH2_ID_TOKEN_WHITELIST_FIELDS || [],
requestPermissions: process.env.OAUTH2_REQUEST_PERMISSIONS,
},
// OAUTH2_ID_TOKEN_WHITELIST_FIELDS || [],
// OAUTH2_REQUEST_PERMISSIONS || 'openid profile email',
}
},
);
}
}
});

View file

@ -1,23 +1,27 @@
Meteor.startup(() => {
if ( process.env.CORS ) {
if (process.env.CORS) {
// Listen to incoming HTTP requests, can only be used on the server
WebApp.rawConnectHandlers.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', process.env.CORS);
return next();
});
}
if ( process.env.CORS_ALLOW_HEADERS ) {
if (process.env.CORS_ALLOW_HEADERS) {
WebApp.rawConnectHandlers.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Headers', process.env.CORS_ALLOW_HEADERS);
res.setHeader(
'Access-Control-Allow-Headers',
process.env.CORS_ALLOW_HEADERS,
);
return next();
});
}
if ( process.env.CORS_EXPOSE_HEADERS ) {
if (process.env.CORS_EXPOSE_HEADERS) {
WebApp.rawConnectHandlers.use(function(req, res, next) {
res.setHeader('Access-Control-Expose-Headers', process.env.CORS_EXPOSE_HEADERS);
res.setHeader(
'Access-Control-Expose-Headers',
process.env.CORS_EXPOSE_HEADERS,
);
return next();
});
}
});

View file

@ -1,10 +1,10 @@
Meteor.startup(() => {
if ( process.env.HEADER_LOGIN_ID ) {
if (process.env.HEADER_LOGIN_ID) {
Meteor.settings.public.headerLoginId = process.env.HEADER_LOGIN_ID;
Meteor.settings.public.headerLoginEmail = process.env.HEADER_LOGIN_EMAIL;
Meteor.settings.public.headerLoginFirstname = process.env.HEADER_LOGIN_FIRSTNAME;
Meteor.settings.public.headerLoginLastname = process.env.HEADER_LOGIN_LASTNAME;
Meteor.settings.public.headerLoginFirstname =
process.env.HEADER_LOGIN_FIRSTNAME;
Meteor.settings.public.headerLoginLastname =
process.env.HEADER_LOGIN_LASTNAME;
}
});

View file

@ -7,7 +7,7 @@ allowIsBoardMember = function(userId, board) {
};
allowIsAnyBoardMember = function(userId, boards) {
return _.some(boards, (board) => {
return _.some(boards, board => {
return board && board.hasMember(userId);
});
};

View file

@ -62,16 +62,16 @@ Migrations.add('board-background-color', () => {
},
},
},
noValidateMulti
noValidateMulti,
);
});
Migrations.add('lowercase-board-permission', () => {
['Public', 'Private'].forEach((permission) => {
['Public', 'Private'].forEach(permission => {
Boards.update(
{ permission },
{ $set: { permission: permission.toLowerCase() } },
noValidateMulti
noValidateMulti,
);
});
});
@ -79,7 +79,7 @@ Migrations.add('lowercase-board-permission', () => {
// Security migration: see https://github.com/wekan/wekan/issues/99
Migrations.add('change-attachments-type-for-non-images', () => {
const newTypeForNonImage = 'application/octet-stream';
Attachments.find().forEach((file) => {
Attachments.find().forEach(file => {
if (!file.isImage()) {
Attachments.update(
file._id,
@ -89,14 +89,14 @@ Migrations.add('change-attachments-type-for-non-images', () => {
'copies.attachments.type': newTypeForNonImage,
},
},
noValidate
noValidate,
);
}
});
});
Migrations.add('card-covers', () => {
Cards.find().forEach((card) => {
Cards.find().forEach(card => {
const cover = Attachments.findOne({ cardId: card._id, cover: true });
if (cover) {
Cards.update(card._id, { $set: { coverId: cover._id } }, noValidate);
@ -114,7 +114,7 @@ Migrations.add('use-css-class-for-boards-colors', () => {
'#2C3E50': 'midnight',
'#E67E22': 'pumpkin',
};
Boards.find().forEach((board) => {
Boards.find().forEach(board => {
const oldBoardColor = board.background.color;
const newBoardColor = associationTable[oldBoardColor];
Boards.update(
@ -123,13 +123,13 @@ Migrations.add('use-css-class-for-boards-colors', () => {
$set: { color: newBoardColor },
$unset: { background: '' },
},
noValidate
noValidate,
);
});
});
Migrations.add('denormalize-star-number-per-board', () => {
Boards.find().forEach((board) => {
Boards.find().forEach(board => {
const nStars = Users.find({ 'profile.starredBoards': board._id }).count();
Boards.update(board._id, { $set: { stars: nStars } }, noValidate);
});
@ -138,9 +138,12 @@ Migrations.add('denormalize-star-number-per-board', () => {
// We want to keep a trace of former members so we can efficiently publish their
// infos in the general board publication.
Migrations.add('add-member-isactive-field', () => {
Boards.find({}, { fields: { members: 1 } }).forEach((board) => {
Boards.find({}, { fields: { members: 1 } }).forEach(board => {
const allUsersWithSomeActivity = _.chain(
Activities.find({ boardId: board._id }, { fields: { userId: 1 } }).fetch()
Activities.find(
{ boardId: board._id },
{ fields: { userId: 1 } },
).fetch(),
)
.pluck('userId')
.uniq()
@ -149,11 +152,11 @@ Migrations.add('add-member-isactive-field', () => {
const formerUsers = _.difference(allUsersWithSomeActivity, currentUsers);
const newMemberSet = [];
board.members.forEach((member) => {
board.members.forEach(member => {
member.isActive = true;
newMemberSet.push(member);
});
formerUsers.forEach((userId) => {
formerUsers.forEach(userId => {
newMemberSet.push({
userId,
isAdmin: false,
@ -170,7 +173,7 @@ Migrations.add('add-sort-checklists', () => {
Checklists.direct.update(
checklist._id,
{ $set: { sort: index } },
noValidate
noValidate,
);
}
checklist.items.forEach((item, index) => {
@ -178,7 +181,7 @@ Migrations.add('add-sort-checklists', () => {
Checklists.direct.update(
{ _id: checklist._id, 'items._id': item._id },
{ $set: { 'items.$.sort': index } },
noValidate
noValidate,
);
}
});
@ -186,14 +189,14 @@ Migrations.add('add-sort-checklists', () => {
});
Migrations.add('add-swimlanes', () => {
Boards.find().forEach((board) => {
Boards.find().forEach(board => {
const swimlaneId = board.getDefaultSwimline()._id;
Cards.find({ boardId: board._id }).forEach((card) => {
Cards.find({ boardId: board._id }).forEach(card => {
if (!card.hasOwnProperty('swimlaneId')) {
Cards.direct.update(
{ _id: card._id },
{ $set: { swimlaneId } },
noValidate
noValidate,
);
}
});
@ -201,19 +204,19 @@ Migrations.add('add-swimlanes', () => {
});
Migrations.add('add-views', () => {
Boards.find().forEach((board) => {
Boards.find().forEach(board => {
if (!board.hasOwnProperty('view')) {
Boards.direct.update(
{ _id: board._id },
{ $set: { view: 'board-view-swimlanes' } },
noValidate
noValidate,
);
}
});
});
Migrations.add('add-checklist-items', () => {
Checklists.find().forEach((checklist) => {
Checklists.find().forEach(checklist => {
// Create new items
_.sortBy(checklist.items, 'sort').forEach((item, index) => {
ChecklistItems.direct.insert({
@ -229,26 +232,26 @@ Migrations.add('add-checklist-items', () => {
Checklists.direct.update(
{ _id: checklist._id },
{ $unset: { items: 1 } },
noValidate
noValidate,
);
});
});
Migrations.add('add-profile-view', () => {
Users.find().forEach((user) => {
Users.find().forEach(user => {
if (!user.hasOwnProperty('profile.boardView')) {
// Set default view
Users.direct.update(
{ _id: user._id },
{ $set: { 'profile.boardView': 'board-view-lists' } },
noValidate
noValidate,
);
}
});
});
Migrations.add('add-card-types', () => {
Cards.find().forEach((card) => {
Cards.find().forEach(card => {
Cards.direct.update(
{ _id: card._id },
{
@ -257,7 +260,7 @@ Migrations.add('add-card-types', () => {
linkedId: null,
},
},
noValidate
noValidate,
);
});
});
@ -274,7 +277,7 @@ Migrations.add('add-custom-fields-to-cards', () => {
customFields: [],
},
},
noValidateMulti
noValidateMulti,
);
});
@ -290,7 +293,7 @@ Migrations.add('add-requester-field', () => {
requestedBy: '',
},
},
noValidateMulti
noValidateMulti,
);
});
@ -306,7 +309,7 @@ Migrations.add('add-assigner-field', () => {
assignedBy: '',
},
},
noValidateMulti
noValidateMulti,
);
});
@ -322,7 +325,7 @@ Migrations.add('add-parent-field-to-cards', () => {
parentId: '',
},
},
noValidateMulti
noValidateMulti,
);
});
@ -339,7 +342,7 @@ Migrations.add('add-subtasks-boards', () => {
subtasksDefaultListId: null,
},
},
noValidateMulti
noValidateMulti,
);
});
@ -355,7 +358,7 @@ Migrations.add('add-subtasks-sort', () => {
subtaskSort: -1,
},
},
noValidateMulti
noValidateMulti,
);
});
@ -371,7 +374,7 @@ Migrations.add('add-subtasks-allowed', () => {
allowsSubtasks: true,
},
},
noValidateMulti
noValidateMulti,
);
});
@ -387,7 +390,7 @@ Migrations.add('add-subtasks-allowed', () => {
presentParentTask: 'no-parent',
},
},
noValidateMulti
noValidateMulti,
);
});
@ -403,7 +406,7 @@ Migrations.add('add-authenticationMethod', () => {
authenticationMethod: 'password',
},
},
noValidateMulti
noValidateMulti,
);
});
@ -415,7 +418,7 @@ Migrations.add('remove-tag', () => {
'profile.tags': 1,
},
},
noValidateMulti
noValidateMulti,
);
});
@ -427,7 +430,7 @@ Migrations.add('remove-customFields-references-broken', () => {
customFields: { value: null },
},
},
noValidateMulti
noValidateMulti,
);
});
@ -443,7 +446,7 @@ Migrations.add('add-product-name', () => {
productName: '',
},
},
noValidateMulti
noValidateMulti,
);
});
@ -459,7 +462,7 @@ Migrations.add('add-hide-logo', () => {
hideLogo: false,
},
},
noValidateMulti
noValidateMulti,
);
});
@ -475,7 +478,7 @@ Migrations.add('add-custom-html-after-body-start', () => {
customHTMLafterBodyStart: '',
},
},
noValidateMulti
noValidateMulti,
);
});
@ -491,7 +494,7 @@ Migrations.add('add-custom-html-before-body-end', () => {
customHTMLbeforeBodyEnd: '',
},
},
noValidateMulti
noValidateMulti,
);
});
@ -507,7 +510,7 @@ Migrations.add('add-displayAuthenticationMethod', () => {
displayAuthenticationMethod: true,
},
},
noValidateMulti
noValidateMulti,
);
});
@ -523,7 +526,7 @@ Migrations.add('add-defaultAuthenticationMethod', () => {
defaultAuthenticationMethod: 'password',
},
},
noValidateMulti
noValidateMulti,
);
});
@ -539,7 +542,7 @@ Migrations.add('add-templates', () => {
type: 'board',
},
},
noValidateMulti
noValidateMulti,
);
Swimlanes.update(
{
@ -552,7 +555,7 @@ Migrations.add('add-templates', () => {
type: 'swimlane',
},
},
noValidateMulti
noValidateMulti,
);
Lists.update(
{
@ -569,13 +572,13 @@ Migrations.add('add-templates', () => {
swimlaneId: '',
},
},
noValidateMulti
noValidateMulti,
);
Users.find({
'profile.templatesBoardId': {
$exists: false,
},
}).forEach((user) => {
}).forEach(user => {
// Create board and swimlanes
Boards.insert(
{
@ -611,7 +614,7 @@ Migrations.add('add-templates', () => {
Users.update(user._id, {
$set: { 'profile.cardTemplatesSwimlaneId': swimlaneId },
});
}
},
);
// Insert the list templates swimlane
@ -627,7 +630,7 @@ Migrations.add('add-templates', () => {
Users.update(user._id, {
$set: { 'profile.listTemplatesSwimlaneId': swimlaneId },
});
}
},
);
// Insert the board templates swimlane
@ -643,15 +646,15 @@ Migrations.add('add-templates', () => {
Users.update(user._id, {
$set: { 'profile.boardTemplatesSwimlaneId': swimlaneId },
});
}
},
);
}
},
);
});
});
Migrations.add('fix-circular-reference_', () => {
Cards.find().forEach((card) => {
Cards.find().forEach(card => {
if (card.parentId === card._id) {
Cards.update(card._id, { $set: { parentId: '' } }, noValidateMulti);
}
@ -659,7 +662,7 @@ Migrations.add('fix-circular-reference_', () => {
});
Migrations.add('mutate-boardIds-in-customfields', () => {
CustomFields.find().forEach((cf) => {
CustomFields.find().forEach(cf => {
CustomFields.update(
cf,
{
@ -670,7 +673,7 @@ Migrations.add('mutate-boardIds-in-customfields', () => {
boardId: '',
},
},
noValidateMulti
noValidateMulti,
);
});
});
@ -696,13 +699,13 @@ const firstBatchOfDbsToAddCreatedAndUpdated = [
UnsavedEdits,
];
firstBatchOfDbsToAddCreatedAndUpdated.forEach((db) => {
firstBatchOfDbsToAddCreatedAndUpdated.forEach(db => {
db.before.insert((userId, doc) => {
doc.createdAt = Date.now();
doc.updatedAt = doc.createdAt;
});
db.before.update((userId, doc, fieldNames, modifier, options) => {
db.before.update((userId, doc, fieldNames, modifier) => {
modifier.$set = modifier.$set || {};
modifier.$set.updatedAt = new Date();
});
@ -732,13 +735,13 @@ const modifiedAtTables = [
Migrations.add('add-missing-created-and-modified', () => {
Promise.all(
modifiedAtTables.map((db) =>
modifiedAtTables.map(db =>
db
.rawCollection()
.update(
{ modifiedAt: { $exists: false } },
{ $set: { modifiedAt: new Date() } },
{ multi: true }
{ multi: true },
)
.then(() =>
db
@ -746,16 +749,16 @@ Migrations.add('add-missing-created-and-modified', () => {
.update(
{ createdAt: { $exists: false } },
{ $set: { createdAt: new Date() } },
{ multi: true }
)
)
)
{ multi: true },
),
),
),
)
.then(() => {
// eslint-disable-next-line no-console
console.info('Successfully added createdAt and updatedAt to all tables');
})
.catch((e) => {
.catch(e => {
// eslint-disable-next-line no-console
console.error(e);
});

View file

@ -3,11 +3,15 @@ Meteor.startup(() => {
Notifications.subscribe('email', (user, title, description, params) => {
// add quote to make titles easier to read in email text
const quoteParams = _.clone(params);
['card', 'list', 'oldList', 'board', 'comment'].forEach((key) => {
['card', 'list', 'oldList', 'board', 'comment'].forEach(key => {
if (quoteParams[key]) quoteParams[key] = `"${params[key]}"`;
});
const text = `${params.user} ${TAPi18n.__(description, quoteParams, user.getLanguage())}\n${params.url}`;
const text = `${params.user} ${TAPi18n.__(
description,
quoteParams,
user.getLanguage(),
)}\n${params.url}`;
user.addEmailBuffer(text);
// unlike setTimeout(func, delay, args),
@ -39,5 +43,3 @@ Meteor.startup(() => {
}, process.env.EMAIL_NOTIFICATION_TIMEOUT || 30000);
});
});

View file

@ -14,14 +14,14 @@ Notifications = {
notifyServices[serviceName] = callback;
},
unsubscribe: (serviceName) => {
unsubscribe: serviceName => {
if (typeof notifyServices[serviceName] === 'function')
delete notifyServices[serviceName];
},
getUsers: (watchers) => {
getUsers: watchers => {
const users = [];
watchers.forEach((userId) => {
watchers.forEach(userId => {
const user = Users.findOne(userId);
if (user) users.push(user);
});
@ -29,9 +29,10 @@ Notifications = {
},
notify: (user, title, description, params) => {
for(const k in notifyServices) {
for (const k in notifyServices) {
const notifyImpl = notifyServices[k];
if (notifyImpl && typeof notifyImpl === 'function') notifyImpl(user, title, description, params);
if (notifyImpl && typeof notifyImpl === 'function')
notifyImpl(user, title, description, params);
}
},
};

View file

@ -8,7 +8,18 @@ const postCatchError = Meteor.wrapAsync((url, options, resolve) => {
});
});
const webhooksAtbts = ( (process.env.WEBHOOKS_ATTRIBUTES && process.env.WEBHOOKS_ATTRIBUTES.split(',') ) || ['cardId', 'listId', 'oldListId', 'boardId', 'comment', 'user', 'card', 'commentId', 'swimlaneId']);
const webhooksAtbts = (process.env.WEBHOOKS_ATTRIBUTES &&
process.env.WEBHOOKS_ATTRIBUTES.split(',')) || [
'cardId',
'listId',
'oldListId',
'boardId',
'comment',
'user',
'card',
'commentId',
'swimlaneId',
];
Meteor.methods({
outgoingWebhooks(integrations, description, params) {
@ -18,13 +29,29 @@ Meteor.methods({
// label activity did not work yet, see wekan/models/activities.js
const quoteParams = _.clone(params);
['card', 'list', 'oldList', 'board', 'oldBoard', 'comment', 'checklist', 'swimlane', 'oldSwimlane', 'label', 'attachment'].forEach((key) => {
[
'card',
'list',
'oldList',
'board',
'oldBoard',
'comment',
'checklist',
'swimlane',
'oldSwimlane',
'label',
'attachment',
].forEach(key => {
if (quoteParams[key]) quoteParams[key] = `"${params[key]}"`;
});
const userId = (params.userId) ? params.userId : integrations[0].userId;
const userId = params.userId ? params.userId : integrations[0].userId;
const user = Users.findOne(userId);
const text = `${params.user} ${TAPi18n.__(description, quoteParams, user.getLanguage())}\n${params.url}`;
const text = `${params.user} ${TAPi18n.__(
description,
quoteParams,
user.getLanguage(),
)}\n${params.url}`;
if (text.length === 0) return;
@ -32,7 +59,7 @@ Meteor.methods({
text: `${text}`,
};
webhooksAtbts.forEach((key) => {
webhooksAtbts.forEach(key => {
if (params[key]) value[key] = params[key];
});
value.description = description;
@ -45,7 +72,7 @@ Meteor.methods({
data: value,
};
integrations.forEach((integration) => {
integrations.forEach(integration => {
const response = postCatchError(integration.url, options);
if (response && response.statusCode && response.statusCode === 200) {

View file

@ -12,22 +12,19 @@ Meteor.methods({
watchableObj = Boards.findOne(id);
if (!watchableObj) throw new Meteor.Error('error-board-doesNotExist');
board = watchableObj;
} else if (watchableType === 'list') {
watchableObj = Lists.findOne(id);
if (!watchableObj) throw new Meteor.Error('error-list-doesNotExist');
board = watchableObj.board();
} else if (watchableType === 'card') {
watchableObj = Cards.findOne(id);
if (!watchableObj) throw new Meteor.Error('error-card-doesNotExist');
board = watchableObj.board();
} else {
throw new Meteor.Error('error-json-schema');
}
if ((board.permission === 'private') && !board.hasMember(userId))
if (board.permission === 'private' && !board.hasMember(userId))
throw new Meteor.Error('error-board-notAMember');
watchableObj.setWatcher(userId, level);

View file

@ -1,8 +1,7 @@
import { BrowserPolicy } from 'meteor/browser-policy-common';
Meteor.startup(() => {
if ( process.env.BROWSER_POLICY_ENABLED === 'true' ) {
if (process.env.BROWSER_POLICY_ENABLED === 'true') {
// Trusted URL that can embed Wekan in iFrame.
const trusted = process.env.TRUSTED_URL;
BrowserPolicy.framing.disallow();
@ -13,8 +12,7 @@ Meteor.startup(() => {
//BrowserPolicy.content.allowFontDataUrl();
BrowserPolicy.framing.restrictToOrigin(trusted);
//BrowserPolicy.content.allowScriptOrigin(trusted);
}
else {
} else {
// Disable browser policy and allow all framing and including.
// Use only at internal LAN, not at Internet.
BrowserPolicy.framing.allowAll();
@ -26,9 +24,8 @@ Meteor.startup(() => {
// If Matomo URL is set, allow it.
const matomoUrl = process.env.MATOMO_ADDRESS;
if (matomoUrl){
if (matomoUrl) {
//BrowserPolicy.content.allowScriptOrigin(matomoUrl);
//BrowserPolicy.content.allowImageOrigin(matomoUrl);
}
});

View file

@ -4,16 +4,21 @@
// We use this publication to paginate for these two publications.
Meteor.publish('activities', (kind, id, limit, hideSystem) => {
check(kind, Match.Where((x) => {
return ['board', 'card'].indexOf(x) !== -1;
}));
check(
kind,
Match.Where(x => {
return ['board', 'card'].indexOf(x) !== -1;
}),
);
check(id, String);
check(limit, Number);
check(hideSystem, Boolean);
const selector = (hideSystem) ? {$and: [{activityType: 'addComment'}, {[`${kind}Id`]: id}]} : {[`${kind}Id`]: id};
const selector = hideSystem
? { $and: [{ activityType: 'addComment' }, { [`${kind}Id`]: id }] }
: { [`${kind}Id`]: id };
return Activities.find(selector, {
limit,
sort: {createdAt: -1},
sort: { createdAt: -1 },
});
});

View file

@ -5,58 +5,62 @@
Meteor.publish('boards', function() {
// Ensure that the user is connected. If it is not, we need to return an empty
// array to tell the client to remove the previously published docs.
if (!Match.test(this.userId, String))
return [];
if (!Match.test(this.userId, String)) return [];
// Defensive programming to verify that starredBoards has the expected
// format -- since the field is in the `profile` a user can modify it.
const {starredBoards = []} = Users.findOne(this.userId).profile || {};
const { starredBoards = [] } = Users.findOne(this.userId).profile || {};
check(starredBoards, [String]);
return Boards.find({
archived: false,
$or: [
{
_id: { $in: starredBoards },
permission: 'public',
},
{ members: { $elemMatch: { userId: this.userId, isActive: true }}},
],
}, {
fields: {
_id: 1,
archived: 1,
slug: 1,
title: 1,
description: 1,
color: 1,
members: 1,
permission: 1,
type: 1,
return Boards.find(
{
archived: false,
$or: [
{
_id: { $in: starredBoards },
permission: 'public',
},
{ members: { $elemMatch: { userId: this.userId, isActive: true } } },
],
},
});
{
fields: {
_id: 1,
archived: 1,
slug: 1,
title: 1,
description: 1,
color: 1,
members: 1,
permission: 1,
type: 1,
},
},
);
});
Meteor.publish('archivedBoards', function() {
if (!Match.test(this.userId, String))
return [];
if (!Match.test(this.userId, String)) return [];
return Boards.find({
archived: true,
members: {
$elemMatch: {
userId: this.userId,
isAdmin: true,
return Boards.find(
{
archived: true,
members: {
$elemMatch: {
userId: this.userId,
isAdmin: true,
},
},
},
}, {
fields: {
_id: 1,
archived: 1,
slug: 1,
title: 1,
{
fields: {
_id: 1,
archived: 1,
slug: 1,
title: 1,
},
},
});
);
});
// If isArchived = false, this will only return board elements which are not archived.
@ -67,106 +71,130 @@ Meteor.publishRelations('board', function(boardId, isArchived) {
check(isArchived, Boolean);
const thisUserId = this.userId;
this.cursor(Boards.find({
_id: boardId,
archived: false,
// If the board is not public the user has to be a member of it to see
// it.
$or: [
{ permission: 'public' },
{ members: { $elemMatch: { userId: this.userId, isActive: true }}},
],
// Sort required to ensure oplog usage
}, { limit: 1, sort: { _id: 1 } }), function(boardId, board) {
this.cursor(Lists.find({ boardId, archived: isArchived }));
this.cursor(Swimlanes.find({ boardId, archived: isArchived }));
this.cursor(Integrations.find({ boardId }));
this.cursor(CustomFields.find({ boardIds: {$in: [boardId]} }, { sort: { name: 1 } }));
this.cursor(
Boards.find(
{
_id: boardId,
archived: false,
// If the board is not public the user has to be a member of it to see
// it.
$or: [
{ permission: 'public' },
{ members: { $elemMatch: { userId: this.userId, isActive: true } } },
],
// Sort required to ensure oplog usage
},
{ limit: 1, sort: { _id: 1 } },
),
function(boardId, board) {
this.cursor(Lists.find({ boardId, archived: isArchived }));
this.cursor(Swimlanes.find({ boardId, archived: isArchived }));
this.cursor(Integrations.find({ boardId }));
this.cursor(
CustomFields.find(
{ boardIds: { $in: [boardId] } },
{ sort: { name: 1 } },
),
);
// Cards and cards comments
// XXX Originally we were publishing the card documents as a child of the
// list publication defined above using the following selector `{ listId:
// list._id }`. But it was causing a race condition in publish-composite,
// that I documented here:
//
// https://github.com/englue/meteor-publish-composite/issues/29
//
// cottz:publish had a similar problem:
//
// https://github.com/Goluis/cottz-publish/issues/4
//
// The current state of relational publishing in meteor is a bit sad,
// there are a lot of various packages, with various APIs, some of them
// are unmaintained. Fortunately this is something that will be fixed by
// meteor-core at some point:
//
// https://trello.com/c/BGvIwkEa/48-easy-joins-in-subscriptions
//
// And in the meantime our code below works pretty well -- it's not even a
// hack!
// Cards and cards comments
// XXX Originally we were publishing the card documents as a child of the
// list publication defined above using the following selector `{ listId:
// list._id }`. But it was causing a race condition in publish-composite,
// that I documented here:
//
// https://github.com/englue/meteor-publish-composite/issues/29
//
// cottz:publish had a similar problem:
//
// https://github.com/Goluis/cottz-publish/issues/4
//
// The current state of relational publishing in meteor is a bit sad,
// there are a lot of various packages, with various APIs, some of them
// are unmaintained. Fortunately this is something that will be fixed by
// meteor-core at some point:
//
// https://trello.com/c/BGvIwkEa/48-easy-joins-in-subscriptions
//
// And in the meantime our code below works pretty well -- it's not even a
// hack!
// Gather queries and send in bulk
const cardComments = this.join(CardComments);
cardComments.selector = (_ids) => ({ cardId: _ids });
const attachments = this.join(Attachments);
attachments.selector = (_ids) => ({ cardId: _ids });
const checklists = this.join(Checklists);
checklists.selector = (_ids) => ({ cardId: _ids });
const checklistItems = this.join(ChecklistItems);
checklistItems.selector = (_ids) => ({ cardId: _ids });
const parentCards = this.join(Cards);
parentCards.selector = (_ids) => ({ parentId: _ids });
const boards = this.join(Boards);
const subCards = this.join(Cards);
subCards.selector = (_ids) => ({ archived: isArchived });
// Gather queries and send in bulk
const cardComments = this.join(CardComments);
cardComments.selector = _ids => ({ cardId: _ids });
const attachments = this.join(Attachments);
attachments.selector = _ids => ({ cardId: _ids });
const checklists = this.join(Checklists);
checklists.selector = _ids => ({ cardId: _ids });
const checklistItems = this.join(ChecklistItems);
checklistItems.selector = _ids => ({ cardId: _ids });
const parentCards = this.join(Cards);
parentCards.selector = _ids => ({ parentId: _ids });
const boards = this.join(Boards);
const subCards = this.join(Cards);
subCards.selector = () => ({ archived: isArchived });
this.cursor(Cards.find({ boardId: {$in: [boardId, board.subtasksDefaultBoardId]}, archived: isArchived }), function(cardId, card) {
if (card.type === 'cardType-linkedCard') {
const impCardId = card.linkedId;
subCards.push(impCardId);
cardComments.push(impCardId);
attachments.push(impCardId);
checklists.push(impCardId);
checklistItems.push(impCardId);
} else if (card.type === 'cardType-linkedBoard') {
boards.push(card.linkedId);
this.cursor(
Cards.find({
boardId: { $in: [boardId, board.subtasksDefaultBoardId] },
archived: isArchived,
}),
function(cardId, card) {
if (card.type === 'cardType-linkedCard') {
const impCardId = card.linkedId;
subCards.push(impCardId);
cardComments.push(impCardId);
attachments.push(impCardId);
checklists.push(impCardId);
checklistItems.push(impCardId);
} else if (card.type === 'cardType-linkedBoard') {
boards.push(card.linkedId);
}
cardComments.push(cardId);
attachments.push(cardId);
checklists.push(cardId);
checklistItems.push(cardId);
parentCards.push(cardId);
},
);
// Send bulk queries for all found ids
subCards.send();
cardComments.send();
attachments.send();
checklists.send();
checklistItems.send();
boards.send();
parentCards.send();
if (board.members) {
// Board members. This publication also includes former board members that
// aren't members anymore but may have some activities attached to them in
// the history.
const memberIds = _.pluck(board.members, 'userId');
// We omit the current user because the client should already have that data,
// and sending it triggers a subtle bug:
// https://github.com/wefork/wekan/issues/15
this.cursor(
Users.find(
{
_id: { $in: _.without(memberIds, thisUserId) },
},
{
fields: {
username: 1,
'profile.fullname': 1,
'profile.avatarUrl': 1,
},
},
),
);
this.cursor(presences.find({ userId: { $in: memberIds } }));
}
cardComments.push(cardId);
attachments.push(cardId);
checklists.push(cardId);
checklistItems.push(cardId);
parentCards.push(cardId);
});
// Send bulk queries for all found ids
subCards.send();
cardComments.send();
attachments.send();
checklists.send();
checklistItems.send();
boards.send();
parentCards.send();
if (board.members) {
// Board members. This publication also includes former board members that
// aren't members anymore but may have some activities attached to them in
// the history.
const memberIds = _.pluck(board.members, 'userId');
// We omit the current user because the client should already have that data,
// and sending it triggers a subtle bug:
// https://github.com/wefork/wekan/issues/15
this.cursor(Users.find({
_id: { $in: _.without(memberIds, thisUserId)},
}, { fields: {
'username': 1,
'profile.fullname': 1,
'profile.avatarUrl': 1,
}}));
this.cursor(presences.find({ userId: { $in: memberIds } }));
}
});
},
);
return this.ready();
});

View file

@ -1,4 +1,4 @@
Meteor.publish('card', (cardId) => {
Meteor.publish('card', cardId => {
check(cardId, String);
return Cards.find({ _id: cardId });
});

View file

@ -7,19 +7,22 @@ Meteor.publish('people', function(limit) {
const user = Users.findOne(this.userId);
if (user && user.isAdmin) {
return Users.find({}, {
limit,
sort: {createdAt: -1},
fields: {
'username': 1,
'profile.fullname': 1,
'isAdmin': 1,
'emails': 1,
'createdAt': 1,
'loginDisabled': 1,
'authenticationMethod': 1,
return Users.find(
{},
{
limit,
sort: { createdAt: -1 },
fields: {
username: 1,
'profile.fullname': 1,
isAdmin: 1,
emails: 1,
createdAt: 1,
loginDisabled: 1,
authenticationMethod: 1,
},
},
});
);
} else {
return [];
}

View file

@ -1,4 +1,4 @@
Meteor.publish('rules', (ruleId) => {
Meteor.publish('rules', ruleId => {
check(ruleId, String);
return Rules.find({
_id: ruleId,

View file

@ -1,23 +1,25 @@
Meteor.publish('setting', () => {
return Settings.find({}, {
fields:{
disableRegistration: 1,
productName: 1,
hideLogo: 1,
customHTMLafterBodyStart: 1,
customHTMLbeforeBodyEnd: 1,
displayAuthenticationMethod: 1,
defaultAuthenticationMethod: 1,
return Settings.find(
{},
{
fields: {
disableRegistration: 1,
productName: 1,
hideLogo: 1,
customHTMLafterBodyStart: 1,
customHTMLbeforeBodyEnd: 1,
displayAuthenticationMethod: 1,
defaultAuthenticationMethod: 1,
},
},
});
);
});
Meteor.publish('mailServer', function () {
if (!Match.test(this.userId, String))
return [];
Meteor.publish('mailServer', function() {
if (!Match.test(this.userId, String)) return [];
const user = Users.findOne(this.userId);
if(user && user.isAdmin){
return Settings.find({}, {fields: {mailServer: 1}});
if (user && user.isAdmin) {
return Settings.find({}, { fields: { mailServer: 1 } });
}
return [];
});

View file

@ -3,7 +3,7 @@ Meteor.publish('user-miniprofile', function(userId) {
return Users.find(userId, {
fields: {
'username': 1,
username: 1,
'profile.fullname': 1,
'profile.avatarUrl': 1,
},
@ -20,9 +20,12 @@ Meteor.publish('user-admin', function() {
Meteor.publish('user-authenticationMethod', function(match) {
check(match, String);
return Users.find({$or: [{_id: match}, {email: match}, {username: match}]}, {
fields: {
'authenticationMethod': 1,
return Users.find(
{ $or: [{ _id: match }, { email: match }, { username: match }] },
{
fields: {
authenticationMethod: 1,
},
},
});
);
});

View file

@ -1,72 +1,78 @@
RulesHelper = {
executeRules(activity){
executeRules(activity) {
const matchingRules = this.findMatchingRules(activity);
for(let i = 0; i< matchingRules.length; i++){
for (let i = 0; i < matchingRules.length; i++) {
const action = matchingRules[i].getAction();
if(action !== undefined){
if (action !== undefined) {
this.performAction(activity, action);
}
}
},
findMatchingRules(activity){
findMatchingRules(activity) {
const activityType = activity.activityType;
if(TriggersDef[activityType] === undefined){
if (TriggersDef[activityType] === undefined) {
return [];
}
const matchingFields = TriggersDef[activityType].matchingFields;
const matchingMap = this.buildMatchingFieldsMap(activity, matchingFields);
const matchingTriggers = Triggers.find(matchingMap);
const matchingRules = [];
matchingTriggers.forEach(function(trigger){
matchingTriggers.forEach(function(trigger) {
const rule = trigger.getRule();
// Check that for some unknown reason there are some leftover triggers
// not connected to any rules
if(rule !== undefined){
if (rule !== undefined) {
matchingRules.push(trigger.getRule());
}
});
return matchingRules;
},
buildMatchingFieldsMap(activity, matchingFields){
const matchingMap = {'activityType':activity.activityType};
for(let i = 0; i< matchingFields.length; i++){
buildMatchingFieldsMap(activity, matchingFields) {
const matchingMap = { activityType: activity.activityType };
for (let i = 0; i < matchingFields.length; i++) {
// Creating a matching map with the actual field of the activity
// and with the wildcard (for example: trigger when a card is added
// in any [*] board
matchingMap[matchingFields[i]] = { $in: [activity[matchingFields[i]], '*']};
matchingMap[matchingFields[i]] = {
$in: [activity[matchingFields[i]], '*'],
};
}
return matchingMap;
},
performAction(activity, action){
const card = Cards.findOne({_id:activity.cardId});
performAction(activity, action) {
const card = Cards.findOne({ _id: activity.cardId });
const boardId = activity.boardId;
if(action.actionType === 'moveCardToTop'){
if (action.actionType === 'moveCardToTop') {
let listId;
let list;
if(action.listTitle === '*'){
if (action.listTitle === '*') {
listId = card.listId;
list = card.list();
}else{
list = Lists.findOne({title: action.listTitle, boardId });
} else {
list = Lists.findOne({ title: action.listTitle, boardId });
listId = list._id;
}
const minOrder = _.min(list.cardsUnfiltered(card.swimlaneId).map((c) => c.sort));
const minOrder = _.min(
list.cardsUnfiltered(card.swimlaneId).map(c => c.sort),
);
card.move(boardId, card.swimlaneId, listId, minOrder - 1);
}
if(action.actionType === 'moveCardToBottom'){
if (action.actionType === 'moveCardToBottom') {
let listId;
let list;
if(action.listTitle === '*'){
if (action.listTitle === '*') {
listId = card.listId;
list = card.list();
}else{
list = Lists.findOne({title: action.listTitle, boardId});
} else {
list = Lists.findOne({ title: action.listTitle, boardId });
listId = list._id;
}
const maxOrder = _.max(list.cardsUnfiltered(card.swimlaneId).map((c) => c.sort));
const maxOrder = _.max(
list.cardsUnfiltered(card.swimlaneId).map(c => c.sort),
);
card.move(boardId, card.swimlaneId, listId, maxOrder + 1);
}
if(action.actionType === 'sendEmail'){
if (action.actionType === 'sendEmail') {
const to = action.emailTo;
const text = action.emailMsg || '';
const subject = action.emailSubject || '';
@ -84,38 +90,38 @@ RulesHelper = {
}
}
if(action.actionType === 'setDate') {
if (action.actionType === 'setDate') {
try {
const currentDateTime = new Date();
switch (action.dateField){
case 'startAt': {
const resStart = card.getStart();
if (typeof resStart === 'undefined') {
card.setStart(currentDateTime);
switch (action.dateField) {
case 'startAt': {
const resStart = card.getStart();
if (typeof resStart === 'undefined') {
card.setStart(currentDateTime);
}
break;
}
break;
}
case 'endAt': {
const resEnd = card.getEnd();
if (typeof resEnd === 'undefined') {
card.setEnd(currentDateTime);
case 'endAt': {
const resEnd = card.getEnd();
if (typeof resEnd === 'undefined') {
card.setEnd(currentDateTime);
}
break;
}
break;
}
case 'dueAt': {
const resDue = card.getDue();
if (typeof resDue === 'undefined') {
card.setDue(currentDateTime);
case 'dueAt': {
const resDue = card.getDue();
if (typeof resDue === 'undefined') {
card.setDue(currentDateTime);
}
break;
}
break;
}
case 'receivedAt': {
const resReceived = card.getReceived();
if (typeof resReceived === 'undefined') {
card.setReceived(currentDateTime);
case 'receivedAt': {
const resReceived = card.getReceived();
if (typeof resReceived === 'undefined') {
card.setReceived(currentDateTime);
}
break;
}
break;
}
}
} catch (e) {
// eslint-disable-next-line no-console
@ -124,135 +130,177 @@ RulesHelper = {
}
}
if(action.actionType === 'updateDate'){
if (action.actionType === 'updateDate') {
const currentDateTimeUpdate = new Date();
switch (action.dateField){
case 'startAt': {
card.setStart(currentDateTimeUpdate);
break;
}
case 'endAt': {
card.setEnd(currentDateTimeUpdate);
break;
}
case 'dueAt': {
card.setDue(currentDateTimeUpdate);
break;
}
case 'receivedAt': {
card.setReceived(currentDateTimeUpdate);
break;
}
switch (action.dateField) {
case 'startAt': {
card.setStart(currentDateTimeUpdate);
break;
}
case 'endAt': {
card.setEnd(currentDateTimeUpdate);
break;
}
case 'dueAt': {
card.setDue(currentDateTimeUpdate);
break;
}
case 'receivedAt': {
card.setReceived(currentDateTimeUpdate);
break;
}
}
}
if(action.actionType === 'removeDate'){
switch (action.dateField){
case 'startAt': {
card.unsetStart();
break;
}
case 'endAt': {
card.unsetEnd();
break;
}
case 'dueAt': {
card.unsetDue();
break;
}
case 'receivedAt': {
card.unsetReceived();
break;
}
if (action.actionType === 'removeDate') {
switch (action.dateField) {
case 'startAt': {
card.unsetStart();
break;
}
case 'endAt': {
card.unsetEnd();
break;
}
case 'dueAt': {
card.unsetDue();
break;
}
case 'receivedAt': {
card.unsetReceived();
break;
}
}
}
if(action.actionType === 'archive'){
if (action.actionType === 'archive') {
card.archive();
}
if(action.actionType === 'unarchive'){
if (action.actionType === 'unarchive') {
card.restore();
}
if(action.actionType === 'setColor'){
if (action.actionType === 'setColor') {
card.setColor(action.selectedColor);
}
if(action.actionType === 'addLabel'){
if (action.actionType === 'addLabel') {
card.addLabel(action.labelId);
}
if(action.actionType === 'removeLabel'){
if (action.actionType === 'removeLabel') {
card.removeLabel(action.labelId);
}
if(action.actionType === 'addMember'){
const memberId = Users.findOne({username:action.username})._id;
if (action.actionType === 'addMember') {
const memberId = Users.findOne({ username: action.username })._id;
card.assignMember(memberId);
}
if(action.actionType === 'removeMember'){
if(action.username === '*'){
if (action.actionType === 'removeMember') {
if (action.username === '*') {
const members = card.members;
for(let i = 0; i< members.length; i++){
for (let i = 0; i < members.length; i++) {
card.unassignMember(members[i]);
}
}else{
const memberId = Users.findOne({username:action.username})._id;
} else {
const memberId = Users.findOne({ username: action.username })._id;
card.unassignMember(memberId);
}
}
if(action.actionType === 'checkAll'){
const checkList = Checklists.findOne({'title':action.checklistName, 'cardId':card._id});
if (action.actionType === 'checkAll') {
const checkList = Checklists.findOne({
title: action.checklistName,
cardId: card._id,
});
checkList.checkAllItems();
}
if(action.actionType === 'uncheckAll'){
const checkList = Checklists.findOne({'title':action.checklistName, 'cardId':card._id});
if (action.actionType === 'uncheckAll') {
const checkList = Checklists.findOne({
title: action.checklistName,
cardId: card._id,
});
checkList.uncheckAllItems();
}
if(action.actionType === 'checkItem'){
const checkList = Checklists.findOne({'title':action.checklistName, 'cardId':card._id});
const checkItem = ChecklistItems.findOne({'title':action.checkItemName, 'checkListId':checkList._id});
if (action.actionType === 'checkItem') {
const checkList = Checklists.findOne({
title: action.checklistName,
cardId: card._id,
});
const checkItem = ChecklistItems.findOne({
title: action.checkItemName,
checkListId: checkList._id,
});
checkItem.check();
}
if(action.actionType === 'uncheckItem'){
const checkList = Checklists.findOne({'title':action.checklistName, 'cardId':card._id});
const checkItem = ChecklistItems.findOne({'title':action.checkItemName, 'checkListId':checkList._id});
if (action.actionType === 'uncheckItem') {
const checkList = Checklists.findOne({
title: action.checklistName,
cardId: card._id,
});
const checkItem = ChecklistItems.findOne({
title: action.checkItemName,
checkListId: checkList._id,
});
checkItem.uncheck();
}
if(action.actionType === 'addChecklist'){
Checklists.insert({'title':action.checklistName, 'cardId':card._id, 'sort':0});
if (action.actionType === 'addChecklist') {
Checklists.insert({
title: action.checklistName,
cardId: card._id,
sort: 0,
});
}
if(action.actionType === 'removeChecklist'){
Checklists.remove({'title':action.checklistName, 'cardId':card._id, 'sort':0});
if (action.actionType === 'removeChecklist') {
Checklists.remove({
title: action.checklistName,
cardId: card._id,
sort: 0,
});
}
if(action.actionType === 'addSwimlane'){
if (action.actionType === 'addSwimlane') {
Swimlanes.insert({
title: action.swimlaneName,
boardId,
sort: 0,
});
}
if(action.actionType === 'addChecklistWithItems'){
const checkListId = Checklists.insert({'title':action.checklistName, 'cardId':card._id, 'sort':0});
if (action.actionType === 'addChecklistWithItems') {
const checkListId = Checklists.insert({
title: action.checklistName,
cardId: card._id,
sort: 0,
});
const itemsArray = action.checklistItems.split(',');
const checkList = Checklists.findOne({_id:checkListId});
for(let i = 0; i <itemsArray.length; i++){
ChecklistItems.insert({title:itemsArray[i], checklistId:checkListId, cardId:card._id, 'sort':checkList.itemCount()});
const checkList = Checklists.findOne({ _id: checkListId });
for (let i = 0; i < itemsArray.length; i++) {
ChecklistItems.insert({
title: itemsArray[i],
checklistId: checkListId,
cardId: card._id,
sort: checkList.itemCount(),
});
}
}
if(action.actionType === 'createCard'){
const list = Lists.findOne({title:action.listName, boardId});
if (action.actionType === 'createCard') {
const list = Lists.findOne({ title: action.listName, boardId });
let listId = '';
let swimlaneId = '';
const swimlane = Swimlanes.findOne({title:action.swimlaneName, boardId});
if(list === undefined){
const swimlane = Swimlanes.findOne({
title: action.swimlaneName,
boardId,
});
if (list === undefined) {
listId = '';
}else{
} else {
listId = list._id;
}
if(swimlane === undefined){
swimlaneId = Swimlanes.findOne({title:'Default', boardId})._id;
}else{
if (swimlane === undefined) {
swimlaneId = Swimlanes.findOne({ title: 'Default', boardId })._id;
} else {
swimlaneId = swimlane._id;
}
Cards.insert({title:action.cardName, listId, swimlaneId, sort:0, boardId});
Cards.insert({
title: action.cardName,
listId,
swimlaneId,
sort: 0,
boardId,
});
}
},
};

View file

@ -1,58 +1,69 @@
TriggersDef = {
createCard:{
matchingFields: ['boardId', 'listName', 'userId', 'swimlaneName', 'cardTitle'],
createCard: {
matchingFields: [
'boardId',
'listName',
'userId',
'swimlaneName',
'cardTitle',
],
},
moveCard:{
matchingFields: ['boardId', 'listName', 'oldListName', 'userId', 'swimlaneName', 'cardTitle'],
moveCard: {
matchingFields: [
'boardId',
'listName',
'oldListName',
'userId',
'swimlaneName',
'cardTitle',
],
},
archivedCard:{
archivedCard: {
matchingFields: ['boardId', 'userId', 'cardTitle'],
},
restoredCard:{
restoredCard: {
matchingFields: ['boardId', 'userId', 'cardTitle'],
},
joinMember:{
joinMember: {
matchingFields: ['boardId', 'username', 'userId'],
},
unjoinMember:{
unjoinMember: {
matchingFields: ['boardId', 'username', 'userId'],
},
addChecklist:{
addChecklist: {
matchingFields: ['boardId', 'checklistName', 'userId'],
},
removeChecklist:{
removeChecklist: {
matchingFields: ['boardId', 'checklistName', 'userId'],
},
completeChecklist:{
completeChecklist: {
matchingFields: ['boardId', 'checklistName', 'userId'],
},
uncompleteChecklist:{
uncompleteChecklist: {
matchingFields: ['boardId', 'checklistName', 'userId'],
},
addedChecklistItem:{
addedChecklistItem: {
matchingFields: ['boardId', 'checklistItemName', 'userId'],
},
removedChecklistItem:{
removedChecklistItem: {
matchingFields: ['boardId', 'checklistItemName', 'userId'],
},
checkedItem:{
checkedItem: {
matchingFields: ['boardId', 'checklistItemName', 'userId'],
},
uncheckedItem:{
uncheckedItem: {
matchingFields: ['boardId', 'checklistItemName', 'userId'],
},
addAttachment:{
addAttachment: {
matchingFields: ['boardId', 'userId'],
},
deleteAttachment:{
deleteAttachment: {
matchingFields: ['boardId', 'userId'],
},
addedLabel:{
addedLabel: {
matchingFields: ['boardId', 'labelId', 'userId'],
},
removedLabel:{
removedLabel: {
matchingFields: ['boardId', 'labelId', 'userId'],
},
};