wekan/models/integrations.js

414 lines
10 KiB
JavaScript

import { ReactiveCache } from '/imports/reactiveCache';
Integrations = new Mongo.Collection('integrations');
/**
* Integration with third-party applications
*/
Integrations.attachSchema(
new SimpleSchema({
enabled: {
/**
* is the integration enabled?
*/
type: Boolean,
defaultValue: true,
},
title: {
/**
* name of the integration
*/
type: String,
optional: true,
},
type: {
/**
* type of the integratation (Default to 'outgoing-webhooks')
*/
type: String,
defaultValue: 'outgoing-webhooks',
},
activities: {
/**
* activities the integration gets triggered (list)
*/
type: [String],
defaultValue: ['all'],
},
url: {
// URL validation regex (https://mathiasbynens.be/demo/url-regex)
/**
* URL validation regex (https://mathiasbynens.be/demo/url-regex)
*/
type: String,
},
token: {
/**
* token of the integration
*/
type: String,
optional: true,
},
boardId: {
/**
* Board ID of the integration
*/
type: String,
},
createdAt: {
/**
* Creation date of the integration
*/
type: Date,
denyUpdate: false,
// eslint-disable-next-line consistent-return
autoValue() {
if (this.isInsert) {
return new Date();
} else if (this.isUpsert) {
return { $setOnInsert: new Date() };
} else {
this.unset();
}
},
},
modifiedAt: {
type: Date,
denyUpdate: false,
// eslint-disable-next-line consistent-return
autoValue() {
if (this.isInsert || this.isUpsert || this.isUpdate) {
return new Date();
} else {
this.unset();
}
},
},
userId: {
/**
* user ID who created the interation
*/
type: String,
},
}),
);
Integrations.Const = {
GLOBAL_WEBHOOK_ID: '_global',
ONEWAY: 'outgoing-webhooks',
TWOWAY: 'bidirectional-webhooks',
get WEBHOOK_TYPES() {
return [this.ONEWAY, this.TWOWAY];
},
};
const permissionHelper = {
allow(userId, doc) {
const user = ReactiveCache.getUser(userId);
const isAdmin = user && ReactiveCache.getCurrentUser().isAdmin;
return isAdmin || allowIsBoardAdmin(userId, ReactiveCache.getBoard(doc.boardId));
},
};
Integrations.allow({
insert(userId, doc) {
return permissionHelper.allow(userId, doc);
},
update(userId, doc) {
return permissionHelper.allow(userId, doc);
},
remove(userId, doc) {
return permissionHelper.allow(userId, doc);
},
fetch: ['boardId'],
});
//INTEGRATIONS REST API
if (Meteor.isServer) {
Meteor.startup(() => {
Integrations._collection.createIndex({ modifiedAt: -1 });
Integrations._collection.createIndex({ boardId: 1 });
});
/**
* @operation get_all_integrations
* @summary Get all integrations in board
*
* @param {string} boardId the board ID
* @return_type [Integrations]
*/
JsonRoutes.add('GET', '/api/boards/:boardId/integrations', function(
req,
res,
) {
try {
const paramBoardId = req.params.boardId;
Authentication.checkBoardAccess(req.userId, paramBoardId);
const data = ReactiveCache.getIntegrations(
{ boardId: paramBoardId },
{ fields: { token: 0 } },
).map(function(doc) {
return doc;
});
JsonRoutes.sendResult(res, { code: 200, data });
} catch (error) {
JsonRoutes.sendResult(res, {
code: 200,
data: error,
});
}
});
/**
* @operation get_integration
* @summary Get a single integration in board
*
* @param {string} boardId the board ID
* @param {string} intId the integration ID
* @return_type Integrations
*/
JsonRoutes.add('GET', '/api/boards/:boardId/integrations/:intId', function(
req,
res,
) {
try {
const paramBoardId = req.params.boardId;
const paramIntId = req.params.intId;
Authentication.checkBoardAccess(req.userId, paramBoardId);
JsonRoutes.sendResult(res, {
code: 200,
data: ReactiveCache.getIntegration(
{ _id: paramIntId, boardId: paramBoardId },
{ fields: { token: 0 } },
),
});
} catch (error) {
JsonRoutes.sendResult(res, {
code: 200,
data: error,
});
}
});
/**
* @operation new_integration
* @summary Create a new integration
*
* @param {string} boardId the board ID
* @param {string} url the URL of the integration
* @return_type {_id: string}
*/
JsonRoutes.add('POST', '/api/boards/:boardId/integrations', function(
req,
res,
) {
try {
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,
},
});
} catch (error) {
JsonRoutes.sendResult(res, {
code: 200,
data: error,
});
}
});
/**
* @operation edit_integration
* @summary Edit integration data
*
* @param {string} boardId the board ID
* @param {string} intId the integration ID
* @param {string} [enabled] is the integration enabled?
* @param {string} [title] new name of the integration
* @param {string} [url] new URL of the integration
* @param {string} [token] new token of the integration
* @param {string} [activities] new list of activities of the integration
* @return_type {_id: string}
*/
JsonRoutes.add('PUT', '/api/boards/:boardId/integrations/:intId', function(
req,
res,
) {
try {
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,
},
});
} catch (error) {
JsonRoutes.sendResult(res, {
code: 200,
data: error,
});
}
});
/**
* @operation delete_integration_activities
* @summary Delete subscribed activities
*
* @param {string} boardId the board ID
* @param {string} intId the integration ID
* @param {string} newActivities the activities to remove from the integration
* @return_type Integrations
*/
JsonRoutes.add(
'DELETE',
'/api/boards/:boardId/integrations/:intId/activities',
function(req, res) {
try {
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: ReactiveCache.getIntegration(
{ _id: paramIntId, boardId: paramBoardId },
{ fields: { _id: 1, activities: 1 } },
),
});
} catch (error) {
JsonRoutes.sendResult(res, {
code: 200,
data: error,
});
}
},
);
/**
* @operation new_integration_activities
* @summary Add subscribed activities
*
* @param {string} boardId the board ID
* @param {string} intId the integration ID
* @param {string} newActivities the activities to add to the integration
* @return_type Integrations
*/
JsonRoutes.add(
'POST',
'/api/boards/:boardId/integrations/:intId/activities',
function(req, res) {
try {
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: ReactiveCache.getIntegration(
{ _id: paramIntId, boardId: paramBoardId },
{ fields: { _id: 1, activities: 1 } },
),
});
} catch (error) {
JsonRoutes.sendResult(res, {
code: 200,
data: error,
});
}
},
);
/**
* @operation delete_integration
* @summary Delete integration
*
* @param {string} boardId the board ID
* @param {string} intId the integration ID
* @return_type {_id: string}
*/
JsonRoutes.add('DELETE', '/api/boards/:boardId/integrations/:intId', function(
req,
res,
) {
try {
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,
},
});
} catch (error) {
JsonRoutes.sendResult(res, {
code: 200,
data: error,
});
}
});
}
export default Integrations;