summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--models/activities.js6
-rw-r--r--models/integrations.js143
-rw-r--r--server/notifications/outgoing.js20
3 files changed, 152 insertions, 17 deletions
diff --git a/models/activities.js b/models/activities.js
index 208dd629..c732a940 100644
--- a/models/activities.js
+++ b/models/activities.js
@@ -140,9 +140,9 @@ if (Meteor.isServer) {
Notifications.notify(user, title, description, params);
});
- const integration = Integrations.findOne({ boardId: board._id, type: 'outgoing-webhooks', enabled: true });
- if (integration) {
- Meteor.call('outgoingWebhooks', integration, description, params);
+ const integrations = Integrations.find({ boardId: board._id, type: 'outgoing-webhooks', enabled: true, activities: { '$in': [description, 'all'] } }).fetch();
+ if (integrations.length > 0) {
+ Meteor.call('outgoingWebhooks', integrations, description, params);
}
});
}
diff --git a/models/integrations.js b/models/integrations.js
index b9bf248f..e9447f69 100644
--- a/models/integrations.js
+++ b/models/integrations.js
@@ -11,6 +11,11 @@ Integrations.attachSchema(new SimpleSchema({
},
type: {
type: String,
+ defaultValue: 'outgoing-webhooks',
+ },
+ activities: {
+ type: [String],
+ defaultValue: ['all'],
},
url: { // URL validation regex (https://mathiasbynens.be/demo/url-regex)
type: String,
@@ -35,11 +40,6 @@ Integrations.attachSchema(new SimpleSchema({
},
userId: {
type: String,
- autoValue() { // eslint-disable-line consistent-return
- if (this.isInsert || this.isUpdate) {
- return this.userId;
- }
- },
},
}));
@@ -52,3 +52,136 @@ Integrations.allow({
},
fetch: ['boardId'],
});
+
+//INTEGRATIONS REST API
+if (Meteor.isServer) {
+ // Get all integrations in board
+ JsonRoutes.add('GET', '/api/boards/:boardId/integrations', function(req, res, next) {
+ const paramBoardId = req.params.boardId;
+ Authentication.checkBoardAccess(req.userId, paramBoardId);
+
+ const data = Integrations.find({ boardId: paramBoardId }, { fields: { token: 0 } }).map(function(doc) {
+ return doc;
+ });
+
+ JsonRoutes.sendResult(res, {code: 200, data});
+ });
+
+ // Get a single integration in board
+ JsonRoutes.add('GET', '/api/boards/:boardId/integrations/:intId', function(req, res, next) {
+ const paramBoardId = req.params.boardId;
+ const paramIntId = req.params.intId;
+ Authentication.checkBoardAccess(req.userId, paramBoardId);
+
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: Integrations.findOne({ _id: paramIntId, boardId: paramBoardId }, { fields: { token: 0 } }),
+ });
+ });
+
+ // Create a new integration
+ JsonRoutes.add('POST', '/api/boards/:boardId/integrations', function(req, res, next) {
+ const paramBoardId = req.params.boardId;
+ Authentication.checkBoardAccess(req.userId, paramBoardId);
+
+ const id = Integrations.insert({
+ userId: req.userId,
+ boardId: paramBoardId,
+ url: req.body.url,
+ });
+
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: {
+ _id: id,
+ },
+ });
+ });
+
+ // Edit integration data
+ JsonRoutes.add('PUT', '/api/boards/:boardId/integrations/:intId', function (req, res, next) {
+ const paramBoardId = req.params.boardId;
+ const paramIntId = req.params.intId;
+ Authentication.checkBoardAccess(req.userId, paramBoardId);
+
+ if (req.body.hasOwnProperty('enabled')) {
+ const newEnabled = req.body.enabled;
+ Integrations.direct.update({_id: paramIntId, boardId: paramBoardId},
+ {$set: {enabled: newEnabled}});
+ }
+ if (req.body.hasOwnProperty('title')) {
+ const newTitle = req.body.title;
+ Integrations.direct.update({_id: paramIntId, boardId: paramBoardId},
+ {$set: {title: newTitle}});
+ }
+ if (req.body.hasOwnProperty('url')) {
+ const newUrl = req.body.url;
+ Integrations.direct.update({_id: paramIntId, boardId: paramBoardId},
+ {$set: {url: newUrl}});
+ }
+ if (req.body.hasOwnProperty('token')) {
+ const newToken = req.body.token;
+ Integrations.direct.update({_id: paramIntId, boardId: paramBoardId},
+ {$set: {token: newToken}});
+ }
+ if (req.body.hasOwnProperty('activities')) {
+ const newActivities = req.body.activities;
+ Integrations.direct.update({_id: paramIntId, boardId: paramBoardId},
+ {$set: {activities: newActivities}});
+ }
+
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: {
+ _id: paramIntId,
+ },
+ });
+ });
+
+ // Delete subscribed activities
+ JsonRoutes.add('DELETE', '/api/boards/:boardId/integrations/:intId/activities', function (req, res, next) {
+ const paramBoardId = req.params.boardId;
+ const paramIntId = req.params.intId;
+ const newActivities = req.body.activities;
+ Authentication.checkBoardAccess(req.userId, paramBoardId);
+
+ Integrations.direct.update({_id: paramIntId, boardId: paramBoardId},
+ {$pullAll: {activities: newActivities}});
+
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: Integrations.findOne({_id: paramIntId, boardId: paramBoardId}, { fields: {_id: 1, activities: 1}}),
+ });
+ });
+
+ // Add subscribed activities
+ JsonRoutes.add('POST', '/api/boards/:boardId/integrations/:intId/activities', function (req, res, next) {
+ const paramBoardId = req.params.boardId;
+ const paramIntId = req.params.intId;
+ const newActivities = req.body.activities;
+ Authentication.checkBoardAccess(req.userId, paramBoardId);
+
+ Integrations.direct.update({_id: paramIntId, boardId: paramBoardId},
+ {$addToSet: {activities: { $each: newActivities}}});
+
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: Integrations.findOne({_id: paramIntId, boardId: paramBoardId}, { fields: {_id: 1, activities: 1}}),
+ });
+ });
+
+ // Delete integration
+ JsonRoutes.add('DELETE', '/api/boards/:boardId/integrations/:intId', function (req, res, next) {
+ const paramBoardId = req.params.boardId;
+ const paramIntId = req.params.intId;
+ Authentication.checkBoardAccess(req.userId, paramBoardId);
+
+ Integrations.direct.remove({_id: paramIntId, boardId: paramBoardId});
+ JsonRoutes.sendResult(res, {
+ code: 200,
+ data: {
+ _id: paramIntId,
+ },
+ });
+ });
+}
diff --git a/server/notifications/outgoing.js b/server/notifications/outgoing.js
index c227366e..a4f24f92 100644
--- a/server/notifications/outgoing.js
+++ b/server/notifications/outgoing.js
@@ -9,8 +9,8 @@ const postCatchError = Meteor.wrapAsync((url, options, resolve) => {
});
Meteor.methods({
- outgoingWebhooks(integration, description, params) {
- check(integration, Object);
+ outgoingWebhooks(integrations, description, params) {
+ check(integrations, Array);
check(description, String);
check(params, Object);
@@ -19,7 +19,7 @@ Meteor.methods({
if (quoteParams[key]) quoteParams[key] = `"${params[key]}"`;
});
- const user = Users.findOne(integration.userId);
+ const user = Users.findOne(params.userId);
const text = `${params.user} ${TAPi18n.__(description, quoteParams, user.getLanguage())}\n${params.url}`;
if (text.length === 0) return;
@@ -41,12 +41,14 @@ Meteor.methods({
data: value,
};
- const response = postCatchError(integration.url, options);
+ integrations.forEach((integration) => {
+ const response = postCatchError(integration.url, options);
- if (response && response.statusCode && response.statusCode === 200) {
- return true; // eslint-disable-line consistent-return
- } else {
- throw new Meteor.Error('error-invalid-webhook-response');
- }
+ if (response && response.statusCode && response.statusCode === 200) {
+ return true; // eslint-disable-line consistent-return
+ } else {
+ throw new Meteor.Error('error-invalid-webhook-response');
+ }
+ });
},
});