Explorar el Código

Merge pull request #4148 from weseek/feat/7018-p2g-validation

Feat/7018 p2g validation
Yuki Takei hace 4 años
padre
commit
df0fd05e1d

+ 3 - 0
packages/app/src/server/models/index.js

@@ -18,4 +18,7 @@ module.exports = {
   GlobalNotificationSlackSetting: require('./GlobalNotificationSetting/GlobalNotificationSlackSetting'),
   ShareLink: require('./share-link'),
   SlackAppIntegration: require('./slack-app-integration'),
+  // MOCK DATA DELETE THIS GW-6972 ---------------
+  SlackAppIntegrationMock: require('./slack-app-integration-mock'),
+  // MOCK DATA DELETE THIS GW-6972 ---------------
 };

+ 5 - 3
packages/app/src/server/models/slack-app-integration-mock.js

@@ -1,15 +1,17 @@
 const crypto = require('crypto');
 const mongoose = require('mongoose');
 
-const permittedChannelsSchema = new mongoose.Schema({
-  channelsObject: {},
+const permittedChannelsForEachCommandSchema = new mongoose.Schema({
+  channelsObject: Map,
 });
 
 
 const schema = new mongoose.Schema({
   tokenGtoP: { type: String, required: true, unique: true },
   tokenPtoG: { type: String, required: true, unique: true },
-  permittedChannels: permittedChannelsSchema,
+  supportedCommandsForBroadcastUse: { type: [String], default: [] },
+  supportedCommandsForSingleUse: { type: [String], default: [] },
+  permittedChannelsForEachCommand: permittedChannelsForEachCommandSchema,
 });
 
 class SlackAppIntegrationMock {

+ 12 - 0
packages/app/src/server/routes/apiv3/slack-integration-settings.js

@@ -415,6 +415,18 @@ module.exports = (crowi) => {
         supportedCommandsForBroadcastUse: defaultSupportedCommandsNameForBroadcastUse,
         supportedCommandsForSingleUse: defaultSupportedCommandsNameForSingleUse,
       });
+      // MOCK DATA DELETE THIS GW-6972 ---------------
+      const SlackAppIntegrationMock = mongoose.model('SlackAppIntegrationMock');
+      const MOCK = await SlackAppIntegrationMock.create({
+        tokenGtoP,
+        tokenPtoG,
+        supportedCommandsForBroadcastUse: defaultSupportedCommandsNameForBroadcastUse,
+        supportedCommandsForSingleUse: defaultSupportedCommandsNameForSingleUse,
+        permittedChannelsForEachCommand: {
+          channelsObject: new Map(),
+        },
+      });
+      // MOCK DATA DELETE THIS GW-6972 ---------------
       return res.apiv3(slackAppTokens, 200);
     }
     catch (error) {

+ 28 - 8
packages/app/src/server/routes/apiv3/slack-integration.js

@@ -45,9 +45,22 @@ module.exports = (crowi) => {
   }
 
   async function checkCommandPermission(req, res, next) {
+    let payload;
+    if (req.body.payload) {
+      payload = JSON.parse(req.body.payload);
+    }
+    if (req.body.text == null && !payload) { // when /relation-test
+      return next();
+    }
+
     const tokenPtoG = req.headers['x-growi-ptog-tokens'];
 
     const relation = await SlackAppIntegration.findOne({ tokenPtoG });
+    // MOCK DATA DELETE THIS GW-6972 ---------------
+    const SlackAppIntegrationMock = mongoose.model('SlackAppIntegrationMock');
+    const slackAppIntegrationMock = await SlackAppIntegrationMock.findOne({ tokenPtoG });
+    const channelsObject = slackAppIntegrationMock.permittedChannelsForEachCommand._doc.channelsObject;
+    // MOCK DATA DELETE THIS GW-6972 ---------------
     const { supportedCommandsForBroadcastUse, supportedCommandsForSingleUse } = relation;
     const supportedCommands = supportedCommandsForBroadcastUse.concat(supportedCommandsForSingleUse);
     const supportedGrowiActionsRegExps = getSupportedGrowiActionsRegExps(supportedCommands);
@@ -56,14 +69,6 @@ module.exports = (crowi) => {
     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];
@@ -75,6 +80,21 @@ module.exports = (crowi) => {
       callbackId = payload.view.callback_id;
     }
 
+    // code below checks permission at channel level
+    const fromChannel = req.body.channel_name || payload.channel.name;
+    [...channelsObject.keys()].forEach((commandName) => {
+      const permittedChannels = channelsObject.get(commandName);
+      // ex. search OR search:hogehoge
+      const commandRegExp = new RegExp(`(^${commandName}$)|(^${commandName}:\\w+)`);
+
+      // RegExp check
+      if (commandRegExp.test(commandName) || commandRegExp.test(actionId) || commandRegExp.test(callbackId)) {
+        // check if the channel is permitted
+        if (permittedChannels.includes(fromChannel)) return next();
+      }
+    });
+
+    // code below checks permission at command level
     let isActionSupported = false;
     supportedGrowiActionsRegExps.forEach((regexp) => {
       if (regexp.test(actionId) || regexp.test(callbackId)) {