This commit is contained in:
John Supplee 2021-12-19 12:18:05 +02:00
commit 241c3ed8ae
332 changed files with 18869 additions and 18221 deletions

View file

@ -0,0 +1,9 @@
Meteor.startup(() => {
if (Meteor.isServer) {
import { AccountsCommon } from 'meteor/accounts-base';
Accounts.config({
loginExpirationInDays: process.env.ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS || 90,
});
}
});

View file

@ -1,4 +1,5 @@
import AccountSettings from '../models/accountSettings';
import TableVisibilityModeSettings from '../models/tableVisibilityModeSettings';
import Actions from '../models/actions';
import Activities from '../models/activities';
import Announcements from '../models/announcements';
@ -645,6 +646,7 @@ Migrations.add('mutate-boardIds-in-customfields', () => {
const modifiedAtTables = [
AccountSettings,
TableVisibilityModeSettings,
Actions,
Activities,
Announcements,
@ -699,6 +701,7 @@ Migrations.add('add-missing-created-and-modified', () => {
Migrations.add('fix-incorrect-dates', () => {
const tables = [
AccountSettings,
TableVisibilityModeSettings,
Actions,
Activities,
Announcements,

View file

@ -1,3 +1,5 @@
//var nodemailer = require('nodemailer');
// buffer each user's email text in a queue, then flush them in single email
Meteor.startup(() => {
Notifications.subscribe('email', (user, title, description, params) => {
@ -38,6 +40,30 @@ Meteor.startup(() => {
const html = texts.join('<br/>\n\n');
user.clearEmailBuffer();
try {
/*
if (process.env.MAIL_SERVICE !== '') {
let transporter = nodemailer.createTransport({
service: process.env.MAIL_SERVICE,
auth: {
user: process.env.MAIL_SERVICE_USER,
pass: process.env.MAIL_SERVICE_PASSWORD
},
})
let info = transporter.sendMail({
to: user.emails[0].address.toLowerCase(),
from: Accounts.emailTemplates.from,
subject,
html,
})
} else {
Email.send({
to: user.emails[0].address.toLowerCase(),
from: Accounts.emailTemplates.from,
subject,
html,
});
}
*/
Email.send({
to: user.emails[0].address.toLowerCase(),
from: Accounts.emailTemplates.from,

View file

@ -34,27 +34,32 @@ Meteor.publish('attachmentsList', function() {
Meteor.publish('orphanedAttachments', function() {
let keys = [];
Attachments.find({}, { fields: { copies: 1 } }).forEach(att => {
keys.push(new ObjectID(att.copies.attachments.key));
});
keys.sort();
keys = _.uniq(keys, true);
return AttachmentStorage.find(
{ _id: { $nin: keys } },
{
fields: {
_id: 1,
filename: 1,
md5: 1,
length: 1,
contentType: 1,
metadata: 1,
if (Attachments.find({}, { fields: { copies: 1 } }) !== undefined) {
Attachments.find({}, { fields: { copies: 1 } }).forEach(att => {
keys.push(new ObjectID(att.copies.attachments.key));
});
keys.sort();
keys = _.uniq(keys, true);
return AttachmentStorage.find(
{ _id: { $nin: keys } },
{
fields: {
_id: 1,
filename: 1,
md5: 1,
length: 1,
contentType: 1,
metadata: 1,
},
sort: {
filename: 1,
},
limit: 250,
},
sort: {
filename: 1,
},
limit: 250,
},
);
);
} else {
return [];
}
});

View file

@ -129,6 +129,7 @@ Meteor.publishRelations('board', function(boardId, isArchived) {
this.cursor(Lists.find({ boardId, archived: isArchived }));
this.cursor(Swimlanes.find({ boardId, archived: isArchived }));
this.cursor(Integrations.find({ boardId }));
this.cursor(CardCommentReactions.find({ boardId }));
this.cursor(
CustomFields.find(
{ boardIds: { $in: [boardId] } },
@ -161,6 +162,8 @@ Meteor.publishRelations('board', function(boardId, isArchived) {
// Gather queries and send in bulk
const cardComments = this.join(CardComments);
cardComments.selector = _ids => ({ cardId: _ids });
const cardCommentReactions = this.join(CardCommentReactions);
cardCommentReactions.selector = _ids => ({ cardId: _ids });
const attachments = this.join(Attachments);
attachments.selector = _ids => ({ cardId: _ids });
const checklists = this.join(Checklists);
@ -194,12 +197,14 @@ Meteor.publishRelations('board', function(boardId, isArchived) {
checklists.push(cardId);
checklistItems.push(cardId);
parentCards.push(cardId);
cardCommentReactions.push(cardId)
},
);
// Send bulk queries for all found ids
subCards.send();
cardComments.send();
cardCommentReactions.send();
attachments.send();
checklists.send();
checklistItems.send();

View file

@ -53,7 +53,22 @@ const escapeForRegex = require('escape-string-regexp');
Meteor.publish('card', cardId => {
check(cardId, String);
return Cards.find({ _id: cardId });
const ret = Cards.find({ _id: cardId });
return ret;
});
/** publish all data which is necessary to display card details as popup
* @returns array of cursors
*/
Meteor.publishRelations('popupCardData', function(cardId) {
check(cardId, String);
this.cursor(
Cards.find({_id: cardId}),
function(cardId, card) {
this.cursor(Boards.find({_id: card.boardId}));
},
);
return this.ready()
});
Meteor.publish('myCards', function(sessionId) {
@ -113,7 +128,7 @@ function buildSelector(queryParams) {
let selector = {};
// eslint-disable-next-line no-console
console.log('queryParams:', queryParams);
// console.log('queryParams:', queryParams);
if (queryParams.selector) {
selector = queryParams.selector;
@ -405,7 +420,7 @@ function buildSelector(queryParams) {
const items = ChecklistItems.find(
{ title: regex },
{ fields: { cardId: 1 } },
{ fields: { cardId: 1, checklistId: 1 } },
);
const checklists = Checklists.find(
{
@ -424,23 +439,18 @@ function buildSelector(queryParams) {
{ fields: { cardId: 1 } },
);
selector.$and.push({
$or: [
let cardsSelector = [
{ title: regex },
{ description: regex },
{ customFields: { $elemMatch: { value: regex } } },
// {
// _id: {
// $in: CardComments.textSearch(userId, [queryParams.text]).map(
// com => com.cardId,
// ),
// },
// },
{ _id: { $in: checklists.map(list => list.cardId) } },
{ _id: { $in: attachments.map(attach => attach.cardId) } },
{ _id: { $in: comments.map(com => com.cardId) } },
],
});
];
if (queryParams.text == "false" || queryParams.text == "true") {
cardsSelector.push({ customFields: { $elemMatch: { value: queryParams.text == "true" ? true : false } } } );
}
selector.$and.push({ $or: cardsSelector });
}
if (selector.$and.length === 0) {
@ -449,9 +459,7 @@ function buildSelector(queryParams) {
}
// eslint-disable-next-line no-console
console.log('selector:', selector);
// eslint-disable-next-line no-console
console.log('selector.$and:', selector.$and);
//console.log('cards selector:', JSON.stringify(selector, null, 2));
const query = new Query();
query.selector = selector;
@ -497,6 +505,7 @@ function buildProjection(query) {
labelIds: 1,
customFields: 1,
userId: 1,
description: 1,
},
sort: {
boardId: 1,
@ -612,7 +621,7 @@ function findCards(sessionId, query) {
// console.log('selector:', query.selector);
// console.log('selector.$and:', query.selector.$and);
// eslint-disable-next-line no-console
// console.log('projection:', projection);
// console.log('projection:', query.projection);
const cards = Cards.find(query.selector, query.projection);
// eslint-disable-next-line no-console
@ -715,6 +724,7 @@ function findCards(sessionId, query) {
CustomFields.find({ _id: { $in: customFieldIds } }),
Users.find({ _id: { $in: users } }, { fields: Users.safeFields }),
Checklists.find({ cardId: { $in: cards.map(c => c._id) } }),
ChecklistItems.find({ cardId: { $in: cards.map(c => c._id) } }),
Attachments.find({ cardId: { $in: cards.map(c => c._id) } }),
CardComments.find({ cardId: { $in: cards.map(c => c._id) } }),
SessionData.find({ userId, sessionId }),

View file

@ -24,6 +24,9 @@ Meteor.publish('setting', () => {
displayAuthenticationMethod: 1,
defaultAuthenticationMethod: 1,
spinnerName: 1,
oidcBtnText: 1,
mailDomainName: 1,
legalNotice: 1,
},
},
);

View file

@ -0,0 +1,3 @@
Meteor.publish('tableVisibilityModeSettings', function() {
return TableVisibilityModeSettings.find();
});

View file

@ -25,6 +25,7 @@ Meteor.publish('user-admin', function() {
isAdmin: 1,
teams: 1,
orgs: 1,
authenticationMethod: 1,
},
});
});

View file

@ -1,3 +1,5 @@
//var nodemailer = require('nodemailer');
RulesHelper = {
executeRules(activity) {
const matchingRules = this.findMatchingRules(activity);
@ -45,8 +47,12 @@ RulesHelper = {
value = oldSwimlane.title;
}
}
let matchesList = [value, '*'];
if ((field === 'cardTitle') && (value !== undefined)) {
matchesList = value.split(/\W/).concat(matchesList);
}
matchingMap[field] = {
$in: [value, '*'],
$in: matchesList,
};
});
return matchingMap;
@ -119,6 +125,30 @@ RulesHelper = {
const text = action.emailMsg || '';
const subject = action.emailSubject || '';
try {
/*
if (process.env.MAIL_SERVICE !== '') {
let transporter = nodemailer.createTransport({
service: process.env.MAIL_SERVICE,
auth: {
user: process.env.MAIL_SERVICE_USER,
pass: process.env.MAIL_SERVICE_PASSWORD
},
})
let info = transporter.sendMail({
to,
from: Accounts.emailTemplates.from,
subject,
text,
})
} else {
Email.send({
to,
from: Accounts.emailTemplates.from,
subject,
text,
});
}
*/
Email.send({
to,
from: Accounts.emailTemplates.from,

View file

@ -1,5 +1,10 @@
import { MongoInternals } from 'meteor/mongo';
// Sandstorm context is detected using the METEOR_SETTINGS environment variable
// in the package definition.
const isSandstorm =
Meteor.settings && Meteor.settings.public && Meteor.settings.public.sandstorm;
if (Meteor.isServer) {
Meteor.methods({
getStatistics() {
@ -28,6 +33,35 @@ if (Meteor.isServer) {
pid: process.pid,
uptime: process.uptime(),
};
// Start: Show Nodejs heap stats at Standalone WeKan.
//
// Not shown at Sandstorm WeKan, because there's a bunch of machine performance data
// Sandstorm doesn't expose to apps to prevent side channel attacks.
if (!isSandstorm) {
const v8 = require('v8'); // Import the v8 module
statistics.nodeHeapStats = {
totalHeapSize: v8.getHeapStatistics().total_heap_size,
totalHeapSizeExecutable: v8.getHeapStatistics().total_heap_size_executable,
totalPhysicalSize: v8.getHeapStatistics().total_physical_size,
totalAvailableSize: v8.getHeapStatistics().total_available_size,
usedHeapSize: v8.getHeapStatistics().used_heap_size,
heapSizeLimit: v8.getHeapStatistics().heap_size_limit,
mallocedMemory: v8.getHeapStatistics().malloced_memory,
peakMallocedMemory: v8.getHeapStatistics().peak_malloced_memory,
doesZapGarbage: v8.getHeapStatistics().does_zap_garbage,
numberOfNativeContexts: v8.getHeapStatistics().number_of_native_contexts,
numberOfDetachedContexts: v8.getHeapStatistics().number_of_detached_contexts,
};
let memoryUsage = process.memoryUsage();
statistics.nodeMemoryUsage = {
rss: memoryUsage.rss,
heapTotal: memoryUsage.heapTotal,
heapUsed: memoryUsage.heapUsed,
external: memoryUsage.external,
};
}
// End: Show Nodejs heap stats at Standalone WeKan.
//
// Remove beginning of Meteor release text METEOR@
let meteorVersion = Meteor.release;
meteorVersion = meteorVersion.replace('METEOR@', '');