|
|
@@ -4,7 +4,7 @@ const express = require('express');
|
|
|
const mongoose = require('mongoose');
|
|
|
const urljoin = require('url-join');
|
|
|
|
|
|
-const { verifySlackRequest, generateWebClient } = require('@growi/slack');
|
|
|
+const { verifySlackRequest, generateWebClient, getSupportedGrowiActionsRegExps } = require('@growi/slack');
|
|
|
|
|
|
const logger = loggerFactory('growi:routes:apiv3:slack-integration');
|
|
|
const router = express.Router();
|
|
|
@@ -44,6 +44,55 @@ module.exports = (crowi) => {
|
|
|
next();
|
|
|
}
|
|
|
|
|
|
+ async function checkCommandPermission(req, res, next) {
|
|
|
+ const tokenPtoG = req.headers['x-growi-ptog-tokens'];
|
|
|
+
|
|
|
+ const relation = await SlackAppIntegration.findOne({ tokenPtoG });
|
|
|
+ const { supportedCommandsForBroadcastUse, supportedCommandsForSingleUse } = relation;
|
|
|
+ const supportedCommands = supportedCommandsForBroadcastUse.concat(supportedCommandsForSingleUse);
|
|
|
+ const supportedGrowiActionsRegExps = getSupportedGrowiActionsRegExps(supportedCommands);
|
|
|
+
|
|
|
+ // get command name from req.body
|
|
|
+ let command = '';
|
|
|
+ let actionId = '';
|
|
|
+ let callbackId = '';
|
|
|
+ let payload;
|
|
|
+ if (req.body.payload) {
|
|
|
+ payload = JSON.parse(req.body.payload);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (req.body.text == null && !payload) { // when /relation-test
|
|
|
+ return next();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!payload) { // when request is to /commands
|
|
|
+ command = req.body.text.split(' ')[0];
|
|
|
+ }
|
|
|
+ else if (payload.actions) { // when request is to /interactions && block_actions
|
|
|
+ actionId = payload.actions[0].action_id;
|
|
|
+ }
|
|
|
+ else { // when request is to /interactions && view_submission
|
|
|
+ callbackId = payload.view.callback_id;
|
|
|
+ }
|
|
|
+
|
|
|
+ let isActionSupported = false;
|
|
|
+ supportedGrowiActionsRegExps.forEach((regexp) => {
|
|
|
+ if (regexp.test(actionId) || regexp.test(callbackId)) {
|
|
|
+ isActionSupported = true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ // validate
|
|
|
+ if (command && !supportedCommands.includes(command)) {
|
|
|
+ return res.status(403).send(`It is not allowed to run '${command}' command to this GROWI.`);
|
|
|
+ }
|
|
|
+ if ((actionId || callbackId) && !isActionSupported) {
|
|
|
+ return res.status(403).send(`It is not allowed to run '${command}' command to this GROWI.`);
|
|
|
+ }
|
|
|
+
|
|
|
+ next();
|
|
|
+ }
|
|
|
+
|
|
|
const addSigningSecretToReq = (req, res, next) => {
|
|
|
req.slackSigningSecret = configManager.getConfig('crowi', 'slackbot:signingSecret');
|
|
|
return next();
|
|
|
@@ -117,7 +166,7 @@ module.exports = (crowi) => {
|
|
|
return handleCommands(req, res);
|
|
|
});
|
|
|
|
|
|
- router.post('/proxied/commands', verifyAccessTokenFromProxy, async(req, res) => {
|
|
|
+ router.post('/proxied/commands', verifyAccessTokenFromProxy, checkCommandPermission, async(req, res) => {
|
|
|
const { body } = req;
|
|
|
|
|
|
// eslint-disable-next-line max-len
|
|
|
@@ -182,7 +231,7 @@ module.exports = (crowi) => {
|
|
|
return handleInteractions(req, res);
|
|
|
});
|
|
|
|
|
|
- router.post('/proxied/interactions', verifyAccessTokenFromProxy, async(req, res) => {
|
|
|
+ router.post('/proxied/interactions', verifyAccessTokenFromProxy, checkCommandPermission, async(req, res) => {
|
|
|
return handleInteractions(req, res);
|
|
|
});
|
|
|
|