+# Optional fields: accessToken, events, excludedEvents
+# WEBHOOKS='[{
+# "url": "http://localhost:3001",
+# "accessToken": "notaccesstoken",
+# "events": ["cardCreate", "cardUpdate", "cardDelete"],
+# "excludedEvents": ["notificationCreate", "notificationUpdate"]
+# }]'
+
# SLACK_BOT_TOKEN=
# SLACK_CHANNEL_ID=
-# WEBHOOK_URL=
-# WEBHOOK_BEARER=
-
## Do not edit this
TZ=UTC
diff --git a/server/api/controllers/access-tokens/exchange-using-oidc.js b/server/api/controllers/access-tokens/exchange-using-oidc.js
index 469d4462..874d1d70 100644
--- a/server/api/controllers/access-tokens/exchange-using-oidc.js
+++ b/server/api/controllers/access-tokens/exchange-using-oidc.js
@@ -4,6 +4,9 @@ const Errors = {
INVALID_CODE_OR_NONCE: {
invalidCodeOrNonce: 'Invalid code or nonce',
},
+ INVALID_USERINFO_SIGNATURE: {
+ invalidUserinfoSignature: 'Invalid signature on userinfo due to client misconfiguration',
+ },
EMAIL_ALREADY_IN_USE: {
emailAlreadyInUse: 'Email already in use',
},
@@ -31,6 +34,9 @@ module.exports = {
invalidCodeOrNonce: {
responseType: 'unauthorized',
},
+ invalidUserinfoSignature: {
+ responseType: 'unauthorized',
+ },
emailAlreadyInUse: {
responseType: 'conflict',
},
@@ -51,6 +57,7 @@ module.exports = {
sails.log.warn(`Invalid code or nonce! (IP: ${remoteAddress})`);
return Errors.INVALID_CODE_OR_NONCE;
})
+ .intercept('invalidUserinfoSignature', () => Errors.INVALID_USERINFO_SIGNATURE)
.intercept('emailAlreadyInUse', () => Errors.EMAIL_ALREADY_IN_USE)
.intercept('usernameAlreadyInUse', () => Errors.USERNAME_ALREADY_IN_USE)
.intercept('missingValues', () => Errors.MISSING_VALUES);
diff --git a/server/api/controllers/attachments/create.js b/server/api/controllers/attachments/create.js
index 1ffe9627..03e0c8cf 100644
--- a/server/api/controllers/attachments/create.js
+++ b/server/api/controllers/attachments/create.js
@@ -44,12 +44,12 @@ module.exports = {
async fn(inputs, exits) {
const { currentUser } = this.req;
- const { card, board } = await sails.helpers.cards
+ const { card, list, board, project } = await sails.helpers.cards
.getProjectPath(inputs.cardId)
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
const boardMembership = await BoardMembership.findOne({
- boardId: card.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -83,12 +83,14 @@ module.exports = {
const fileData = await sails.helpers.attachments.processUploadedFile(file);
const attachment = await sails.helpers.attachments.createOne.with({
+ project,
+ board,
+ list,
values: {
...fileData,
card,
creatorUser: currentUser,
},
- board,
requestId: inputs.requestId,
request: this.req,
});
diff --git a/server/api/controllers/attachments/delete.js b/server/api/controllers/attachments/delete.js
index 697f749d..c0b0d666 100755
--- a/server/api/controllers/attachments/delete.js
+++ b/server/api/controllers/attachments/delete.js
@@ -33,7 +33,7 @@ module.exports = {
.intercept('pathNotFound', () => Errors.ATTACHMENT_NOT_FOUND);
let { attachment } = path;
- const { card, board } = path;
+ const { card, list, board, project } = path;
const boardMembership = await BoardMembership.findOne({
boardId: board.id,
@@ -49,9 +49,12 @@ module.exports = {
}
attachment = await sails.helpers.attachments.deleteOne.with({
+ project,
board,
+ list,
card,
record: attachment,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/attachments/update.js b/server/api/controllers/attachments/update.js
index 90e51bab..752d86db 100755
--- a/server/api/controllers/attachments/update.js
+++ b/server/api/controllers/attachments/update.js
@@ -37,7 +37,7 @@ module.exports = {
.intercept('pathNotFound', () => Errors.ATTACHMENT_NOT_FOUND);
let { attachment } = path;
- const { board } = path;
+ const { card, list, board, project } = path;
const boardMembership = await BoardMembership.findOne({
boardId: board.id,
@@ -56,8 +56,12 @@ module.exports = {
attachment = await sails.helpers.attachments.updateOne.with({
values,
+ project,
board,
+ list,
+ card,
record: attachment,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/board-memberships/create.js b/server/api/controllers/board-memberships/create.js
index 7c70fa5b..f5337a66 100755
--- a/server/api/controllers/board-memberships/create.js
+++ b/server/api/controllers/board-memberships/create.js
@@ -48,14 +48,11 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { board } = await sails.helpers.boards
+ const { board, project } = await sails.helpers.boards
.getProjectPath(inputs.boardId)
.intercept('pathNotFound', () => Errors.BOARD_NOT_FOUND);
- const isProjectManager = await sails.helpers.users.isProjectManager(
- currentUser.id,
- board.projectId,
- );
+ const isProjectManager = await sails.helpers.users.isProjectManager(currentUser.id, project.id);
if (!isProjectManager) {
throw Errors.BOARD_NOT_FOUND; // Forbidden
@@ -71,11 +68,13 @@ module.exports = {
const boardMembership = await sails.helpers.boardMemberships.createOne
.with({
+ project,
values: {
...values,
board,
user,
},
+ actorUser: currentUser,
request: this.req,
})
.intercept('userAlreadyBoardMember', () => Errors.USER_ALREADY_BOARD_MEMBER);
diff --git a/server/api/controllers/board-memberships/delete.js b/server/api/controllers/board-memberships/delete.js
index b9d6021c..48c073fd 100755
--- a/server/api/controllers/board-memberships/delete.js
+++ b/server/api/controllers/board-memberships/delete.js
@@ -27,7 +27,7 @@ module.exports = {
.intercept('pathNotFound', () => Errors.BOARD_MEMBERSHIP_NOT_FOUND);
let { boardMembership } = path;
- const { project } = path;
+ const { board, project } = path;
if (boardMembership.userId !== currentUser.id) {
const isProjectManager = await sails.helpers.users.isProjectManager(
@@ -42,7 +42,9 @@ module.exports = {
boardMembership = await sails.helpers.boardMemberships.deleteOne.with({
project,
+ board,
record: boardMembership,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/board-memberships/update.js b/server/api/controllers/board-memberships/update.js
index 695b2b8a..d1ac0539 100644
--- a/server/api/controllers/board-memberships/update.js
+++ b/server/api/controllers/board-memberships/update.js
@@ -35,7 +35,7 @@ module.exports = {
.intercept('pathNotFound', () => Errors.BOARD_MEMBERSHIP_NOT_FOUND);
let { boardMembership } = path;
- const { project } = path;
+ const { board, project } = path;
const isProjectManager = await sails.helpers.users.isProjectManager(currentUser.id, project.id);
@@ -47,7 +47,10 @@ module.exports = {
boardMembership = await sails.helpers.boardMemberships.updateOne.with({
values,
+ project,
+ board,
record: boardMembership,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/boards/create.js b/server/api/controllers/boards/create.js
index 207180bc..990cb85a 100755
--- a/server/api/controllers/boards/create.js
+++ b/server/api/controllers/boards/create.js
@@ -103,7 +103,7 @@ module.exports = {
project,
},
import: boardImport,
- user: currentUser,
+ actorUser: currentUser,
requestId: inputs.requestId,
request: this.req,
});
diff --git a/server/api/controllers/boards/delete.js b/server/api/controllers/boards/delete.js
index 9d0fc5cd..f834576d 100755
--- a/server/api/controllers/boards/delete.js
+++ b/server/api/controllers/boards/delete.js
@@ -22,25 +22,27 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- let { board } = await sails.helpers.boards
+ const path = await sails.helpers.boards
.getProjectPath(inputs.id)
.intercept('pathNotFound', () => Errors.BOARD_NOT_FOUND);
+ let { board } = path;
+ const { project } = path;
+
if (!board) {
throw Errors.BOARD_NOT_FOUND;
}
- const isProjectManager = await sails.helpers.users.isProjectManager(
- currentUser.id,
- board.projectId,
- );
+ const isProjectManager = await sails.helpers.users.isProjectManager(currentUser.id, project.id);
if (!isProjectManager) {
throw Errors.BOARD_NOT_FOUND; // Forbidden
}
board = await sails.helpers.boards.deleteOne.with({
+ project,
record: board,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/boards/update.js b/server/api/controllers/boards/update.js
index 85c2d01c..2ffb5741 100755
--- a/server/api/controllers/boards/update.js
+++ b/server/api/controllers/boards/update.js
@@ -29,18 +29,18 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- let { board } = await sails.helpers.boards
+ const path = await sails.helpers.boards
.getProjectPath(inputs.id)
.intercept('pathNotFound', () => Errors.BOARD_NOT_FOUND);
+ let { board } = path;
+ const { project } = path;
+
if (!board) {
throw Errors.BOARD_NOT_FOUND;
}
- const isProjectManager = await sails.helpers.users.isProjectManager(
- currentUser.id,
- board.projectId,
- );
+ const isProjectManager = await sails.helpers.users.isProjectManager(currentUser.id, project.id);
if (!isProjectManager) {
throw Errors.BOARD_NOT_FOUND; // Forbidden
@@ -50,7 +50,9 @@ module.exports = {
board = await sails.helpers.boards.updateOne.with({
values,
+ project,
record: board,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/card-labels/create.js b/server/api/controllers/card-labels/create.js
index 207619af..68341372 100755
--- a/server/api/controllers/card-labels/create.js
+++ b/server/api/controllers/card-labels/create.js
@@ -45,12 +45,12 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { card } = await sails.helpers.cards
+ const { card, list, board, project } = await sails.helpers.cards
.getProjectPath(inputs.cardId)
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
const boardMembership = await BoardMembership.findOne({
- boardId: card.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -64,7 +64,7 @@ module.exports = {
const label = await Label.findOne({
id: inputs.labelId,
- boardId: card.boardId,
+ boardId: board.id,
});
if (!label) {
@@ -73,10 +73,14 @@ module.exports = {
const cardLabel = await sails.helpers.cardLabels.createOne
.with({
+ project,
+ board,
+ list,
values: {
card,
label,
},
+ actorUser: currentUser,
request: this.req,
})
.intercept('labelAlreadyInCard', () => Errors.LABEL_ALREADY_IN_CARD);
diff --git a/server/api/controllers/card-labels/delete.js b/server/api/controllers/card-labels/delete.js
index 2911bce4..23b4c9c9 100755
--- a/server/api/controllers/card-labels/delete.js
+++ b/server/api/controllers/card-labels/delete.js
@@ -39,7 +39,7 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { board } = await sails.helpers.cards
+ const { card, list, board, project } = await sails.helpers.cards
.getProjectPath(inputs.cardId)
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
@@ -66,8 +66,12 @@ module.exports = {
}
cardLabel = await sails.helpers.cardLabels.deleteOne.with({
+ project,
board,
+ list,
+ card,
record: cardLabel,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/card-memberships/create.js b/server/api/controllers/card-memberships/create.js
index 9143cc91..14f544ef 100755
--- a/server/api/controllers/card-memberships/create.js
+++ b/server/api/controllers/card-memberships/create.js
@@ -45,12 +45,12 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { card, board } = await sails.helpers.cards
+ const { card, list, board, project } = await sails.helpers.cards
.getProjectPath(inputs.cardId)
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
const boardMembership = await BoardMembership.findOne({
- boardId: card.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -62,7 +62,7 @@ module.exports = {
throw Errors.NOT_ENOUGH_RIGHTS;
}
- const isBoardMember = await sails.helpers.users.isBoardMember(inputs.userId, card.boardId);
+ const isBoardMember = await sails.helpers.users.isBoardMember(inputs.userId, board.id);
if (!isBoardMember) {
throw Errors.USER_NOT_FOUND;
@@ -70,11 +70,14 @@ module.exports = {
const cardMembership = await sails.helpers.cardMemberships.createOne
.with({
+ project,
+ board,
+ list,
values: {
card,
userId: inputs.userId,
},
- board,
+ actorUser: currentUser,
request: this.req,
})
.intercept('userAlreadyCardMember', () => Errors.USER_ALREADY_CARD_MEMBER);
diff --git a/server/api/controllers/card-memberships/delete.js b/server/api/controllers/card-memberships/delete.js
index 4b9d7547..297c93b4 100755
--- a/server/api/controllers/card-memberships/delete.js
+++ b/server/api/controllers/card-memberships/delete.js
@@ -39,7 +39,7 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { board, card } = await sails.helpers.cards
+ const { card, list, board, project } = await sails.helpers.cards
.getProjectPath(inputs.cardId)
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
@@ -66,9 +66,12 @@ module.exports = {
}
cardMembership = await sails.helpers.cardMemberships.deleteOne.with({
+ project,
board,
+ list,
card,
record: cardMembership,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/cards/create.js b/server/api/controllers/cards/create.js
index b847c3e0..33bc6b2d 100755
--- a/server/api/controllers/cards/create.js
+++ b/server/api/controllers/cards/create.js
@@ -78,7 +78,7 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { board, list } = await sails.helpers.lists
+ const { list, board, project } = await sails.helpers.lists
.getProjectPath(inputs.listId)
.intercept('pathNotFound', () => Errors.LIST_NOT_FOUND);
@@ -99,6 +99,7 @@ module.exports = {
const card = await sails.helpers.cards.createOne
.with({
+ project,
board,
values: {
...values,
diff --git a/server/api/controllers/cards/delete.js b/server/api/controllers/cards/delete.js
index dad82de1..12bb9a5b 100755
--- a/server/api/controllers/cards/delete.js
+++ b/server/api/controllers/cards/delete.js
@@ -28,12 +28,15 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- let { card } = await sails.helpers.cards
+ const path = await sails.helpers.cards
.getProjectPath(inputs.id)
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
+ let { card } = path;
+ const { list, board, project } = path;
+
const boardMembership = await BoardMembership.findOne({
- boardId: card.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -46,8 +49,11 @@ module.exports = {
}
card = await sails.helpers.cards.deleteOne.with({
+ project,
+ board,
+ list,
record: card,
- user: currentUser,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/cards/duplicate.js b/server/api/controllers/cards/duplicate.js
index 918a8ec1..25cfaad5 100755
--- a/server/api/controllers/cards/duplicate.js
+++ b/server/api/controllers/cards/duplicate.js
@@ -35,12 +35,12 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { card, list, board } = await sails.helpers.cards
+ const { card, list, board, project } = await sails.helpers.cards
.getProjectPath(inputs.id)
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
const boardMembership = await BoardMembership.findOne({
- boardId: card.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -60,6 +60,7 @@ module.exports = {
cardLabels,
tasks,
} = await sails.helpers.cards.duplicateOne.with({
+ project,
board,
list,
record: card,
diff --git a/server/api/controllers/cards/update.js b/server/api/controllers/cards/update.js
index 8ee37523..d3deaf48 100755
--- a/server/api/controllers/cards/update.js
+++ b/server/api/controllers/cards/update.js
@@ -118,7 +118,7 @@ module.exports = {
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
let { card } = path;
- const { list, board } = path;
+ const { list, board, project } = path;
let boardMembership = await BoardMembership.findOne({
boardId: board.id,
@@ -133,9 +133,11 @@ module.exports = {
throw Errors.NOT_ENOUGH_RIGHTS;
}
+ let nextProject;
let nextBoard;
+
if (!_.isUndefined(inputs.boardId)) {
- ({ board: nextBoard } = await sails.helpers.boards
+ ({ board: nextBoard, project: nextProject } = await sails.helpers.boards
.getProjectPath(inputs.boardId)
.intercept('pathNotFound', () => Errors.BOARD_NOT_FOUND));
@@ -177,15 +179,17 @@ module.exports = {
card = await sails.helpers.cards.updateOne
.with({
+ project,
board,
list,
record: card,
values: {
...values,
+ project: nextProject,
board: nextBoard,
list: nextList,
},
- user: currentUser,
+ actorUser: currentUser,
request: this.req,
})
.intercept('positionMustBeInValues', () => Errors.POSITION_MUST_BE_PRESENT)
diff --git a/server/api/controllers/comment-actions/create.js b/server/api/controllers/comment-actions/create.js
index 7712a3a5..41cc694d 100755
--- a/server/api/controllers/comment-actions/create.js
+++ b/server/api/controllers/comment-actions/create.js
@@ -32,7 +32,7 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { board, card } = await sails.helpers.cards
+ const { card, list, board, project } = await sails.helpers.cards
.getProjectPath(inputs.cardId)
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
@@ -55,7 +55,9 @@ module.exports = {
};
const action = await sails.helpers.actions.createOne.with({
+ project,
board,
+ list,
values: {
...values,
card,
diff --git a/server/api/controllers/comment-actions/delete.js b/server/api/controllers/comment-actions/delete.js
index 97c98790..25082358 100755
--- a/server/api/controllers/comment-actions/delete.js
+++ b/server/api/controllers/comment-actions/delete.js
@@ -36,7 +36,7 @@ module.exports = {
.intercept('pathNotFound', () => Errors.COMMENT_ACTION_NOT_FOUND);
let { action } = path;
- const { board, project, card } = path;
+ const { card, list, board, project } = path;
const isProjectManager = await sails.helpers.users.isProjectManager(currentUser.id, project.id);
@@ -60,9 +60,12 @@ module.exports = {
}
action = await sails.helpers.actions.deleteOne.with({
+ project,
board,
+ list,
card,
record: action,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/comment-actions/update.js b/server/api/controllers/comment-actions/update.js
index a385ae8c..aa62fd5c 100755
--- a/server/api/controllers/comment-actions/update.js
+++ b/server/api/controllers/comment-actions/update.js
@@ -40,7 +40,7 @@ module.exports = {
.intercept('pathNotFound', () => Errors.COMMENT_ACTION_NOT_FOUND);
let { action } = path;
- const { board, project, card } = path;
+ const { card, list, board, project } = path;
const isProjectManager = await sails.helpers.users.isProjectManager(currentUser.id, project.id);
@@ -69,9 +69,12 @@ module.exports = {
action = await sails.helpers.actions.updateOne.with({
values,
- card,
+ project,
board,
+ list,
+ card,
record: action,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/labels/create.js b/server/api/controllers/labels/create.js
index d3b8743c..a1e84991 100755
--- a/server/api/controllers/labels/create.js
+++ b/server/api/controllers/labels/create.js
@@ -42,7 +42,7 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { board } = await sails.helpers.boards
+ const { board, project } = await sails.helpers.boards
.getProjectPath(inputs.boardId)
.intercept('pathNotFound', () => Errors.BOARD_NOT_FOUND);
@@ -62,10 +62,12 @@ module.exports = {
const values = _.pick(inputs, ['position', 'name', 'color']);
const label = await sails.helpers.labels.createOne.with({
+ project,
values: {
...values,
board,
},
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/labels/delete.js b/server/api/controllers/labels/delete.js
index e2f0a098..f14bf451 100755
--- a/server/api/controllers/labels/delete.js
+++ b/server/api/controllers/labels/delete.js
@@ -28,12 +28,15 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- let { label } = await sails.helpers.labels
+ const path = await sails.helpers.labels
.getProjectPath(inputs.id)
.intercept('pathNotFound', () => Errors.LABEL_NOT_FOUND);
+ let { label } = path;
+ const { board, project } = path;
+
const boardMembership = await BoardMembership.findOne({
- boardId: label.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -46,7 +49,10 @@ module.exports = {
}
label = await sails.helpers.labels.deleteOne.with({
+ project,
+ board,
record: label,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/labels/update.js b/server/api/controllers/labels/update.js
index e289bdf9..7e76b74b 100755
--- a/server/api/controllers/labels/update.js
+++ b/server/api/controllers/labels/update.js
@@ -40,12 +40,15 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- let { label } = await sails.helpers.labels
+ const path = await sails.helpers.labels
.getProjectPath(inputs.id)
.intercept('pathNotFound', () => Errors.LABEL_NOT_FOUND);
+ let { label } = path;
+ const { board, project } = path;
+
const boardMembership = await BoardMembership.findOne({
- boardId: label.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -61,7 +64,10 @@ module.exports = {
label = await sails.helpers.labels.updateOne.with({
values,
+ project,
+ board,
record: label,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/lists/create.js b/server/api/controllers/lists/create.js
index 9383f5be..869c00bb 100755
--- a/server/api/controllers/lists/create.js
+++ b/server/api/controllers/lists/create.js
@@ -36,7 +36,7 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { board } = await sails.helpers.boards
+ const { board, project } = await sails.helpers.boards
.getProjectPath(inputs.boardId)
.intercept('pathNotFound', () => Errors.BOARD_NOT_FOUND);
@@ -56,10 +56,12 @@ module.exports = {
const values = _.pick(inputs, ['position', 'name']);
const list = await sails.helpers.lists.createOne.with({
+ project,
values: {
...values,
board,
},
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/lists/delete.js b/server/api/controllers/lists/delete.js
index 982b0f73..2368161f 100755
--- a/server/api/controllers/lists/delete.js
+++ b/server/api/controllers/lists/delete.js
@@ -28,13 +28,15 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- // eslint-disable-next-line prefer-const
- let { list, board } = await sails.helpers.lists
+ const path = await sails.helpers.lists
.getProjectPath(inputs.id)
.intercept('pathNotFound', () => Errors.LIST_NOT_FOUND);
+ let { list } = path;
+ const { board, project } = path;
+
const boardMembership = await BoardMembership.findOne({
- boardId: list.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -47,8 +49,10 @@ module.exports = {
}
list = await sails.helpers.lists.deleteOne.with({
- record: list,
+ project,
board,
+ record: list,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/lists/sort.js b/server/api/controllers/lists/sort.js
index ec5863f6..0451ca69 100644
--- a/server/api/controllers/lists/sort.js
+++ b/server/api/controllers/lists/sort.js
@@ -32,12 +32,12 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { list } = await sails.helpers.lists
+ const { list, board, project } = await sails.helpers.lists
.getProjectPath(inputs.id)
.intercept('pathNotFound', () => Errors.LIST_NOT_FOUND);
const boardMembership = await BoardMembership.findOne({
- boardId: list.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -50,8 +50,11 @@ module.exports = {
}
const cards = await sails.helpers.lists.sortOne.with({
+ project,
+ board,
record: list,
type: inputs.type,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/lists/update.js b/server/api/controllers/lists/update.js
index 15f5f209..e1988b93 100755
--- a/server/api/controllers/lists/update.js
+++ b/server/api/controllers/lists/update.js
@@ -35,13 +35,15 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- // eslint-disable-next-line prefer-const
- let { list, board } = await sails.helpers.lists
+ const path = await sails.helpers.lists
.getProjectPath(inputs.id)
.intercept('pathNotFound', () => Errors.LIST_NOT_FOUND);
+ let { list } = path;
+ const { board, project } = path;
+
const boardMembership = await BoardMembership.findOne({
- boardId: list.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -57,8 +59,10 @@ module.exports = {
list = await sails.helpers.lists.updateOne.with({
values,
+ project,
board,
record: list,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/notifications/update.js b/server/api/controllers/notifications/update.js
index f8a97a35..09d5b4c2 100755
--- a/server/api/controllers/notifications/update.js
+++ b/server/api/controllers/notifications/update.js
@@ -18,7 +18,7 @@ module.exports = {
const notifications = await sails.helpers.notifications.updateMany.with({
values,
recordsOrIds: inputs.ids.split(','),
- user: currentUser,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/project-managers/create.js b/server/api/controllers/project-managers/create.js
index a5751fdb..e3796958 100755
--- a/server/api/controllers/project-managers/create.js
+++ b/server/api/controllers/project-managers/create.js
@@ -63,6 +63,7 @@ module.exports = {
project,
user,
},
+ actorUser: currentUser,
request: this.req,
})
.intercept('userAlreadyProjectManager', () => Errors.USER_ALREADY_PROJECT_MANAGER);
diff --git a/server/api/controllers/project-managers/delete.js b/server/api/controllers/project-managers/delete.js
index 5bd3f9af..46946e61 100755
--- a/server/api/controllers/project-managers/delete.js
+++ b/server/api/controllers/project-managers/delete.js
@@ -40,6 +40,7 @@ module.exports = {
// TODO: check if the last one
projectManager = await sails.helpers.projectManagers.deleteOne.with({
record: projectManager,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/projects/create.js b/server/api/controllers/projects/create.js
index 1ce57ae8..54bd7f00 100755
--- a/server/api/controllers/projects/create.js
+++ b/server/api/controllers/projects/create.js
@@ -1,3 +1,9 @@
+const Errors = {
+ NOT_ENOUGH_RIGHTS: {
+ notEnoughRights: 'Not enough rights',
+ },
+};
+
module.exports = {
inputs: {
name: {
@@ -6,14 +12,24 @@ module.exports = {
},
},
+ exits: {
+ notEnoughRights: {
+ responseType: 'forbidden',
+ },
+ },
+
async fn(inputs) {
const { currentUser } = this.req;
+ if (!currentUser.isAdmin && !sails.config.custom.allowAllToCreateProjects) {
+ throw Errors.NOT_ENOUGH_RIGHTS;
+ }
+
const values = _.pick(inputs, ['name']);
const { project, projectManager } = await sails.helpers.projects.createOne.with({
values,
- user: currentUser,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/projects/delete.js b/server/api/controllers/projects/delete.js
index dedb9070..90ae180d 100755
--- a/server/api/controllers/projects/delete.js
+++ b/server/api/controllers/projects/delete.js
@@ -36,6 +36,7 @@ module.exports = {
project = await sails.helpers.projects.deleteOne.with({
record: project,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/projects/update-background-image.js b/server/api/controllers/projects/update-background-image.js
index 85825e08..2045ee1e 100755
--- a/server/api/controllers/projects/update-background-image.js
+++ b/server/api/controllers/projects/update-background-image.js
@@ -90,6 +90,7 @@ module.exports = {
values: {
backgroundImage: fileData,
},
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/projects/update.js b/server/api/controllers/projects/update.js
index 6d6e16e9..230be644 100755
--- a/server/api/controllers/projects/update.js
+++ b/server/api/controllers/projects/update.js
@@ -81,6 +81,7 @@ module.exports = {
project = await sails.helpers.projects.updateOne.with({
values,
record: project,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/show-config.js b/server/api/controllers/show-config.js
index 5349149a..1a8207ec 100644
--- a/server/api/controllers/show-config.js
+++ b/server/api/controllers/show-config.js
@@ -4,11 +4,16 @@ module.exports = {
if (sails.hooks.oidc.isActive()) {
const oidcClient = sails.hooks.oidc.getClient();
+ const authorizationUrlParams = {
+ scope: sails.config.custom.oidcScopes,
+ };
+
+ if (!sails.config.custom.oidcUseDefaultResponseMode) {
+ authorizationUrlParams.response_mode = sails.config.custom.oidcResponseMode;
+ }
+
oidc = {
- authorizationUrl: oidcClient.authorizationUrl({
- scope: sails.config.custom.oidcScopes,
- response_mode: 'fragment',
- }),
+ authorizationUrl: oidcClient.authorizationUrl(authorizationUrlParams),
endSessionUrl: oidcClient.issuer.end_session_endpoint ? oidcClient.endSessionUrl({}) : null,
isEnforced: sails.config.custom.oidcEnforced,
};
@@ -17,6 +22,7 @@ module.exports = {
return {
item: {
oidc,
+ allowAllToCreateProjects: sails.config.custom.allowAllToCreateProjects,
},
};
},
diff --git a/server/api/controllers/tasks/create.js b/server/api/controllers/tasks/create.js
index ff4b0523..126e39a6 100755
--- a/server/api/controllers/tasks/create.js
+++ b/server/api/controllers/tasks/create.js
@@ -39,12 +39,12 @@ module.exports = {
async fn(inputs) {
const { currentUser } = this.req;
- const { card, board } = await sails.helpers.cards
+ const { card, list, board, project } = await sails.helpers.cards
.getProjectPath(inputs.cardId)
.intercept('pathNotFound', () => Errors.CARD_NOT_FOUND);
const boardMembership = await BoardMembership.findOne({
- boardId: card.boardId,
+ boardId: board.id,
userId: currentUser.id,
});
@@ -59,11 +59,14 @@ module.exports = {
const values = _.pick(inputs, ['position', 'name', 'isCompleted']);
const task = await sails.helpers.tasks.createOne.with({
+ project,
+ board,
+ list,
values: {
...values,
card,
},
- board,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/tasks/delete.js b/server/api/controllers/tasks/delete.js
index c4ba0ed3..a83cc9dc 100755
--- a/server/api/controllers/tasks/delete.js
+++ b/server/api/controllers/tasks/delete.js
@@ -33,7 +33,7 @@ module.exports = {
.intercept('pathNotFound', () => Errors.TASK_NOT_FOUND);
let { task } = path;
- const { board } = path;
+ const { card, list, board, project } = path;
const boardMembership = await BoardMembership.findOne({
boardId: board.id,
@@ -49,8 +49,12 @@ module.exports = {
}
task = await sails.helpers.tasks.deleteOne.with({
+ project,
board,
+ list,
+ card,
record: task,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/tasks/update.js b/server/api/controllers/tasks/update.js
index 9e08f76f..ff43fcb8 100755
--- a/server/api/controllers/tasks/update.js
+++ b/server/api/controllers/tasks/update.js
@@ -43,7 +43,7 @@ module.exports = {
.intercept('pathNotFound', () => Errors.TASK_NOT_FOUND);
let { task } = path;
- const { board } = path;
+ const { card, list, board, project } = path;
const boardMembership = await BoardMembership.findOne({
boardId: board.id,
@@ -62,8 +62,12 @@ module.exports = {
task = await sails.helpers.tasks.updateOne.with({
values,
+ project,
board,
+ list,
+ card,
record: task,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/users/create.js b/server/api/controllers/users/create.js
index 7d40c975..dc76b31f 100755
--- a/server/api/controllers/users/create.js
+++ b/server/api/controllers/users/create.js
@@ -50,7 +50,7 @@ module.exports = {
},
language: {
type: 'string',
- isNotEmptyString: true,
+ isIn: User.LANGUAGES,
allowNull: true,
},
subscribeToOwnCards: {
@@ -71,6 +71,8 @@ module.exports = {
},
async fn(inputs) {
+ const { currentUser } = this.req;
+
if (sails.config.custom.oidcEnforced) {
throw Errors.NOT_ENOUGH_RIGHTS;
}
@@ -89,6 +91,7 @@ module.exports = {
const user = await sails.helpers.users.createOne
.with({
values,
+ actorUser: currentUser,
request: this.req,
})
.intercept('emailAlreadyInUse', () => Errors.EMAIL_ALREADY_IN_USE)
diff --git a/server/api/controllers/users/delete.js b/server/api/controllers/users/delete.js
index 56a42f8b..b1afab29 100755
--- a/server/api/controllers/users/delete.js
+++ b/server/api/controllers/users/delete.js
@@ -26,6 +26,8 @@ module.exports = {
},
async fn(inputs) {
+ const { currentUser } = this.req;
+
let user = await sails.helpers.users.getOne(inputs.id);
if (!user) {
@@ -38,6 +40,7 @@ module.exports = {
user = await sails.helpers.users.deleteOne.with({
record: user,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/users/update-avatar.js b/server/api/controllers/users/update-avatar.js
index 37b01f11..fc628564 100755
--- a/server/api/controllers/users/update-avatar.js
+++ b/server/api/controllers/users/update-avatar.js
@@ -91,7 +91,7 @@ module.exports = {
values: {
avatar: fileData,
},
- user: currentUser,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/users/update-email.js b/server/api/controllers/users/update-email.js
index f067e004..17575577 100644
--- a/server/api/controllers/users/update-email.js
+++ b/server/api/controllers/users/update-email.js
@@ -82,7 +82,7 @@ module.exports = {
.with({
values,
record: user,
- user: currentUser,
+ actorUser: currentUser,
request: this.req,
})
.intercept('emailAlreadyInUse', () => Errors.EMAIL_ALREADY_IN_USE);
diff --git a/server/api/controllers/users/update-password.js b/server/api/controllers/users/update-password.js
index 107c013e..01466811 100644
--- a/server/api/controllers/users/update-password.js
+++ b/server/api/controllers/users/update-password.js
@@ -80,7 +80,7 @@ module.exports = {
user = await sails.helpers.users.updateOne.with({
values,
record: user,
- user: currentUser,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/controllers/users/update-username.js b/server/api/controllers/users/update-username.js
index b55529b4..a59c587d 100644
--- a/server/api/controllers/users/update-username.js
+++ b/server/api/controllers/users/update-username.js
@@ -83,7 +83,7 @@ module.exports = {
.with({
values,
record: user,
- user: currentUser,
+ actorUser: currentUser,
request: this.req,
})
.intercept('usernameAlreadyInUse', () => Errors.USERNAME_ALREADY_IN_USE);
diff --git a/server/api/controllers/users/update.js b/server/api/controllers/users/update.js
index 161ae78c..a46a2f7f 100755
--- a/server/api/controllers/users/update.js
+++ b/server/api/controllers/users/update.js
@@ -36,7 +36,7 @@ module.exports = {
},
language: {
type: 'string',
- isNotEmptyString: true,
+ isIn: User.LANGUAGES,
allowNull: true,
},
subscribeToOwnCards: {
@@ -95,7 +95,7 @@ module.exports = {
user = await sails.helpers.users.updateOne.with({
values,
record: user,
- user: currentUser,
+ actorUser: currentUser,
request: this.req,
});
diff --git a/server/api/helpers/actions/create-one.js b/server/api/helpers/actions/create-one.js
index e0310c82..fb0d1856 100644
--- a/server/api/helpers/actions/create-one.js
+++ b/server/api/helpers/actions/create-one.js
@@ -14,21 +14,21 @@ const valuesValidator = (value) => {
return true;
};
-const buildAndSendSlackMessage = async (user, card, action) => {
+const buildAndSendSlackMessage = async (card, action, actorUser) => {
const cardLink = `<${sails.config.custom.baseUrl}/cards/${card.id}|${card.name}>`;
let markdown;
switch (action.type) {
case Action.Types.CREATE_CARD:
- markdown = `${cardLink} was created by ${user.name} in *${action.data.list.name}*`;
+ markdown = `${cardLink} was created by ${actorUser.name} in *${action.data.list.name}*`;
break;
case Action.Types.MOVE_CARD:
- markdown = `${cardLink} was moved by ${user.name} to *${action.data.toList.name}*`;
+ markdown = `${cardLink} was moved by ${actorUser.name} to *${action.data.toList.name}*`;
break;
case Action.Types.COMMENT_CARD:
- markdown = `*${user.name}* commented on ${cardLink}:\n>${action.data.text}`;
+ markdown = `*${actorUser.name}* commented on ${cardLink}:\n>${action.data.text}`;
break;
default:
@@ -45,10 +45,18 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -72,6 +80,24 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'actionCreate',
+ data: {
+ item: action,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [values.card],
+ },
+ },
+ user: values.user,
+ });
+
+ if (sails.config.custom.slackBotToken) {
+ buildAndSendSlackMessage(values.card, action, values.user);
+ }
+
const subscriptionUserIds = await sails.helpers.cards.getSubscriptionUserIds(
action.cardId,
action.userId,
@@ -84,26 +110,15 @@ module.exports = {
userId,
action,
},
- user: values.user,
+ project: inputs.project,
board: inputs.board,
+ list: inputs.list,
card: values.card,
+ actorUser: values.user,
}),
),
);
- if (sails.config.custom.slackBotToken) {
- buildAndSendSlackMessage(values.user, values.card, action);
- }
-
- await sails.helpers.utils.sendWebhook.with({
- event: 'ACTION_CREATE',
- data: action,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card: values.card,
- board: inputs.board,
- });
-
return action;
},
};
diff --git a/server/api/helpers/actions/delete-one.js b/server/api/helpers/actions/delete-one.js
index ba862f85..3ccaff19 100644
--- a/server/api/helpers/actions/delete-one.js
+++ b/server/api/helpers/actions/delete-one.js
@@ -4,11 +4,23 @@ module.exports = {
type: 'ref',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ board: {
+ type: 'ref',
+ required: true,
+ },
+ list: {
+ type: 'ref',
+ required: true,
+ },
card: {
type: 'ref',
required: true,
},
- board: {
+ actorUser: {
type: 'ref',
required: true,
},
@@ -30,13 +42,18 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'ACTION_DELETE',
- data: action,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card: inputs.card,
- board: inputs.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'actionDelete',
+ data: {
+ item: action,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [inputs.card],
+ },
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/actions/update-one.js b/server/api/helpers/actions/update-one.js
index cdca79c0..7835fa74 100644
--- a/server/api/helpers/actions/update-one.js
+++ b/server/api/helpers/actions/update-one.js
@@ -8,7 +8,7 @@ module.exports = {
type: 'json',
required: true,
},
- card: {
+ project: {
type: 'ref',
required: true,
},
@@ -16,6 +16,18 @@ module.exports = {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
+ card: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -36,13 +48,18 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'ACTION_UPDATE',
- data: action,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card: inputs.card,
- board: inputs.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'actionUpdate',
+ data: {
+ item: action,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [inputs.card],
+ },
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/attachments/create-one.js b/server/api/helpers/attachments/create-one.js
index 0a5923b3..8db35ab6 100644
--- a/server/api/helpers/attachments/create-one.js
+++ b/server/api/helpers/attachments/create-one.js
@@ -21,10 +21,18 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
requestId: {
type: 'string',
isNotEmptyString: true,
@@ -35,7 +43,7 @@ module.exports = {
},
async fn(inputs) {
- const { values, board } = inputs;
+ const { values } = inputs;
const attachment = await Attachment.create({
...values,
@@ -53,26 +61,33 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'attachmentCreate',
+ data: {
+ item: attachment,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [values.card],
+ },
+ },
+ user: values.creatorUser,
+ });
+
if (!values.card.coverAttachmentId && attachment.image) {
await sails.helpers.cards.updateOne.with({
record: values.card,
values: {
coverAttachmentId: attachment.id,
},
- board,
- request: inputs.request,
+ project: inputs.project,
+ board: inputs.board,
+ list: inputs.list,
+ actorUser: values.creatorUser,
});
}
- await sails.helpers.utils.sendWebhook.with({
- event: 'ATTACHMENT_CREATE',
- data: attachment,
- projectId: board.projectId,
- user: inputs.request.currentUser,
- card: values.card,
- board,
- });
-
return attachment;
},
};
diff --git a/server/api/helpers/attachments/delete-one.js b/server/api/helpers/attachments/delete-one.js
index 469e1461..9d08cb4f 100644
--- a/server/api/helpers/attachments/delete-one.js
+++ b/server/api/helpers/attachments/delete-one.js
@@ -7,14 +7,26 @@ module.exports = {
type: 'ref',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
card: {
type: 'ref',
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -27,6 +39,10 @@ module.exports = {
values: {
coverAttachmentId: null,
},
+ project: inputs.project,
+ board: inputs.board,
+ list: inputs.list,
+ actorUser: inputs.actorUser,
request: inputs.request,
});
}
@@ -49,13 +65,18 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'ATTACHMENT_DELETE',
- data: attachment,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card: inputs.card,
- board: inputs.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'attachmentDelete',
+ data: {
+ item: attachment,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [inputs.card],
+ },
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/attachments/update-one.js b/server/api/helpers/attachments/update-one.js
index 9de735e1..49660206 100644
--- a/server/api/helpers/attachments/update-one.js
+++ b/server/api/helpers/attachments/update-one.js
@@ -8,10 +8,26 @@ module.exports = {
type: 'json',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
+ card: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -32,12 +48,18 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'ATTACHMENT_UPDATE',
- data: attachment,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- board: inputs.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'attachmentUpdate',
+ data: {
+ item: attachment,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [inputs.card],
+ },
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/board-memberships/create-one.js b/server/api/helpers/board-memberships/create-one.js
index 5adf9eb2..f6088474 100644
--- a/server/api/helpers/board-memberships/create-one.js
+++ b/server/api/helpers/board-memberships/create-one.js
@@ -21,6 +21,14 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -67,6 +75,19 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'boardMembershipCreate',
+ data: {
+ item: boardMembership,
+ included: {
+ users: [values.user],
+ projects: [inputs.project],
+ boards: [values.board],
+ },
+ },
+ user: inputs.actorUser,
+ });
+
return boardMembership;
},
};
diff --git a/server/api/helpers/board-memberships/delete-one.js b/server/api/helpers/board-memberships/delete-one.js
index 236734ab..e51daf4d 100644
--- a/server/api/helpers/board-memberships/delete-one.js
+++ b/server/api/helpers/board-memberships/delete-one.js
@@ -10,6 +10,14 @@ module.exports = {
type: 'ref',
required: true,
},
+ board: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -73,6 +81,18 @@ module.exports = {
);
});
}
+
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'boardMembershipDelete',
+ data: {
+ item: boardMembership,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ },
+ },
+ user: inputs.actorUser,
+ });
}
return boardMembership;
diff --git a/server/api/helpers/board-memberships/update-one.js b/server/api/helpers/board-memberships/update-one.js
index cb43adc8..63948907 100644
--- a/server/api/helpers/board-memberships/update-one.js
+++ b/server/api/helpers/board-memberships/update-one.js
@@ -8,6 +8,18 @@ module.exports = {
type: 'json',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ board: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -40,6 +52,18 @@ module.exports = {
},
inputs.request,
);
+
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'boardMembershipUpdate',
+ data: {
+ item: boardMembership,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ },
+ },
+ user: inputs.actorUser,
+ });
}
return boardMembership;
diff --git a/server/api/helpers/boards/create-one.js b/server/api/helpers/boards/create-one.js
index 98618722..368dda92 100644
--- a/server/api/helpers/boards/create-one.js
+++ b/server/api/helpers/boards/create-one.js
@@ -37,7 +37,7 @@ module.exports = {
type: 'json',
custom: importValidator,
},
- user: {
+ actorUser: {
type: 'ref',
required: true,
},
@@ -80,6 +80,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
});
@@ -90,12 +92,12 @@ module.exports = {
}).fetch();
if (inputs.import && inputs.import.type === Board.ImportTypes.TRELLO) {
- await sails.helpers.boards.importFromTrello(inputs.user, board, inputs.import.board);
+ await sails.helpers.boards.importFromTrello(board, inputs.import.board, inputs.actorUser);
}
const boardMembership = await BoardMembership.create({
boardId: board.id,
- userId: inputs.user.id,
+ userId: inputs.actorUser.id,
role: BoardMembership.Roles.EDITOR,
}).fetch();
@@ -111,12 +113,15 @@ module.exports = {
);
});
- await sails.helpers.utils.sendWebhook.with({
- event: 'BOARD_CREATE',
- data: board,
- projectId: board.projectId,
- user: inputs.request.currentUser,
- board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'boardCreate',
+ data: {
+ item: board,
+ included: {
+ projects: [values.project],
+ },
+ },
+ user: inputs.actorUser,
});
return {
diff --git a/server/api/helpers/boards/delete-one.js b/server/api/helpers/boards/delete-one.js
index ddc51d7e..8633cd55 100644
--- a/server/api/helpers/boards/delete-one.js
+++ b/server/api/helpers/boards/delete-one.js
@@ -4,6 +4,14 @@ module.exports = {
type: 'ref',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -33,15 +41,18 @@ module.exports = {
inputs.request,
);
});
- }
- await sails.helpers.utils.sendWebhook.with({
- event: 'BOARD_DELETE',
- data: board,
- projectId: board.projectId,
- user: inputs.request.currentUser,
- board,
- });
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'boardDelete',
+ data: {
+ item: board,
+ included: {
+ projects: [inputs.project],
+ },
+ },
+ user: inputs.actorUser,
+ });
+ }
return board;
},
diff --git a/server/api/helpers/boards/import-from-trello.js b/server/api/helpers/boards/import-from-trello.js
index 2ab6e0af..a7b54238 100644
--- a/server/api/helpers/boards/import-from-trello.js
+++ b/server/api/helpers/boards/import-from-trello.js
@@ -2,10 +2,6 @@ const POSITION_GAP = 65535; // TODO: move to config
module.exports = {
inputs: {
- user: {
- type: 'ref',
- required: true,
- },
board: {
type: 'ref',
required: true,
@@ -14,6 +10,10 @@ module.exports = {
type: 'json',
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
},
async fn(inputs) {
@@ -87,7 +87,7 @@ module.exports = {
trelloComments.map(async (trelloComment) => {
return Action.create({
cardId: plankaCard.id,
- userId: inputs.user.id,
+ userId: inputs.actorUser.id,
type: 'commentCard',
data: {
text:
@@ -105,7 +105,7 @@ module.exports = {
const plankaCard = await Card.create({
boardId: inputs.board.id,
listId: plankaList.id,
- creatorUserId: inputs.user.id,
+ creatorUserId: inputs.actorUser.id,
position: trelloCard.pos,
name: trelloCard.name,
description: trelloCard.desc || null,
diff --git a/server/api/helpers/boards/update-one.js b/server/api/helpers/boards/update-one.js
index 82fdcce0..e20324dd 100644
--- a/server/api/helpers/boards/update-one.js
+++ b/server/api/helpers/boards/update-one.js
@@ -21,6 +21,14 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -64,6 +72,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
});
}
@@ -81,15 +91,18 @@ module.exports = {
inputs.request,
);
});
- }
- await sails.helpers.utils.sendWebhook.with({
- event: 'BOARD_UPDATE',
- data: board,
- projectId: board.projectId,
- user: inputs.request.currentUser,
- board,
- });
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'boardUpdate',
+ data: {
+ item: board,
+ included: {
+ projects: [inputs.project],
+ },
+ },
+ user: inputs.actorUser,
+ });
+ }
return board;
},
diff --git a/server/api/helpers/card-labels/create-one.js b/server/api/helpers/card-labels/create-one.js
index f0cde82c..7e168ca9 100644
--- a/server/api/helpers/card-labels/create-one.js
+++ b/server/api/helpers/card-labels/create-one.js
@@ -21,6 +21,22 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ board: {
+ type: 'ref',
+ required: true,
+ },
+ list: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -50,6 +66,21 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'cardLabelCreate',
+ data: {
+ item: cardLabel,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ labels: [values.label],
+ lists: [inputs.list],
+ cards: [values.card],
+ },
+ },
+ user: inputs.actorUser,
+ });
+
return cardLabel;
},
};
diff --git a/server/api/helpers/card-labels/delete-one.js b/server/api/helpers/card-labels/delete-one.js
index 3dc30ddc..e557d383 100644
--- a/server/api/helpers/card-labels/delete-one.js
+++ b/server/api/helpers/card-labels/delete-one.js
@@ -4,10 +4,26 @@ module.exports = {
type: 'ref',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
+ card: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -25,6 +41,20 @@ module.exports = {
},
inputs.request,
);
+
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'cardLabelDelete',
+ data: {
+ item: cardLabel,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [inputs.card],
+ },
+ },
+ user: inputs.actorUser,
+ });
}
return cardLabel;
diff --git a/server/api/helpers/card-memberships/create-one.js b/server/api/helpers/card-memberships/create-one.js
index 52f17882..c32ff428 100644
--- a/server/api/helpers/card-memberships/create-one.js
+++ b/server/api/helpers/card-memberships/create-one.js
@@ -21,10 +21,22 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -57,6 +69,20 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'cardMembershipCreate',
+ data: {
+ item: cardMembership,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [values.card],
+ },
+ },
+ user: inputs.actorUser,
+ });
+
const cardSubscription = await CardSubscription.create({
cardId: cardMembership.cardId,
userId: cardMembership.userId,
@@ -77,16 +103,9 @@ module.exports = {
},
inputs.request,
);
- }
- await sails.helpers.utils.sendWebhook.with({
- event: 'CARD_MEMBERSHIP_CREATE',
- data: cardMembership,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card: values.card,
- board: inputs.board,
- });
+ // TODO: send webhooks
+ }
return cardMembership;
},
diff --git a/server/api/helpers/card-memberships/delete-one.js b/server/api/helpers/card-memberships/delete-one.js
index a4ed107f..cfa2fc7e 100644
--- a/server/api/helpers/card-memberships/delete-one.js
+++ b/server/api/helpers/card-memberships/delete-one.js
@@ -4,11 +4,23 @@ module.exports = {
type: 'ref',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ board: {
+ type: 'ref',
+ required: true,
+ },
+ list: {
+ type: 'ref',
+ required: true,
+ },
card: {
type: 'ref',
required: true,
},
- board: {
+ actorUser: {
type: 'ref',
required: true,
},
@@ -30,6 +42,20 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'cardMembershipDelete',
+ data: {
+ item: cardMembership,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [inputs.card],
+ },
+ },
+ user: inputs.actorUser,
+ });
+
const cardSubscription = await CardSubscription.destroyOne({
cardId: cardMembership.cardId,
userId: cardMembership.userId,
@@ -43,16 +69,9 @@ module.exports = {
isSubscribed: false,
},
});
- }
- await sails.helpers.utils.sendWebhook.with({
- event: 'CARD_MEMBERSHIP_DELETE',
- data: cardMembership,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card: inputs.card,
- board: inputs.board,
- });
+ // TODO: send webhook
+ }
}
return cardMembership;
diff --git a/server/api/helpers/cards/create-one.js b/server/api/helpers/cards/create-one.js
index 0514bf5f..36cdb81a 100644
--- a/server/api/helpers/cards/create-one.js
+++ b/server/api/helpers/cards/create-one.js
@@ -25,6 +25,10 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
@@ -66,6 +70,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
const card = await Card.create({
@@ -85,6 +91,19 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'cardCreate',
+ data: {
+ item: card,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [values.list],
+ },
+ },
+ user: values.creatorUser,
+ });
+
if (values.creatorUser.subscribeToOwnCards) {
await CardSubscription.create({
cardId: card.id,
@@ -97,6 +116,8 @@ module.exports = {
isSubscribed: true,
},
});
+
+ // TODO: send webhooks
}
await sails.helpers.actions.createOne.with({
@@ -108,18 +129,10 @@ module.exports = {
},
user: values.creatorUser,
},
- board: inputs.board,
- request: inputs.request,
- });
-
- await sails.helpers.utils.sendWebhook.with({
- event: 'CARD_CREATE',
- data: card,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card,
+ project: inputs.project,
board: inputs.board,
list: values.list,
+ request: inputs.request,
});
return card;
diff --git a/server/api/helpers/cards/delete-one.js b/server/api/helpers/cards/delete-one.js
index e95596e8..1400bfcb 100644
--- a/server/api/helpers/cards/delete-one.js
+++ b/server/api/helpers/cards/delete-one.js
@@ -1,5 +1,5 @@
-const buildAndSendSlackMessage = async (user, card) => {
- await sails.helpers.utils.sendSlackMessage(`*${card.name}* was deleted by ${user.name}`);
+const buildAndSendSlackMessage = async (card, actorUser) => {
+ await sails.helpers.utils.sendSlackMessage(`*${card.name}* was deleted by ${actorUser.name}`);
};
module.exports = {
@@ -8,7 +8,19 @@ module.exports = {
type: 'ref',
required: true,
},
- user: {
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ board: {
+ type: 'ref',
+ required: true,
+ },
+ list: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
type: 'ref',
required: true,
},
@@ -21,10 +33,6 @@ module.exports = {
const card = await Card.archiveOne(inputs.record.id);
if (card) {
- const { board } = await sails.helpers.lists
- .getProjectPath(card.listId)
- .intercept('pathNotFound', () => Errors.LIST_NOT_FOUND);
-
sails.sockets.broadcast(
`board:${card.boardId}`,
'cardDelete',
@@ -34,18 +42,22 @@ module.exports = {
inputs.request,
);
- if (sails.config.custom.slackBotToken) {
- buildAndSendSlackMessage(inputs.user, card);
- }
-
- await sails.helpers.utils.sendWebhook.with({
- event: 'CARD_DELETE',
- data: card,
- projectId: board.projectId,
- user: inputs.request.currentUser,
- card,
- board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'cardDelete',
+ data: {
+ item: card,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ },
+ },
+ user: inputs.actorUser,
});
+
+ if (sails.config.custom.slackBotToken) {
+ buildAndSendSlackMessage(card, inputs.actorUser);
+ }
}
return card;
diff --git a/server/api/helpers/cards/duplicate-one.js b/server/api/helpers/cards/duplicate-one.js
index 71645533..94a0d755 100644
--- a/server/api/helpers/cards/duplicate-one.js
+++ b/server/api/helpers/cards/duplicate-one.js
@@ -25,6 +25,10 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
@@ -62,6 +66,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
const card = await Card.create({
@@ -108,6 +114,19 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'cardCreate',
+ data: {
+ item: card,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ },
+ },
+ user: values.creatorUser,
+ });
+
if (values.creatorUser.subscribeToOwnCards) {
await CardSubscription.create({
cardId: card.id,
@@ -120,6 +139,8 @@ module.exports = {
isSubscribed: true,
},
});
+
+ // TODO: send webhooks
}
await sails.helpers.actions.createOne.with({
@@ -131,18 +152,10 @@ module.exports = {
},
user: values.creatorUser,
},
- board: inputs.board,
- request: inputs.request,
- });
-
- await sails.helpers.utils.sendWebhook.with({
- event: 'CARD_CREATE',
- data: card,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card,
+ project: inputs.project,
board: inputs.board,
list: inputs.list,
+ request: inputs.request,
});
return {
diff --git a/server/api/helpers/cards/update-one.js b/server/api/helpers/cards/update-one.js
index cc054039..cd978b7e 100644
--- a/server/api/helpers/cards/update-one.js
+++ b/server/api/helpers/cards/update-one.js
@@ -7,8 +7,14 @@ const valuesValidator = (value) => {
return false;
}
- if (!_.isUndefined(value.board) && !_.isPlainObject(value.board)) {
- return false;
+ if (!_.isUndefined(value.board)) {
+ if (!_.isPlainObject(value.project)) {
+ return false;
+ }
+
+ if (!_.isPlainObject(value.board)) {
+ return false;
+ }
}
if (!_.isUndefined(value.list) && !_.isPlainObject(value.list)) {
@@ -29,14 +35,21 @@ module.exports = {
custom: valuesValidator,
required: true,
},
- user: {
+ project: {
type: 'ref',
+ required: true,
},
board: {
type: 'ref',
+ required: true,
},
list: {
type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
},
request: {
type: 'ref',
@@ -45,65 +58,56 @@ module.exports = {
exits: {
positionMustBeInValues: {},
+ boardInValuesMustBelongToProject: {},
listMustBeInValues: {},
listInValuesMustBelongToBoard: {},
- userMustBePresent: {},
- boardMustBePresent: {},
- listMustBePresent: {},
},
async fn(inputs) {
const { isSubscribed, ...values } = inputs.values;
- if (values.board || values.list || !_.isUndefined(values.position)) {
- if (!inputs.board) {
- throw 'boardMustBePresent';
+ if (values.project && values.project.id === inputs.project.id) {
+ delete values.project;
+ }
+
+ const project = values.project || inputs.project;
+
+ if (values.board) {
+ if (values.board.projectId !== project.id) {
+ throw 'boardInValuesMustBelongToProject';
}
- if (values.board) {
- if (values.board.id === inputs.board.id) {
- delete values.board;
- } else {
- values.boardId = values.board.id;
- }
- }
-
- const board = values.board || inputs.board;
-
- if (values.list) {
- if (!inputs.list) {
- throw 'listMustBePresent';
- }
-
- if (values.list.boardId !== board.id) {
- throw 'listInValuesMustBelongToBoard';
- }
-
- if (values.list.id === inputs.list.id) {
- delete values.list;
- } else {
- values.listId = values.list.id;
- }
- }
-
- if (values.list) {
- if (_.isUndefined(values.position)) {
- throw 'positionMustBeInValues';
- }
- } else if (values.board) {
- throw 'listMustBeInValues';
+ if (values.board.id === inputs.board.id) {
+ delete values.board;
+ } else {
+ values.boardId = values.board.id;
}
}
- if ((!_.isUndefined(isSubscribed) || values.board || values.list) && !inputs.user) {
- throw 'userMustBePresent';
+ const board = values.board || inputs.board;
+
+ if (values.list) {
+ if (values.list.boardId !== board.id) {
+ throw 'listInValuesMustBelongToBoard';
+ }
+
+ if (values.list.id === inputs.list.id) {
+ delete values.list;
+ } else {
+ values.listId = values.list.id;
+ }
+ } else if (values.board) {
+ throw 'listMustBeInValues';
+ }
+
+ const list = values.list || inputs.list;
+
+ if (values.list && _.isUndefined(values.position)) {
+ throw 'positionMustBeInValues';
}
if (!_.isUndefined(values.position)) {
- const boardId = values.boardId || inputs.record.boardId;
- const listId = values.listId || inputs.record.listId;
-
- const cards = await sails.helpers.lists.getCards(listId, inputs.record.id);
+ const cards = await sails.helpers.lists.getCards(list.id, inputs.record.id);
const { position, repositions } = sails.helpers.utils.insertToPositionables(
values.position,
@@ -115,17 +119,19 @@ module.exports = {
repositions.forEach(async ({ id, position: nextPosition }) => {
await Card.update({
id,
- listId,
+ listId: list.id,
}).set({
position: nextPosition,
});
- sails.sockets.broadcast(`board:${boardId}`, 'cardUpdate', {
+ sails.sockets.broadcast(`board:${board.id}`, 'cardUpdate', {
item: {
id,
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
}
@@ -175,10 +181,12 @@ module.exports = {
}
const { id } = await sails.helpers.labels.createOne.with({
+ project,
values: {
..._.omit(label, ['id', 'boardId']),
board: values.board,
},
+ actorUser: inputs.actorUser,
});
return id;
@@ -196,6 +204,15 @@ module.exports = {
),
);
+ sails.sockets.broadcast(
+ `board:${inputs.record.boardId}`,
+ 'cardDelete', // TODO: introduce separate event
+ {
+ item: inputs.record,
+ },
+ inputs.request,
+ );
+
sails.sockets.broadcast(`board:${card.boardId}`, 'cardUpdate', {
item: card,
});
@@ -209,6 +226,8 @@ module.exports = {
isSubscribed: true,
},
});
+
+ // TODO: send webhooks
});
} else {
sails.sockets.broadcast(
@@ -221,18 +240,33 @@ module.exports = {
);
}
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'cardUpdate',
+ data: {
+ item: card,
+ included: {
+ projects: [project],
+ boards: [board],
+ lists: [list],
+ },
+ },
+ user: inputs.actorUser,
+ });
+
if (!values.board && values.list) {
await sails.helpers.actions.createOne.with({
+ project,
+ board,
+ list,
values: {
card,
- user: inputs.user,
+ user: inputs.actorUser,
type: Action.Types.MOVE_CARD,
data: {
fromList: _.pick(inputs.list, ['id', 'name']),
toList: _.pick(values.list, ['id', 'name']),
},
},
- board: inputs.board,
request: inputs.request,
});
}
@@ -241,23 +275,26 @@ module.exports = {
}
if (!_.isUndefined(isSubscribed)) {
- const prevIsSubscribed = await sails.helpers.users.isCardSubscriber(inputs.user.id, card.id);
+ const prevIsSubscribed = await sails.helpers.users.isCardSubscriber(
+ inputs.actorUser.id,
+ card.id,
+ );
if (isSubscribed !== prevIsSubscribed) {
if (isSubscribed) {
await CardSubscription.create({
cardId: card.id,
- userId: inputs.user.id,
+ userId: inputs.actorUser.id,
}).tolerate('E_UNIQUE');
} else {
await CardSubscription.destroyOne({
cardId: card.id,
- userId: inputs.user.id,
+ userId: inputs.actorUser.id,
});
}
sails.sockets.broadcast(
- `user:${inputs.user.id}`,
+ `user:${inputs.actorUser.id}`,
'cardUpdate',
{
item: {
@@ -267,18 +304,11 @@ module.exports = {
},
inputs.request,
);
+
+ // TODO: send webhooks
}
}
- await sails.helpers.utils.sendWebhook.with({
- event: 'CARD_UPDATE',
- data: card,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card,
- board: inputs.board,
- });
-
return card;
},
};
diff --git a/server/api/helpers/labels/create-one.js b/server/api/helpers/labels/create-one.js
index 04f58c36..f9d66d64 100644
--- a/server/api/helpers/labels/create-one.js
+++ b/server/api/helpers/labels/create-one.js
@@ -21,6 +21,14 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -50,6 +58,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
const label = await Label.create({
@@ -67,6 +77,18 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'labelCreate',
+ data: {
+ item: label,
+ included: {
+ projects: [inputs.project],
+ boards: [values.board],
+ },
+ },
+ user: inputs.actorUser,
+ });
+
return label;
},
};
diff --git a/server/api/helpers/labels/delete-one.js b/server/api/helpers/labels/delete-one.js
index 654d97c7..da45eb9c 100644
--- a/server/api/helpers/labels/delete-one.js
+++ b/server/api/helpers/labels/delete-one.js
@@ -4,6 +4,18 @@ module.exports = {
type: 'ref',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ board: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -25,6 +37,18 @@ module.exports = {
},
inputs.request,
);
+
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'labelDelete',
+ data: {
+ item: label,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ },
+ },
+ user: inputs.actorUser,
+ });
}
return label;
diff --git a/server/api/helpers/labels/update-one.js b/server/api/helpers/labels/update-one.js
index 3237ce8c..01efcdbd 100644
--- a/server/api/helpers/labels/update-one.js
+++ b/server/api/helpers/labels/update-one.js
@@ -21,6 +21,18 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ board: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -53,6 +65,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
}
@@ -67,6 +81,18 @@ module.exports = {
},
inputs.request,
);
+
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'labelUpdate',
+ data: {
+ item: label,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ },
+ },
+ user: inputs.actorUser,
+ });
}
return label;
diff --git a/server/api/helpers/lists/create-one.js b/server/api/helpers/lists/create-one.js
index 1c65fcce..833ff6d2 100644
--- a/server/api/helpers/lists/create-one.js
+++ b/server/api/helpers/lists/create-one.js
@@ -21,6 +21,14 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -50,6 +58,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
const list = await List.create({
@@ -67,12 +77,16 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'LIST_CREATE',
- data: list,
- projectId: values.board.projectId,
- user: inputs.request.currentUser,
- board: values.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'listCreate',
+ data: {
+ item: list,
+ included: {
+ projects: [inputs.project],
+ boards: [values.board],
+ },
+ },
+ user: inputs.actorUser,
});
return list;
diff --git a/server/api/helpers/lists/delete-one.js b/server/api/helpers/lists/delete-one.js
index d4f7c49b..78041730 100644
--- a/server/api/helpers/lists/delete-one.js
+++ b/server/api/helpers/lists/delete-one.js
@@ -4,10 +4,18 @@ module.exports = {
type: 'ref',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -26,12 +34,16 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'LIST_DELETE',
- data: list,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- board: inputs.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'listDelete',
+ data: {
+ item: list,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ },
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/lists/sort-one.js b/server/api/helpers/lists/sort-one.js
index c5e4fbd2..58384ef6 100644
--- a/server/api/helpers/lists/sort-one.js
+++ b/server/api/helpers/lists/sort-one.js
@@ -11,6 +11,18 @@ module.exports = {
isIn: Object.values(List.SortTypes),
defaultsTo: List.SortTypes.NAME_ASC,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
+ board: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -65,6 +77,19 @@ module.exports = {
inputs.request,
);
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'listSort',
+ data: {
+ item: inputs.record,
+ included: {
+ cards,
+ projects: [inputs.project],
+ boards: [inputs.board],
+ },
+ },
+ user: inputs.actorUser,
+ });
+
return cards;
},
};
diff --git a/server/api/helpers/lists/update-one.js b/server/api/helpers/lists/update-one.js
index ba186b82..0335b9ee 100644
--- a/server/api/helpers/lists/update-one.js
+++ b/server/api/helpers/lists/update-one.js
@@ -21,10 +21,18 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -57,6 +65,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
}
@@ -72,12 +82,16 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'LIST_UPDATE',
- data: list,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- board: inputs.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'listUpdate',
+ data: {
+ item: list,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ },
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/notifications/create-one.js b/server/api/helpers/notifications/create-one.js
index f24e4bfa..95d88382 100644
--- a/server/api/helpers/notifications/create-one.js
+++ b/server/api/helpers/notifications/create-one.js
@@ -15,14 +15,14 @@ const valuesValidator = (value) => {
};
// TODO: use templates (views) to build html
-const buildAndSendEmail = async (user, board, card, action, notifiableUser) => {
+const buildAndSendEmail = async (board, card, action, actorUser, notifiableUser) => {
let emailData;
switch (action.type) {
case Action.Types.MOVE_CARD:
emailData = {
- subject: `${user.name} moved ${card.name} from ${action.data.fromList.name} to ${action.data.toList.name} on ${board.name}`,
+ subject: `${actorUser.name} moved ${card.name} from ${action.data.fromList.name} to ${action.data.toList.name} on ${board.name}`,
html:
- `${user.name} moved ` +
+ `
${actorUser.name} moved ` +
`${card.name} ` +
`from ${action.data.fromList.name} to ${action.data.toList.name} ` +
`on ${board.name}
`,
@@ -31,9 +31,9 @@ const buildAndSendEmail = async (user, board, card, action, notifiableUser) => {
break;
case Action.Types.COMMENT_CARD:
emailData = {
- subject: `${user.name} left a new comment to ${card.name} on ${board.name}`,
+ subject: `${actorUser.name} left a new comment to ${card.name} on ${board.name}`,
html:
- `${user.name} left a new comment to ` +
+ `
${actorUser.name} left a new comment to ` +
`${card.name} ` +
`on ${board.name}
` +
`${action.data.text}
`,
@@ -57,7 +57,7 @@ module.exports = {
custom: valuesValidator,
required: true,
},
- user: {
+ project: {
type: 'ref',
required: true,
},
@@ -65,10 +65,18 @@ module.exports = {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
card: {
type: 'ref',
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
},
async fn(inputs) {
@@ -96,9 +104,24 @@ module.exports = {
notifiableUser = await sails.helpers.users.getOne(notification.userId);
}
- buildAndSendEmail(inputs.user, inputs.board, inputs.card, values.action, notifiableUser);
+ buildAndSendEmail(inputs.board, inputs.card, values.action, inputs.actorUser, notifiableUser);
}
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'notificationCreate',
+ data: {
+ item: notification,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [inputs.card],
+ actions: [values.action],
+ },
+ },
+ user: inputs.actorUser,
+ });
+
return notification;
},
};
diff --git a/server/api/helpers/notifications/update-many.js b/server/api/helpers/notifications/update-many.js
index fee2c024..7775919d 100644
--- a/server/api/helpers/notifications/update-many.js
+++ b/server/api/helpers/notifications/update-many.js
@@ -12,8 +12,9 @@ module.exports = {
type: 'json',
required: true,
},
- user: {
+ actorUser: {
type: 'ref',
+ required: true,
},
request: {
type: 'ref',
@@ -23,7 +24,9 @@ module.exports = {
async fn(inputs) {
const { values } = inputs;
- const criteria = {};
+ const criteria = {
+ userId: inputs.actorUser.id,
+ };
if (_.every(inputs.recordsOrIds, _.isPlainObject)) {
criteria.id = sails.helpers.utils.mapRecords(inputs.recordsOrIds);
@@ -31,10 +34,6 @@ module.exports = {
criteria.id = inputs.recordsOrIds;
}
- if (inputs.user) {
- criteria.userId = inputs.user.id;
- }
-
const notifications = await Notification.update(criteria)
.set({ ...values })
.fetch();
@@ -48,6 +47,14 @@ module.exports = {
},
inputs.request,
);
+
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'notificationUpdate',
+ data: {
+ item: notification,
+ },
+ user: inputs.actorUser,
+ });
});
return notifications;
diff --git a/server/api/helpers/project-managers/create-one.js b/server/api/helpers/project-managers/create-one.js
index 56929d18..80a9a432 100644
--- a/server/api/helpers/project-managers/create-one.js
+++ b/server/api/helpers/project-managers/create-one.js
@@ -21,6 +21,10 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -55,6 +59,18 @@ module.exports = {
);
});
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'projectManagerCreate',
+ data: {
+ item: projectManager,
+ included: {
+ users: [values.user],
+ projects: [values.project],
+ },
+ },
+ user: inputs.actorUser,
+ });
+
return projectManager;
},
};
diff --git a/server/api/helpers/project-managers/delete-one.js b/server/api/helpers/project-managers/delete-one.js
index 3677836d..aa9b7487 100644
--- a/server/api/helpers/project-managers/delete-one.js
+++ b/server/api/helpers/project-managers/delete-one.js
@@ -4,6 +4,10 @@ module.exports = {
type: 'ref',
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -27,6 +31,14 @@ module.exports = {
inputs.request,
);
});
+
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'projectManagerDelete',
+ data: {
+ item: projectManager,
+ },
+ user: inputs.actorUser,
+ });
}
return projectManager;
diff --git a/server/api/helpers/projects/create-one.js b/server/api/helpers/projects/create-one.js
index 7deb9c4a..a22dd698 100644
--- a/server/api/helpers/projects/create-one.js
+++ b/server/api/helpers/projects/create-one.js
@@ -4,7 +4,7 @@ module.exports = {
type: 'json',
required: true,
},
- user: {
+ actorUser: {
type: 'ref',
required: true,
},
@@ -20,7 +20,7 @@ module.exports = {
const projectManager = await ProjectManager.create({
projectId: project.id,
- userId: inputs.user.id,
+ userId: inputs.actorUser.id,
}).fetch();
sails.sockets.broadcast(
@@ -32,11 +32,12 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'PROJECT_CREATE',
- data: project,
- projectId: project.id,
- user: inputs.request.currentUser,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'projectCreate',
+ data: {
+ item: project,
+ },
+ user: inputs.actorUser,
});
return {
diff --git a/server/api/helpers/projects/delete-one.js b/server/api/helpers/projects/delete-one.js
index 1021d272..c5b3c9dc 100644
--- a/server/api/helpers/projects/delete-one.js
+++ b/server/api/helpers/projects/delete-one.js
@@ -4,6 +4,10 @@ module.exports = {
type: 'ref',
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -38,11 +42,12 @@ module.exports = {
);
});
- await sails.helpers.utils.sendWebhook.with({
- event: 'PROJECT_DELETE',
- data: project,
- projectId: project.id,
- user: inputs.request.currentUser,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'projectDelete',
+ data: {
+ item: project,
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/projects/update-one.js b/server/api/helpers/projects/update-one.js
index 6b57a71c..f9e11eec 100644
--- a/server/api/helpers/projects/update-one.js
+++ b/server/api/helpers/projects/update-one.js
@@ -28,6 +28,10 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -109,11 +113,12 @@ module.exports = {
);
});
- await sails.helpers.utils.sendWebhook.with({
- event: 'PROJECT_UPDATE',
- data: project,
- projectId: project.id,
- user: inputs.request.currentUser,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'projectUpdate',
+ data: {
+ item: project,
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/tasks/create-one.js b/server/api/helpers/tasks/create-one.js
index 7bb33182..5b156235 100644
--- a/server/api/helpers/tasks/create-one.js
+++ b/server/api/helpers/tasks/create-one.js
@@ -21,10 +21,22 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -54,6 +66,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
const task = await Task.create({
@@ -71,13 +85,18 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'TASK_CREATE',
- data: task,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card: values.card,
- board: inputs.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'taskCreate',
+ data: {
+ item: task,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [values.card],
+ },
+ },
+ user: inputs.actorUser,
});
return task;
diff --git a/server/api/helpers/tasks/delete-one.js b/server/api/helpers/tasks/delete-one.js
index 3b876aea..c413e39d 100644
--- a/server/api/helpers/tasks/delete-one.js
+++ b/server/api/helpers/tasks/delete-one.js
@@ -4,10 +4,26 @@ module.exports = {
type: 'ref',
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
+ card: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -26,12 +42,18 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'TASK_DELETE',
- data: task,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- board: inputs.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'taskDelete',
+ data: {
+ item: task,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [inputs.card],
+ },
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/tasks/update-one.js b/server/api/helpers/tasks/update-one.js
index 6d6b81ba..94c1d4b7 100644
--- a/server/api/helpers/tasks/update-one.js
+++ b/server/api/helpers/tasks/update-one.js
@@ -21,10 +21,26 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ project: {
+ type: 'ref',
+ required: true,
+ },
board: {
type: 'ref',
required: true,
},
+ list: {
+ type: 'ref',
+ required: true,
+ },
+ card: {
+ type: 'ref',
+ required: true,
+ },
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -57,6 +73,8 @@ module.exports = {
position: nextPosition,
},
});
+
+ // TODO: send webhooks
});
}
@@ -72,13 +90,18 @@ module.exports = {
inputs.request,
);
- await sails.helpers.utils.sendWebhook.with({
- event: 'TASK_UPDATE',
- data: task,
- projectId: inputs.board.projectId,
- user: inputs.request.currentUser,
- card: values.card,
- board: inputs.board,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'taskUpdate',
+ data: {
+ item: task,
+ included: {
+ projects: [inputs.project],
+ boards: [inputs.board],
+ lists: [inputs.list],
+ cards: [inputs.card],
+ },
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/users/create-one.js b/server/api/helpers/users/create-one.js
index 87f36863..358ef679 100644
--- a/server/api/helpers/users/create-one.js
+++ b/server/api/helpers/users/create-one.js
@@ -27,6 +27,10 @@ module.exports = {
custom: valuesValidator,
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -84,21 +88,12 @@ module.exports = {
);
});
- /* The user could be created manually by an user or via OIDC. We hijack the id field, so one can differentiate between the two on the webhook side. */
- let initiator;
- if (inputs.request && inputs.request.currentUser) {
- initiator = inputs.request.currentUser;
- } else {
- initiator = {
- id: 'oidc',
- };
- }
-
- await sails.helpers.utils.sendWebhook.with({
- event: 'USER_CREATE',
- data: { ...user, password: undefined },
- projectId: '',
- user: initiator,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'userCreate',
+ data: {
+ item: user,
+ },
+ user: inputs.actorUser,
});
return user;
diff --git a/server/api/helpers/users/delete-one.js b/server/api/helpers/users/delete-one.js
index 524db4b5..5c9c9f59 100644
--- a/server/api/helpers/users/delete-one.js
+++ b/server/api/helpers/users/delete-one.js
@@ -4,6 +4,10 @@ module.exports = {
type: 'ref',
required: true,
},
+ actorUser: {
+ type: 'ref',
+ required: true,
+ },
request: {
type: 'ref',
},
@@ -60,11 +64,12 @@ module.exports = {
);
});
- await sails.helpers.utils.sendWebhook.with({
- event: 'USER_DELETE',
- data: { ...user, password: undefined },
- projectId: '',
- user: inputs.request.currentUser,
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'userDelete',
+ data: {
+ item: user,
+ },
+ user: inputs.actorUser,
});
}
diff --git a/server/api/helpers/users/get-or-create-one-using-oidc.js b/server/api/helpers/users/get-or-create-one-using-oidc.js
index 2186c099..465a55b6 100644
--- a/server/api/helpers/users/get-or-create-one-using-oidc.js
+++ b/server/api/helpers/users/get-or-create-one-using-oidc.js
@@ -12,6 +12,7 @@ module.exports = {
exits: {
invalidCodeOrNonce: {},
+ invalidUserinfoSignature: {},
missingValues: {},
emailAlreadyInUse: {},
usernameAlreadyInUse: {},
@@ -34,6 +35,14 @@ module.exports = {
);
userInfo = await client.userinfo(tokenSet);
} catch (e) {
+ if (
+ e instanceof SyntaxError &&
+ e.message.includes('Unexpected token e in JSON at position 0')
+ ) {
+ sails.log.warn('Error while exchanging OIDC code: userinfo response is signed');
+ throw 'invalidUserinfoSignature';
+ }
+
sails.log.warn(`Error while exchanging OIDC code: ${e}`);
throw 'invalidCodeOrNonce';
}
@@ -88,8 +97,11 @@ module.exports = {
// Otherwise, create a new user.
if (!user) {
- user = await sails.helpers.users
- .createOne(values)
+ user = await sails.helpers.users.createOne
+ .with({
+ values,
+ actorUser: User.OIDC,
+ })
.intercept('usernameAlreadyInUse', 'usernameAlreadyInUse');
}
@@ -115,8 +127,12 @@ module.exports = {
}
if (Object.keys(updateValues).length > 0) {
- user = await sails.helpers.users
- .updateOne(user, updateValues, {}) // FIXME: hack for last parameter
+ user = await sails.helpers.users.updateOne
+ .with({
+ record: user,
+ values: updateValues,
+ actorUser: User.OIDC,
+ })
.intercept('emailAlreadyInUse', 'emailAlreadyInUse')
.intercept('usernameAlreadyInUse', 'usernameAlreadyInUse');
}
diff --git a/server/api/helpers/users/update-one.js b/server/api/helpers/users/update-one.js
index a829b43e..4d2b3910 100644
--- a/server/api/helpers/users/update-one.js
+++ b/server/api/helpers/users/update-one.js
@@ -38,7 +38,7 @@ module.exports = {
custom: valuesValidator,
required: true,
},
- user: {
+ actorUser: {
type: 'ref',
required: true,
},
@@ -62,14 +62,14 @@ module.exports = {
let isOnlyPasswordChange = false;
if (!_.isUndefined(values.password)) {
+ if (Object.keys(values).length === 1) {
+ isOnlyPasswordChange = true;
+ }
+
Object.assign(values, {
password: bcrypt.hashSync(values.password, 10),
passwordChangedAt: new Date().toISOString(),
});
-
- if (Object.keys(values).length === 1) {
- isOnlyPasswordChange = true;
- }
}
if (values.username) {
@@ -118,7 +118,7 @@ module.exports = {
inputs.request,
);
- if (user.id === inputs.user.id && inputs.request && inputs.request.isSocket) {
+ if (user.id === inputs.actorUser.id && inputs.request && inputs.request.isSocket) {
const tempRoom = uuid();
sails.sockets.addRoomMembersToRooms(`@user:${user.id}`, tempRoom, () => {
@@ -153,14 +153,15 @@ module.exports = {
inputs.request,
);
});
- }
- await sails.helpers.utils.sendWebhook.with({
- event: 'USER_UPDATE',
- data: { ...user, password: undefined },
- projectId: '',
- user: inputs.request.currentUser,
- });
+ sails.helpers.utils.sendWebhooks.with({
+ event: 'userUpdate',
+ data: {
+ item: user,
+ },
+ user: inputs.actorUser,
+ });
+ }
}
return user;
diff --git a/server/api/helpers/utils/jsonify-record.js b/server/api/helpers/utils/jsonify-record.js
new file mode 100644
index 00000000..9927e09a
--- /dev/null
+++ b/server/api/helpers/utils/jsonify-record.js
@@ -0,0 +1,14 @@
+module.exports = {
+ sync: true,
+
+ inputs: {
+ record: {
+ type: 'ref',
+ required: true,
+ },
+ },
+
+ fn(inputs) {
+ return inputs.record.toJSON ? inputs.record.toJSON() : inputs.record;
+ },
+};
diff --git a/server/api/helpers/utils/send-email.js b/server/api/helpers/utils/send-email.js
index 02593f88..cb6a1e13 100644
--- a/server/api/helpers/utils/send-email.js
+++ b/server/api/helpers/utils/send-email.js
@@ -1,4 +1,6 @@
module.exports = {
+ // TODO: make sync?
+
inputs: {
to: {
type: 'string',
diff --git a/server/api/helpers/utils/send-slack-message.js b/server/api/helpers/utils/send-slack-message.js
index 510ae1b2..d17985e2 100644
--- a/server/api/helpers/utils/send-slack-message.js
+++ b/server/api/helpers/utils/send-slack-message.js
@@ -1,6 +1,8 @@
const POST_MESSAGE_API_URL = 'https://slack.com/api/chat.postMessage';
module.exports = {
+ // TODO: make sync?
+
inputs: {
markdown: {
type: 'string',
diff --git a/server/api/helpers/utils/send-webhook.js b/server/api/helpers/utils/send-webhook.js
deleted file mode 100644
index a33f7a89..00000000
--- a/server/api/helpers/utils/send-webhook.js
+++ /dev/null
@@ -1,115 +0,0 @@
-const EVENT_TYPES = {
- ACTION_CREATE: 'action_create',
- ACTION_UPDATE: 'action_update',
- ACTION_DELETE: 'action_delete',
-
- CARD_CREATE: 'card_create',
- CARD_UPDATE: 'card_update',
- CARD_DELETE: 'card_delete',
-
- CARD_MEMBERSHIP_CREATE: 'card_membership_create',
- CARD_MEMBERSHIP_DELETE: 'card_membership_delete',
-
- LIST_CREATE: 'list_create',
- LIST_UPDATE: 'list_update',
- LIST_DELETE: 'list_delete',
-
- BOARD_CREATE: 'board_create',
- BOARD_UPDATE: 'board_update',
- BOARD_DELETE: 'board_delete',
-
- ATTACHMENT_CREATE: 'attachment_create',
- ATTACHMENT_UPDATE: 'attachment_update',
- ATTACHMENT_DELETE: 'attachment_delete',
-
- PROJECT_CREATE: 'project_create',
- PROJECT_UPDATE: 'project_update',
- PROJECT_DELETE: 'project_delete',
-
- TASK_CREATE: 'task_create',
- TASK_UPDATE: 'task_update',
- TASK_DELETE: 'task_delete',
-
- USER_CREATE: 'user_create',
- USER_UPDATE: 'user_update',
- USER_DELETE: 'user_delete',
-};
-
-/**
- * Sends a webhook notification to a configured URL.
- *
- * @param {Object} inputs - Data to include in the webhook payload.
- * @param {string} inputs.event - The event type (see {@link EVENT_TYPES}).
- * @param {*} inputs.data - The actual data related to the event.
- * @param {string} inputs.projectId - The project ID associated with the event.
- * @param {ref} [inputs.user] - Optional user object associated with the event.
- * @param {ref} [inputs.card] - Optional card object associated with the event.
- * @param {ref} [inputs.board] - Optional board object associated with the event.
- * @param {ref} [inputs.list] - Optional list object associated with the event.
- * @returns {Promise}
- */
-async function sendWebhook(inputs) {
- const url = sails.config.custom.webhookUrl;
- const headers = {
- 'Content-Type': 'application/json',
- };
- if (sails.config.custom.webhookBearer) {
- headers.Authorization = `Bearer ${sails.config.custom.webhookBearer}`;
- }
-
- const body = JSON.stringify({
- ...inputs,
- user: {
- ...inputs.user,
- password: undefined,
- },
- });
-
- const req = await fetch(url, {
- method: 'POST',
- headers,
- body,
- });
- if (req.status !== 200) {
- sails.log.error(`Webhook failed with status ${req.status} and message: ${await req.text()}`);
- }
-}
-
-module.exports = {
- eventTypes: EVENT_TYPES,
- inputs: {
- event: {
- type: 'string',
- isIn: Object.keys(EVENT_TYPES),
- required: true,
- },
- data: {
- type: 'ref',
- required: true,
- },
- projectId: {
- type: 'string',
- default: '',
- },
- user: {
- type: 'ref',
- },
- card: {
- type: 'ref',
- },
- board: {
- type: 'ref',
- },
- list: {
- type: 'ref',
- },
- },
- async fn(inputs) {
- if (!sails.config.custom.webhookUrl) return;
- try {
- await sendWebhook(inputs);
- } catch (err) {
- sails.log.error(err);
- }
- },
-};
diff --git a/server/api/helpers/utils/send-webhooks.js b/server/api/helpers/utils/send-webhooks.js
new file mode 100644
index 00000000..addfb8af
--- /dev/null
+++ b/server/api/helpers/utils/send-webhooks.js
@@ -0,0 +1,178 @@
+const EVENT_TYPES = {
+ ACTION_CREATE: 'actionCreate',
+ ACTION_DELETE: 'actionDelete',
+ ACTION_UPDATE: 'actionUpdate',
+
+ ATTACHMENT_CREATE: 'attachmentCreate',
+ ATTACHMENT_DELETE: 'attachmentDelete',
+ ATTACHMENT_UPDATE: 'attachmentUpdate',
+
+ BOARD_CREATE: 'boardCreate',
+ BOARD_DELETE: 'boardDelete',
+ BOARD_UPDATE: 'boardUpdate',
+
+ BOARD_MEMBERSHIP_CREATE: 'boardMembershipCreate',
+ BOARD_MEMBERSHIP_DELETE: 'boardMembershipDelete',
+ BOARD_MEMBERSHIP_UPDATE: 'boardMembershipUpdate',
+
+ CARD_CREATE: 'cardCreate',
+ CARD_DELETE: 'cardDelete',
+ CARD_UPDATE: 'cardUpdate',
+
+ CARD_LABEL_CREATE: 'cardLabelCreate',
+ CARD_LABEL_DELETE: 'cardLabelDelete',
+
+ CARD_MEMBERSHIP_CREATE: 'cardMembershipCreate',
+ CARD_MEMBERSHIP_DELETE: 'cardMembershipDelete',
+
+ LABEL_CREATE: 'labelCreate',
+ LABEL_DELETE: 'labelDelete',
+ LABEL_UPDATE: 'labelUpdate',
+
+ LIST_CREATE: 'listCreate',
+ LIST_DELETE: 'listDelete',
+ LIST_SORT: 'listSort',
+ LIST_UPDATE: 'listUpdate',
+
+ NOTIFICATION_CREATE: 'notificationCreate',
+ NOTIFICATION_UPDATE: 'notificationUpdate',
+
+ PROJECT_CREATE: 'projectCreate',
+ PROJECT_DELETE: 'projectDelete',
+ PROJECT_UPDATE: 'projectUpdate',
+
+ PROJECT_MANAGER_CREATE: 'projectManagerCreate',
+ PROJECT_MANAGER_DELETE: 'projectManagerDelete',
+
+ TASK_CREATE: 'taskCreate',
+ TASK_DELETE: 'taskDelete',
+ TASK_UPDATE: 'taskUpdate',
+
+ USER_CREATE: 'userCreate',
+ USER_DELETE: 'userDelete',
+ USER_UPDATE: 'userUpdate',
+};
+
+const jsonifyData = (data) => {
+ const nextData = {};
+
+ if (data.item) {
+ nextData.item = sails.helpers.utils.jsonifyRecord(data.item);
+ }
+
+ if (data.items) {
+ nextData.items = data.items.map((item) => sails.helpers.utils.jsonifyRecord(item));
+ }
+
+ if (data.included) {
+ nextData.included = Object.entries(data.included).reduce(
+ (result, [key, items]) => ({
+ ...result,
+ [key]: items.map((item) => sails.helpers.utils.jsonifyRecord(item)),
+ }),
+ {},
+ );
+ }
+
+ return nextData;
+};
+
+/**
+ * @typedef {Object} Included
+ * @property {any[]} [projects] - Array of projects (optional).
+ * @property {any[]} [boards] - Array of boards (optional).
+ * @property {any[]} [lists] - Array of lists (optional).
+ * @property {any[]} [cards] - Array of cards (optional).
+ */
+
+/**
+ * @typedef {Object} Data
+ * @property {any} item - Actual event data.
+ * @property {Included} [included] - Optional included data.
+ */
+
+/**
+ * Sends a webhook notification to a configured URL.
+ *
+ * @param {*} webhook - Webhook configuration.
+ * @param {string} event - The event (see {@link EVENT_TYPES}).
+ * @param {Data} data - The data object containing event data and optionally included data.
+ * @param {ref} user - User object associated with the event.
+ * @returns {Promise}
+ */
+async function sendWebhook(webhook, event, data, user) {
+ const headers = {
+ 'Content-Type': 'application/json',
+ 'User-Agent': `planka (+${sails.config.custom.baseUrl})`,
+ };
+
+ if (webhook.accessToken) {
+ headers.Authorization = `Bearer ${webhook.accessToken}`;
+ }
+
+ const body = JSON.stringify({
+ event,
+ data: jsonifyData(data),
+ user: sails.helpers.utils.jsonifyRecord(user),
+ });
+
+ try {
+ const response = await fetch(webhook.url, {
+ headers,
+ body,
+ method: 'POST',
+ });
+
+ if (!response.ok) {
+ const message = await response.text();
+
+ sails.log.error(
+ `Webhook ${webhook.url} failed with status ${response.status} and message: ${message}`,
+ );
+ }
+ } catch (e) {
+ sails.log.error(`Webhook ${webhook.url} failed with error message: ${e.message}`);
+ }
+}
+
+module.exports = {
+ sync: true,
+
+ inputs: {
+ event: {
+ type: 'string',
+ required: true,
+ isIn: Object.values(EVENT_TYPES),
+ },
+ data: {
+ type: 'ref',
+ required: true,
+ },
+ user: {
+ type: 'ref',
+ required: true,
+ },
+ },
+
+ fn(inputs) {
+ if (!sails.config.custom.webhooks) {
+ return;
+ }
+
+ sails.config.custom.webhooks.forEach((webhook) => {
+ if (!webhook.url) {
+ return;
+ }
+
+ if (webhook.excludedEvents && webhook.excludedEvents.includes(inputs.event)) {
+ return;
+ }
+
+ if (webhook.events && !webhook.events.includes(inputs.event)) {
+ return;
+ }
+
+ sendWebhook(webhook, inputs.event, inputs.data, inputs.user);
+ });
+ },
+};
diff --git a/server/api/hooks/oidc/index.js b/server/api/hooks/oidc/index.js
index 6dbeddd1..47c2bf7a 100644
--- a/server/api/hooks/oidc/index.js
+++ b/server/api/hooks/oidc/index.js
@@ -25,12 +25,19 @@ module.exports = function defineOidcHook(sails) {
const issuer = await openidClient.Issuer.discover(sails.config.custom.oidcIssuer);
- client = new issuer.Client({
+ const metadata = {
client_id: sails.config.custom.oidcClientId,
client_secret: sails.config.custom.oidcClientSecret,
redirect_uris: [sails.config.custom.oidcRedirectUri],
response_types: ['code'],
- });
+ userinfo_signed_response_alg: sails.config.custom.oidcUserinfoSignedResponseAlg,
+ };
+
+ if (sails.config.custom.oidcIdTokenSignedResponseAlg) {
+ metadata.id_token_signed_response_alg = sails.config.custom.oidcIdTokenSignedResponseAlg;
+ }
+
+ client = new issuer.Client(metadata);
},
getClient() {
diff --git a/server/api/models/User.js b/server/api/models/User.js
index 1d875318..486a66b2 100755
--- a/server/api/models/User.js
+++ b/server/api/models/User.js
@@ -5,7 +5,41 @@
* @docs :: https://sailsjs.com/docs/concepts/models-and-orm/models
*/
+const LANGUAGES = [
+ 'bg-BG',
+ 'cs-CZ',
+ 'da-DK',
+ 'de-DE',
+ 'en-US',
+ 'es-ES',
+ 'fa-IR',
+ 'fr-FR',
+ 'hu-HU',
+ 'id-ID',
+ 'it-IT',
+ 'ja-JP',
+ 'ko-KR',
+ 'nl-NL',
+ 'pl-PL',
+ 'pt-BR',
+ 'ro-RO',
+ 'ru-RU',
+ 'sk-SK',
+ 'sv-SE',
+ 'tr-TR',
+ 'uk-UA',
+ 'uz-UZ',
+ 'zh-CN',
+];
+
+const OIDC = {
+ id: '_oidc',
+};
+
module.exports = {
+ LANGUAGES,
+ OIDC,
+
attributes: {
// ╔═╗╦═╗╦╔╦╗╦╔╦╗╦╦ ╦╔═╗╔═╗
// ╠═╝╠╦╝║║║║║ ║ ║╚╗╔╝║╣ ╚═╗
@@ -56,7 +90,7 @@ module.exports = {
},
language: {
type: 'string',
- isNotEmptyString: true,
+ isIn: LANGUAGES,
allowNull: true,
},
subscribeToOwnCards: {
diff --git a/server/config/custom.js b/server/config/custom.js
index 8e335c50..6d641573 100644
--- a/server/config/custom.js
+++ b/server/config/custom.js
@@ -34,10 +34,16 @@ module.exports.custom = {
defaultAdminEmail:
process.env.DEFAULT_ADMIN_EMAIL && process.env.DEFAULT_ADMIN_EMAIL.toLowerCase(),
+ allowAllToCreateProjects: process.env.ALLOW_ALL_TO_CREATE_PROJECTS === 'true',
+
oidcIssuer: process.env.OIDC_ISSUER,
oidcClientId: process.env.OIDC_CLIENT_ID,
oidcClientSecret: process.env.OIDC_CLIENT_SECRET,
+ oidcIdTokenSignedResponseAlg: process.env.OIDC_ID_TOKEN_SIGNED_RESPONSE_ALG,
+ oidcUserinfoSignedResponseAlg: process.env.OIDC_USERINFO_SIGNED_RESPONSE_ALG,
oidcScopes: process.env.OIDC_SCOPES || 'openid email profile',
+ oidcResponseMode: process.env.OIDC_RESPONSE_MODE || 'fragment',
+ oidcUseDefaultResponseMode: process.env.OIDC_USE_DEFAULT_RESPONSE_MODE === 'true',
oidcAdminRoles: process.env.OIDC_ADMIN_ROLES ? process.env.OIDC_ADMIN_ROLES.split(',') : [],
oidcEmailAttribute: process.env.OIDC_EMAIL_ATTRIBUTE || 'email',
oidcNameAttribute: process.env.OIDC_NAME_ATTRIBUTE || 'name',
@@ -60,9 +66,8 @@ module.exports.custom = {
smtpPassword: process.env.SMTP_PASSWORD,
smtpFrom: process.env.SMTP_FROM,
+ webhooks: JSON.parse(process.env.WEBHOOKS || '[]'), // TODO: validate structure
+
slackBotToken: process.env.SLACK_BOT_TOKEN,
slackChannelId: process.env.SLACK_CHANNEL_ID,
-
- webhookUrl: process.env.WEBHOOK_URL,
- webhookBearer: process.env.WEBHOOK_BEARER,
};
diff --git a/server/config/http.js b/server/config/http.js
index c25ed29a..42d7a9cc 100644
--- a/server/config/http.js
+++ b/server/config/http.js
@@ -48,5 +48,7 @@ module.exports.http = {
// var middlewareFn = skipper({ strict: true });
// return middlewareFn;
// })(),
+
+ poweredBy: false,
},
};
diff --git a/server/config/policies.js b/server/config/policies.js
index 665689df..a871368e 100644
--- a/server/config/policies.js
+++ b/server/config/policies.js
@@ -21,8 +21,6 @@ module.exports.policies = {
'users/create': ['is-authenticated', 'is-admin'],
'users/delete': ['is-authenticated', 'is-admin'],
- 'projects/create': ['is-authenticated', 'is-admin'],
-
'show-config': true,
'access-tokens/create': true,
'access-tokens/exchange-using-oidc': true,
diff --git a/server/db/migrations/20220523131229_add_image_to_attachment_table.js b/server/db/migrations/20220523131229_add_image_to_attachment_table.js
index 989f6957..25d6f62f 100644
--- a/server/db/migrations/20220523131229_add_image_to_attachment_table.js
+++ b/server/db/migrations/20220523131229_add_image_to_attachment_table.js
@@ -15,7 +15,7 @@ module.exports.up = async (knex) => {
const attachments = await knex('attachment');
// eslint-disable-next-line no-restricted-syntax
- for (attachment of attachments) {
+ for (const attachment of attachments) {
if (attachment.is_image) {
const image = sharp(
path.join(config.custom.attachmentsPath, attachment.dirname, attachment.filename),
@@ -54,7 +54,7 @@ module.exports.down = async (knex) => {
const attachments = await knex('attachment');
// eslint-disable-next-line no-restricted-syntax
- for (attachment of attachments) {
+ for (const attachment of attachments) {
// eslint-disable-next-line no-await-in-loop
await knex('attachment')
.update({
diff --git a/server/db/migrations/20221223131625_preserve_original_format_of_images.js b/server/db/migrations/20221223131625_preserve_original_format_of_images.js
index de2ec07c..f78762d2 100644
--- a/server/db/migrations/20221223131625_preserve_original_format_of_images.js
+++ b/server/db/migrations/20221223131625_preserve_original_format_of_images.js
@@ -93,7 +93,7 @@ module.exports.up = async (knex) => {
const attachments = await knex('attachment').whereNotNull('image');
// eslint-disable-next-line no-restricted-syntax
- for (attachment of attachments) {
+ for (const attachment of attachments) {
// eslint-disable-next-line no-await-in-loop
const image = await processAttachmentImage(attachment, config.custom.attachmentsPath);
diff --git a/server/db/migrations/20221226210239_improve_quality_of_resized_images.js b/server/db/migrations/20221226210239_improve_quality_of_resized_images.js
index fed01d40..b6e1e23c 100644
--- a/server/db/migrations/20221226210239_improve_quality_of_resized_images.js
+++ b/server/db/migrations/20221226210239_improve_quality_of_resized_images.js
@@ -113,7 +113,7 @@ module.exports.up = async (knex) => {
const users = await knex('user_account').whereNotNull('avatar');
// eslint-disable-next-line no-restricted-syntax
- for (user of users) {
+ for (const user of users) {
// eslint-disable-next-line no-await-in-loop
await processUserAvatar(user, config.custom.userAvatarsPath);
}
@@ -121,7 +121,7 @@ module.exports.up = async (knex) => {
const projects = await knex('project').whereNotNull('background_image');
// eslint-disable-next-line no-restricted-syntax
- for (project of projects) {
+ for (const project of projects) {
// eslint-disable-next-line no-await-in-loop
await processProjectBackgroundImage(project, config.custom.projectBackgroundImagesPath);
}
@@ -129,7 +129,7 @@ module.exports.up = async (knex) => {
const attachments = await knex('attachment').whereNotNull('image');
// eslint-disable-next-line no-restricted-syntax
- for (attachment of attachments) {
+ for (const attachment of attachments) {
// eslint-disable-next-line no-await-in-loop
await processAttachmentImage(attachment, config.custom.attachmentsPath);
}
diff --git a/server/db/migrations/20240721171239_languages_with_country_codes.js b/server/db/migrations/20240721171239_languages_with_country_codes.js
new file mode 100644
index 00000000..083dae91
--- /dev/null
+++ b/server/db/migrations/20240721171239_languages_with_country_codes.js
@@ -0,0 +1,68 @@
+const _ = require('lodash');
+
+const LANGUAGES = [
+ 'bg-BG',
+ 'cs-CZ',
+ 'da-DK',
+ 'de-DE',
+ 'en-US',
+ 'es-ES',
+ 'fa-IR',
+ 'fr-FR',
+ 'hu-HU',
+ 'id-ID',
+ 'it-IT',
+ 'ja-JP',
+ 'ko-KR',
+ 'nl-NL',
+ 'pl-PL',
+ 'pt-BR',
+ 'ro-RO',
+ 'ru-RU',
+ 'sk-SK',
+ 'sv-SE',
+ 'tr-TR',
+ 'uz-UZ',
+ 'zh-CN',
+];
+
+const LANGUAGE_BY_PREV_LANGUAGE = LANGUAGES.reduce(
+ (result, language) => ({
+ ...result,
+ [language.split('-')[0]]: language,
+ }),
+ {},
+);
+LANGUAGE_BY_PREV_LANGUAGE.ua = 'uk-UA';
+
+const PREV_LANGUAGE_BY_LANGUAGE = _.invert(LANGUAGE_BY_PREV_LANGUAGE);
+
+module.exports.up = async (knex) => {
+ const users = await knex('user_account').whereNotNull('language');
+ const prevLanguages = [...new Set(users.map((user) => user.language))];
+
+ // eslint-disable-next-line no-restricted-syntax
+ for (const prevLanguage of prevLanguages) {
+ // eslint-disable-next-line no-await-in-loop
+ await knex('user_account')
+ .update({
+ language: LANGUAGE_BY_PREV_LANGUAGE[prevLanguage],
+ })
+ .where('language', prevLanguage);
+ }
+};
+
+module.exports.down = async (knex) => {
+ const users = await knex('user_account').whereNotNull('language');
+ const languages = [...new Set(users.map((user) => user.language))];
+
+ // eslint-disable-next-line no-restricted-syntax
+ for (const language of languages) {
+ // eslint-disable-next-line no-await-in-loop
+ await knex('user_account')
+ .update({
+ language: PREV_LANGUAGE_BY_LANGUAGE[language],
+ })
+ .where('language', language);
+ }
+};
diff --git a/server/package-lock.json b/server/package-lock.json
index 3551a014..6487f43c 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -2164,9 +2164,9 @@
}
},
"node_modules/engine.io": {
- "version": "6.5.4",
- "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz",
- "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==",
+ "version": "6.5.5",
+ "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz",
+ "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==",
"dependencies": {
"@types/cookie": "^0.4.1",
"@types/cors": "^2.8.12",
@@ -2177,7 +2177,7 @@
"cors": "~2.8.5",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
- "ws": "~8.11.0"
+ "ws": "~8.17.1"
},
"engines": {
"node": ">=10.2.0"
@@ -7119,12 +7119,12 @@
}
},
"node_modules/socket.io-adapter": {
- "version": "2.5.4",
- "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz",
- "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==",
+ "version": "2.5.5",
+ "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz",
+ "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==",
"dependencies": {
"debug": "~4.3.4",
- "ws": "~8.11.0"
+ "ws": "~8.17.1"
}
},
"node_modules/socket.io-parser": {
@@ -8190,15 +8190,15 @@
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/ws": {
- "version": "8.11.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
- "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
+ "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
- "utf-8-validate": "^5.0.2"
+ "utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {