diff options
author | Romulus Tsai 蔡仲明 <urakagi@gmail.com> | 2020-05-08 09:35:11 +0800 |
---|---|---|
committer | Romulus Tsai 蔡仲明 <urakagi@gmail.com> | 2020-05-08 09:35:11 +0800 |
commit | cfcc73724fcd394150d1b815d0a7a4c466e216b5 (patch) | |
tree | a9648255f14cd8b0e1ad8eee1f8d42337a0668bc /server | |
parent | a3658993128bdddd5d40f792c19281dc5eac51f5 (diff) | |
parent | 533bc045d06269dba2f42cdfe61817a1b3407974 (diff) | |
download | wekan-cfcc73724fcd394150d1b815d0a7a4c466e216b5.tar.gz wekan-cfcc73724fcd394150d1b815d0a7a4c466e216b5.tar.bz2 wekan-cfcc73724fcd394150d1b815d0a7a4c466e216b5.zip |
Merge branch 'master' of https://github.com/wekan/wekan
Diffstat (limited to 'server')
-rw-r--r-- | server/card-opened-webhook.js | 4 | ||||
-rw-r--r-- | server/migrations.js | 280 | ||||
-rw-r--r-- | server/notifications/outgoing.js | 361 | ||||
-rw-r--r-- | server/notifications/profile.js | 10 | ||||
-rw-r--r-- | server/publications/boards.js | 8 | ||||
-rw-r--r-- | server/publications/notifications.js | 101 | ||||
-rw-r--r-- | server/publications/users.js | 1 | ||||
-rw-r--r-- | server/rulesHelper.js | 74 | ||||
-rw-r--r-- | server/scroll.js | 15 | ||||
-rw-r--r-- | server/statistics.js | 138 |
10 files changed, 686 insertions, 306 deletions
diff --git a/server/card-opened-webhook.js b/server/card-opened-webhook.js index 242ae7ca..3c94d104 100644 --- a/server/card-opened-webhook.js +++ b/server/card-opened-webhook.js @@ -1,5 +1,7 @@ Meteor.startup(() => { - if (process.env.CARD_OPENED_WEBHOOK_ENABLED) { + if (process.env.CARD_OPENED_WEBHOOK_ENABLED === 'true') { Meteor.settings.public.CARD_OPENED_WEBHOOK_ENABLED = true; + } else { + Meteor.settings.public.CARD_OPENED_WEBHOOK_ENABLED = false; } }); diff --git a/server/migrations.js b/server/migrations.js index 92339110..a6c945fa 100644 --- a/server/migrations.js +++ b/server/migrations.js @@ -472,38 +472,6 @@ Migrations.add('add-hide-logo', () => { ); }); -Migrations.add('add-custom-html-after-body-start', () => { - Settings.update( - { - customHTMLafterBodyStart: { - $exists: false, - }, - }, - { - $set: { - customHTMLafterBodyStart: '', - }, - }, - noValidateMulti, - ); -}); - -Migrations.add('add-custom-html-before-body-end', () => { - Settings.update( - { - customHTMLbeforeBodyEnd: { - $exists: false, - }, - }, - { - $set: { - customHTMLbeforeBodyEnd: '', - }, - }, - noValidateMulti, - ); -}); - Migrations.add('add-displayAuthenticationMethod', () => { Settings.update( { @@ -825,3 +793,251 @@ Migrations.add('add-profile-hiddenMinicardLabelText', () => { noValidateMulti, ); }); + +Migrations.add('add-receiveddate-allowed', () => { + Boards.update( + { + allowsReceivedDate: { + $exists: false, + }, + }, + { + $set: { + allowsReceivedDate: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-startdate-allowed', () => { + Boards.update( + { + allowsStartDate: { + $exists: false, + }, + }, + { + $set: { + allowsStartDate: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-duedate-allowed', () => { + Boards.update( + { + allowsDueDate: { + $exists: false, + }, + }, + { + $set: { + allowsDueDate: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-enddate-allowed', () => { + Boards.update( + { + allowsEndDate: { + $exists: false, + }, + }, + { + $set: { + allowsEndDate: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-members-allowed', () => { + Boards.update( + { + allowsMembers: { + $exists: false, + }, + }, + { + $set: { + allowsMembers: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-assignee-allowed', () => { + Boards.update( + { + allowsAssignee: { + $exists: false, + }, + }, + { + $set: { + allowsAssignee: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-labels-allowed', () => { + Boards.update( + { + allowsLabels: { + $exists: false, + }, + }, + { + $set: { + allowsLabels: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-checklists-allowed', () => { + Boards.update( + { + allowsChecklists: { + $exists: false, + }, + }, + { + $set: { + allowsChecklists: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-attachments-allowed', () => { + Boards.update( + { + allowsAttachments: { + $exists: false, + }, + }, + { + $set: { + allowsAttachments: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-comments-allowed', () => { + Boards.update( + { + allowsComments: { + $exists: false, + }, + }, + { + $set: { + allowsComments: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-assigned-by-allowed', () => { + Boards.update( + { + allowsAssignedBy: { + $exists: false, + }, + }, + { + $set: { + allowsAssignedBy: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-requested-by-allowed', () => { + Boards.update( + { + allowsRequestedBy: { + $exists: false, + }, + }, + { + $set: { + allowsRequestedBy: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-activities-allowed', () => { + Boards.update( + { + allowsActivities: { + $exists: false, + }, + }, + { + $set: { + allowsActivities: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-description-title-allowed', () => { + Boards.update( + { + allowsDescriptionTitle: { + $exists: false, + }, + }, + { + $set: { + allowsDescriptionTitle: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-description-text-allowed', () => { + Boards.update( + { + allowsDescriptionText: { + $exists: false, + }, + }, + { + $set: { + allowsDescriptionText: true, + }, + }, + noValidateMulti, + ); +}); + +Migrations.add('add-sort-field-to-boards', () => { + Boards.find().forEach((board, index) => { + if (!board.hasOwnProperty('sort')) { + Boards.direct.update(board._id, { $set: { sort: index } }, noValidate); + } + }); +}); diff --git a/server/notifications/outgoing.js b/server/notifications/outgoing.js index 5bc2c540..9a741ea1 100644 --- a/server/notifications/outgoing.js +++ b/server/notifications/outgoing.js @@ -1,192 +1,199 @@ -const postCatchError = Meteor.wrapAsync((url, options, resolve) => { - HTTP.post(url, options, (err, res) => { - if (err) { - resolve(null, err.response); - } else { - resolve(null, res); - } +if (Meteor.isServer) { + const postCatchError = Meteor.wrapAsync((url, options, resolve) => { + HTTP.post(url, options, (err, res) => { + if (err) { + resolve(null, err.response); + } else { + resolve(null, res); + } + }); }); -}); -const Lock = { - _lock: {}, - _timer: {}, - echoDelay: 500, // echo should be happening much faster - normalDelay: 1e3, // normally user typed comment will be much slower - ECHO: 2, - NORMAL: 1, - NULL: 0, - has(id, value) { - const existing = this._lock[id]; - let ret = this.NULL; - if (existing) { - ret = existing === value ? this.ECHO : this.NORMAL; - } - return ret; - }, - clear(id, delay) { - const previous = this._timer[id]; - if (previous) { - Meteor.clearTimeout(previous); - } - this._timer[id] = Meteor.setTimeout(() => this.unset(id), delay); - }, - set(id, value) { - const state = this.has(id, value); - let delay = this.normalDelay; - if (state === this.ECHO) { - delay = this.echoDelay; - } - if (!value) { - // user commented, we set a lock - value = 1; - } - this._lock[id] = value; - this.clear(id, delay); // always auto reset the locker after delay - }, - unset(id) { - delete this._lock[id]; - }, -}; + const Lock = { + _lock: {}, + _timer: {}, + echoDelay: 500, // echo should be happening much faster + normalDelay: 1e3, // normally user typed comment will be much slower + ECHO: 2, + NORMAL: 1, + NULL: 0, + has(id, value) { + const existing = this._lock[id]; + let ret = this.NULL; + if (existing) { + ret = existing === value ? this.ECHO : this.NORMAL; + } + return ret; + }, + clear(id, delay) { + const previous = this._timer[id]; + if (previous) { + Meteor.clearTimeout(previous); + } + this._timer[id] = Meteor.setTimeout(() => this.unset(id), delay); + }, + set(id, value) { + const state = this.has(id, value); + let delay = this.normalDelay; + if (state === this.ECHO) { + delay = this.echoDelay; + } + if (!value) { + // user commented, we set a lock + value = 1; + } + this._lock[id] = value; + this.clear(id, delay); // always auto reset the locker after delay + }, + unset(id) { + delete this._lock[id]; + }, + }; -const webhooksAtbts = (process.env.WEBHOOKS_ATTRIBUTES && - process.env.WEBHOOKS_ATTRIBUTES.split(',')) || [ - 'cardId', - 'listId', - 'oldListId', - 'boardId', - 'comment', - 'user', - 'card', - 'commentId', - 'swimlaneId', -]; -const responseFunc = data => { - const paramCommentId = data.commentId; - const paramCardId = data.cardId; - const paramBoardId = data.boardId; - const newComment = data.comment; - if (paramCardId && paramBoardId && newComment) { - // only process data with the cardid, boardid and comment text, TODO can expand other functions here to react on returned data - const comment = CardComments.findOne({ - _id: paramCommentId, - cardId: paramCardId, - boardId: paramBoardId, - }); - const board = Boards.findOne(paramBoardId); - const card = Cards.findOne(paramCardId); - if (board && card) { - if (comment) { - Lock.set(comment._id, newComment); - CardComments.direct.update(comment._id, { - $set: { + const webhooksAtbts = (process.env.WEBHOOKS_ATTRIBUTES && + process.env.WEBHOOKS_ATTRIBUTES.split(',')) || [ + 'cardId', + 'listId', + 'oldListId', + 'boardId', + 'comment', + 'user', + 'card', + 'commentId', + 'swimlaneId', + ]; + const responseFunc = data => { + const paramCommentId = data.commentId; + const paramCardId = data.cardId; + const paramBoardId = data.boardId; + const newComment = data.comment; + if (paramCardId && paramBoardId && newComment) { + // only process data with the cardid, boardid and comment text, TODO can expand other functions here to react on returned data + const comment = CardComments.findOne({ + _id: paramCommentId, + cardId: paramCardId, + boardId: paramBoardId, + }); + const board = Boards.findOne(paramBoardId); + const card = Cards.findOne(paramCardId); + if (board && card) { + if (comment) { + Lock.set(comment._id, newComment); + CardComments.direct.update(comment._id, { + $set: { + text: newComment, + }, + }); + } + } else { + const userId = data.userId; + if (userId) { + const inserted = CardComments.direct.insert({ text: newComment, - }, - }); - } - } else { - const userId = data.userId; - if (userId) { - const inserted = CardComments.direct.insert({ - text: newComment, - userId, - cardId, - boardId, - }); - Lock.set(inserted._id, newComment); + userId, + cardId, + boardId, + }); + Lock.set(inserted._id, newComment); + } } } - } -}; -Meteor.methods({ - outgoingWebhooks(integration, description, params) { - check(integration, Object); - check(description, String); - check(params, Object); - this.unblock(); + }; + Meteor.methods({ + outgoingWebhooks(integration, description, params) { + if (Meteor.user()) { + check(integration, Object); + check(description, String); + check(params, Object); + this.unblock(); - // label activity did not work yet, see wekan/models/activities.js - const quoteParams = _.clone(params); - const clonedParams = _.clone(params); - [ - 'card', - 'list', - 'oldList', - 'board', - 'oldBoard', - 'comment', - 'checklist', - 'swimlane', - 'oldSwimlane', - 'label', - 'attachment', - ].forEach(key => { - if (quoteParams[key]) quoteParams[key] = `"${params[key]}"`; - }); + // label activity did not work yet, see wekan/models/activities.js + const quoteParams = _.clone(params); + const clonedParams = _.clone(params); + [ + '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 user = Users.findOne(userId); - const text = `${params.user} ${TAPi18n.__( - description, - quoteParams, - user.getLanguage(), - )}\n${params.url}`; + 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}`; - if (text.length === 0) return; + if (text.length === 0) return; - const value = { - text: `${text}`, - }; + const value = { + text: `${text}`, + }; - webhooksAtbts.forEach(key => { - if (params[key]) value[key] = params[key]; - }); - value.description = description; - //integrations.forEach(integration => { - const is2way = integration.type === Integrations.Const.TWOWAY; - const token = integration.token || ''; - const headers = { - 'Content-Type': 'application/json', - }; - if (token) headers['X-Wekan-Token'] = token; - const options = { - headers, - data: is2way ? { description, ...clonedParams } : value, - }; - const url = integration.url; - if (is2way) { - const cid = params.commentId; - const comment = params.comment; - const lockState = cid && Lock.has(cid, comment); - if (cid && lockState !== Lock.NULL) { - // it's a comment and there is a previous lock - return; - } else if (cid) { - Lock.set(cid, comment); // set a lock here - } - } - const response = postCatchError(url, options); + webhooksAtbts.forEach(key => { + if (params[key]) value[key] = params[key]; + }); + value.description = description; + //integrations.forEach(integration => { + const is2way = integration.type === Integrations.Const.TWOWAY; + const token = integration.token || ''; + const headers = { + 'Content-Type': 'application/json', + }; + if (token) headers['X-Wekan-Token'] = token; + const options = { + headers, + data: is2way ? { description, ...clonedParams } : value, + }; - if ( - response && - response.statusCode && - response.statusCode >= 200 && - response.statusCode < 300 - ) { - if (is2way) { - const data = response.data; // only an JSON encoded response will be actioned - if (data) { - try { - responseFunc(data); - } catch (e) { - throw new Meteor.Error('error-process-data'); + if (!Integrations.findOne({ url: integration.url })) return; + + const url = integration.url; + + if (is2way) { + const cid = params.commentId; + const comment = params.comment; + const lockState = cid && Lock.has(cid, comment); + if (cid && lockState !== Lock.NULL) { + // it's a comment and there is a previous lock + return; + } else if (cid) { + Lock.set(cid, comment); // set a lock here } } + const response = postCatchError(url, options); + + if ( + response && + response.statusCode && + response.statusCode >= 200 && + response.statusCode < 300 + ) { + if (is2way) { + const data = response.data; // only an JSON encoded response will be actioned + if (data) { + try { + responseFunc(data); + } catch (e) { + throw new Meteor.Error('error-process-data'); + } + } + } + return response; // eslint-disable-line consistent-return + } else { + throw new Meteor.Error('error-invalid-webhook-response'); + } } - return response; // eslint-disable-line consistent-return - } else { - throw new Meteor.Error('error-invalid-webhook-response'); - } - //}); - }, -}); + }, + }); +} diff --git a/server/notifications/profile.js b/server/notifications/profile.js index 6d9c7018..608931cf 100644 --- a/server/notifications/profile.js +++ b/server/notifications/profile.js @@ -1,9 +1,5 @@ Meteor.startup(() => { - // XXX: add activity id to profile.notifications, - // it can be displayed and rendered on web or mobile UI - // will uncomment the following code once UI implemented - // - // Notifications.subscribe('profile', (user, title, description, params) => { - // user.addNotification(params.activityId); - // }); + Notifications.subscribe('profile', (user, title, description, params) => { + user.addNotification(params.activityId); + }); }); diff --git a/server/publications/boards.js b/server/publications/boards.js index e3095833..b80a6b23 100644 --- a/server/publications/boards.js +++ b/server/publications/boards.js @@ -18,7 +18,7 @@ Meteor.publish('boards', function() { archived: false, $or: [ { - _id: { $in: starredBoards }, + // _id: { $in: starredBoards }, // Commented out, to get a list of all public boards permission: 'public', }, { members: { $elemMatch: { userId, isActive: true } } }, @@ -35,7 +35,9 @@ Meteor.publish('boards', function() { members: 1, permission: 1, type: 1, + sort: 1, }, + sort: { sort: 1 /* boards default sorting */ }, }, ); }); @@ -61,6 +63,7 @@ Meteor.publish('archivedBoards', function() { slug: 1, title: 1, }, + sort: { sort: 1 /* boards default sorting */ }, }, ); }); @@ -90,7 +93,7 @@ Meteor.publishRelations('board', function(boardId, isArchived) { $or, // Sort required to ensure oplog usage }, - { limit: 1, sort: { _id: 1 } }, + { limit: 1, sort: { sort: 1 /* boards default sorting */ } }, ), function(boardId, board) { this.cursor(Lists.find({ boardId, archived: isArchived })); @@ -192,6 +195,7 @@ Meteor.publishRelations('board', function(boardId, isArchived) { username: 1, 'profile.fullname': 1, 'profile.avatarUrl': 1, + 'profile.initials': 1, }, }, ), diff --git a/server/publications/notifications.js b/server/publications/notifications.js new file mode 100644 index 00000000..bc55a37c --- /dev/null +++ b/server/publications/notifications.js @@ -0,0 +1,101 @@ +// We use these when displaying notifications in the notificationsDrawer + +// gets all activities associated with the current user +Meteor.publish('notificationActivities', () => { + return activities(); +}); + +// gets all attachments associated with activities associated with the current user +Meteor.publish('notificationAttachments', function() { + return Attachments.find({ + _id: { + $in: activities() + .map(v => v.attachmentId) + .filter(v => !!v), + }, + }); +}); + +// gets all cards associated with activities associated with the current user +Meteor.publish('notificationCards', function() { + return Cards.find({ + _id: { + $in: activities() + .map(v => v.cardId) + .filter(v => !!v), + }, + }); +}); + +// gets all checklistItems associated with activities associated with the current user +Meteor.publish('notificationChecklistItems', function() { + return ChecklistItems.find({ + _id: { + $in: activities() + .map(v => v.checklistItemId) + .filter(v => !!v), + }, + }); +}); + +// gets all checklists associated with activities associated with the current user +Meteor.publish('notificationChecklists', function() { + return Checklists.find({ + _id: { + $in: activities() + .map(v => v.checklistId) + .filter(v => !!v), + }, + }); +}); + +// gets all comments associated with activities associated with the current user +Meteor.publish('notificationComments', function() { + return CardComments.find({ + _id: { + $in: activities() + .map(v => v.commentId) + .filter(v => !!v), + }, + }); +}); + +// gets all lists associated with activities associated with the current user +Meteor.publish('notificationLists', function() { + return Lists.find({ + _id: { + $in: activities() + .map(v => v.listId) + .filter(v => !!v), + }, + }); +}); + +// gets all swimlanes associated with activities associated with the current user +Meteor.publish('notificationSwimlanes', function() { + return Swimlanes.find({ + _id: { + $in: activities() + .map(v => v.swimlaneId) + .filter(v => !!v), + }, + }); +}); + +// gets all users associated with activities associated with the current user +Meteor.publish('notificationUsers', function() { + return Users.find({ + _id: { + $in: activities() + .map(v => v.userId) + .filter(v => !!v), + }, + }); +}); + +function activities() { + const notifications = Meteor.user().profile.notifications || []; + return Activities.find({ + _id: { $in: notifications.map(v => v.activity) }, + }); +} diff --git a/server/publications/users.js b/server/publications/users.js index 59411ca0..c04f8c5c 100644 --- a/server/publications/users.js +++ b/server/publications/users.js @@ -6,6 +6,7 @@ Meteor.publish('user-miniprofile', function(userId) { username: 1, 'profile.fullname': 1, 'profile.avatarUrl': 1, + 'profile.initials': 1, }, }); }); diff --git a/server/rulesHelper.js b/server/rulesHelper.js index cf278c52..63e330ab 100644 --- a/server/rulesHelper.js +++ b/server/rulesHelper.js @@ -42,35 +42,65 @@ RulesHelper = { performAction(activity, action) { const card = Cards.findOne({ _id: activity.cardId }); const boardId = activity.boardId; - if (action.actionType === 'moveCardToTop') { - let listId; + if ( + action.actionType === 'moveCardToTop' || + action.actionType === 'moveCardToBottom' + ) { let list; - if (action.listTitle === '*') { - listId = card.listId; + let listId; + if (action.listName === '*') { list = card.list(); + if (boardId !== action.boardId) { + list = Lists.findOne({ title: list.title, boardId: action.boardId }); + } } else { - list = Lists.findOne({ title: action.listTitle, boardId }); - listId = list._id; + list = Lists.findOne({ + title: action.listName, + boardId: action.boardId, + }); } - const minOrder = _.min( - list.cardsUnfiltered(card.swimlaneId).map(c => c.sort), - ); - card.move(boardId, card.swimlaneId, listId, minOrder - 1); - } - if (action.actionType === 'moveCardToBottom') { - let listId; - let list; - if (action.listTitle === '*') { - listId = card.listId; - list = card.list(); + if (list === undefined) { + listId = ''; } else { - list = Lists.findOne({ title: action.listTitle, boardId }); listId = list._id; } - const maxOrder = _.max( - list.cardsUnfiltered(card.swimlaneId).map(c => c.sort), - ); - card.move(boardId, card.swimlaneId, listId, maxOrder + 1); + + let swimlane; + let swimlaneId; + if (action.swimlaneName === '*') { + swimlane = Swimlanes.findOne(card.swimlaneId); + if (boardId !== action.boardId) { + swimlane = Swimlanes.findOne({ + title: swimlane.title, + boardId: action.boardId, + }); + } + } else { + swimlane = Swimlanes.findOne({ + title: action.swimlaneName, + boardId: action.boardId, + }); + } + if (swimlane === undefined) { + swimlaneId = Swimlanes.findOne({ + title: 'Default', + boardId: action.boardId, + })._id; + } else { + swimlaneId = swimlane._id; + } + + if (action.actionType === 'moveCardToTop') { + const minOrder = _.min( + list.cardsUnfiltered(swimlaneId).map(c => c.sort), + ); + card.move(action.boardId, swimlaneId, listId, minOrder - 1); + } else { + const maxOrder = _.max( + list.cardsUnfiltered(swimlaneId).map(c => c.sort), + ); + card.move(action.boardId, swimlaneId, listId, maxOrder + 1); + } } if (action.actionType === 'sendEmail') { const to = action.emailTo; diff --git a/server/scroll.js b/server/scroll.js new file mode 100644 index 00000000..c2cc797e --- /dev/null +++ b/server/scroll.js @@ -0,0 +1,15 @@ +Meteor.startup(() => { + // Mouse Scroll Intertia, issue #2949. Integer. + if (process.env.SCROLLINERTIA !== '0') { + Meteor.settings.public.SCROLLINERTIA = process.env.SCROLLINERTIA; + } else { + Meteor.settings.public.SCROLLINERTIA = 0; + } + + // Mouse Scroll Amount, issue #2949. "auto" or Integer. + if (process.env.SCROLLAMOUNT !== 'auto') { + Meteor.settings.public.SCROLLAMOUNT = process.env.SCROLLAMOUNT; + } else { + Meteor.settings.public.SCROLLAMOUNT = 'auto'; + } +}); diff --git a/server/statistics.js b/server/statistics.js index 997fd86f..0ead840f 100644 --- a/server/statistics.js +++ b/server/statistics.js @@ -1,68 +1,76 @@ import { MongoInternals } from 'meteor/mongo'; -Meteor.methods({ - getStatistics() { - const os = require('os'); - const pjson = require('/package.json'); - const statistics = {}; - let wekanVersion = pjson.version; - wekanVersion = wekanVersion.replace('v', ''); - statistics.version = wekanVersion; - statistics.os = { - type: os.type(), - platform: os.platform(), - arch: os.arch(), - release: os.release(), - uptime: os.uptime(), - loadavg: os.loadavg(), - totalmem: os.totalmem(), - freemem: os.freemem(), - cpus: os.cpus(), - }; - let nodeVersion = process.version; - nodeVersion = nodeVersion.replace('v', ''); - statistics.process = { - nodeVersion, - pid: process.pid, - uptime: process.uptime(), - }; - // Remove beginning of Meteor release text METEOR@ - let meteorVersion = Meteor.release; - meteorVersion = meteorVersion.replace('METEOR@', ''); - statistics.meteor = { - meteorVersion, - }; - // Thanks to RocketChat for MongoDB version detection ! - // https://github.com/RocketChat/Rocket.Chat/blob/develop/app/utils/server/functions/getMongoInfo.js - let mongoVersion; - let mongoStorageEngine; - let mongoOplogEnabled; - try { - const { mongo } = MongoInternals.defaultRemoteCollectionDriver(); - oplogEnabled = Boolean( - mongo._oplogHandle && mongo._oplogHandle.onOplogEntry, - ); - const { version, storageEngine } = Promise.await( - mongo.db.command({ serverStatus: 1 }), - ); - mongoVersion = version; - mongoStorageEngine = storageEngine.name; - mongoOplogEnabled = oplogEnabled; - } catch (e) { - try { - const { version } = Promise.await(mongo.db.command({ buildinfo: 1 })); - mongoVersion = version; - mongoStorageEngine = 'unknown'; - } catch (e) { - mongoVersion = 'unknown'; - mongoStorageEngine = 'unknown'; +if (Meteor.isServer) { + Meteor.methods({ + getStatistics() { + if (Meteor.user() && Meteor.user().isAdmin) { + const os = require('os'); + const pjson = require('/package.json'); + const statistics = {}; + let wekanVersion = pjson.version; + wekanVersion = wekanVersion.replace('v', ''); + statistics.version = wekanVersion; + statistics.os = { + type: os.type(), + platform: os.platform(), + arch: os.arch(), + release: os.release(), + uptime: os.uptime(), + loadavg: os.loadavg(), + totalmem: os.totalmem(), + freemem: os.freemem(), + cpus: os.cpus(), + }; + let nodeVersion = process.version; + nodeVersion = nodeVersion.replace('v', ''); + statistics.process = { + nodeVersion, + pid: process.pid, + uptime: process.uptime(), + }; + // Remove beginning of Meteor release text METEOR@ + let meteorVersion = Meteor.release; + meteorVersion = meteorVersion.replace('METEOR@', ''); + statistics.meteor = { + meteorVersion, + }; + // Thanks to RocketChat for MongoDB version detection ! + // https://github.com/RocketChat/Rocket.Chat/blob/develop/app/utils/server/functions/getMongoInfo.js + let mongoVersion; + let mongoStorageEngine; + let mongoOplogEnabled; + try { + const { mongo } = MongoInternals.defaultRemoteCollectionDriver(); + oplogEnabled = Boolean( + mongo._oplogHandle && mongo._oplogHandle.onOplogEntry, + ); + const { version, storageEngine } = Promise.await( + mongo.db.command({ serverStatus: 1 }), + ); + mongoVersion = version; + mongoStorageEngine = storageEngine.name; + mongoOplogEnabled = oplogEnabled; + } catch (e) { + try { + const { version } = Promise.await( + mongo.db.command({ buildinfo: 1 }), + ); + mongoVersion = version; + mongoStorageEngine = 'unknown'; + } catch (e) { + mongoVersion = 'unknown'; + mongoStorageEngine = 'unknown'; + } + } + statistics.mongo = { + mongoVersion, + mongoStorageEngine, + mongoOplogEnabled, + }; + return statistics; + } else { + return false; } - } - statistics.mongo = { - mongoVersion, - mongoStorageEngine, - mongoOplogEnabled, - }; - return statistics; - }, -}); + }, + }); +} |