Taichi Masuyama 4 лет назад
Родитель
Сommit
751573ad1e

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

@@ -9,9 +9,8 @@ const permittedChannelsForEachCommandSchema = new mongoose.Schema({
 const schema = new mongoose.Schema({
   tokenGtoP: { type: String, required: true, unique: true },
   tokenPtoG: { type: String, required: true, unique: true },
-  supportedCommandsForBroadcastUse: { type: [String], default: [] },
-  supportedCommandsForSingleUse: { type: [String], default: [] },
-  permittedChannelsForEachCommand: permittedChannelsForEachCommandSchema,
+  permissionsForBroadcastUseCommands: Map,
+  permissionsForSingleUseCommands: Map,
 });
 
 class SlackAppIntegrationMock {

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

@@ -416,18 +416,21 @@ module.exports = (crowi) => {
         supportedCommandsForSingleUse: defaultSupportedCommandsNameForSingleUse,
       });
       // MOCK DATA DELETE THIS GW-6972 ---------------
-      /**
-       * this code represents the creation of new SlackAppIntegration model
-       */
+      /* This code represents the creation of the new SlackAppIntegration model instance. */
       const SlackAppIntegrationMock = mongoose.model('SlackAppIntegrationMock');
+      const initialSupportedCommandsForBroadcastUse = new Map();
+      const initialSupportedCommandsForSingleUse = new Map();
+      defaultSupportedCommandsNameForBroadcastUse.forEach((commandName) => {
+        initialSupportedCommandsForBroadcastUse.set(commandName, true);
+      });
+      defaultSupportedCommandsNameForSingleUse.forEach((commandName) => {
+        initialSupportedCommandsForSingleUse.set(commandName, true);
+      });
       const MOCK = await SlackAppIntegrationMock.create({
         tokenGtoP,
         tokenPtoG,
-        supportedCommandsForBroadcastUse: defaultSupportedCommandsNameForBroadcastUse,
-        supportedCommandsForSingleUse: defaultSupportedCommandsNameForSingleUse,
-        permittedChannelsForEachCommand: {
-          channelsObject: new Map(),
-        },
+        permissionsForBroadcastUseCommands: initialSupportedCommandsForBroadcastUse,
+        permissionsForSingleUseCommands: initialSupportedCommandsForSingleUse,
       });
       // MOCK DATA DELETE THIS GW-6972 ---------------
       return res.apiv3(slackAppTokens, 200);

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

@@ -59,11 +59,10 @@ module.exports = (crowi) => {
     // MOCK DATA DELETE THIS GW-6972 ---------------
     const SlackAppIntegrationMock = mongoose.model('SlackAppIntegrationMock');
     const slackAppIntegrationMock = await SlackAppIntegrationMock.findOne({ tokenPtoG });
-    const channelsObject = slackAppIntegrationMock.permittedChannelsForEachCommand._doc.channelsObject;
+    const permissionsForBroadcastUseCommands = slackAppIntegrationMock.permissionsForBroadcastUseCommands;
+    const permissionsForSingleUseCommands = slackAppIntegrationMock.permissionsForSingleUseCommands;
     // MOCK DATA DELETE THIS GW-6972 ---------------
     const { supportedCommandsForBroadcastUse, supportedCommandsForSingleUse } = relation;
-    const supportedCommands = supportedCommandsForBroadcastUse.concat(supportedCommandsForSingleUse);
-    const supportedGrowiActionsRegExps = getSupportedGrowiActionsRegExps(supportedCommands);
 
     // get command name from req.body
     let command = '';
@@ -82,35 +81,36 @@ module.exports = (crowi) => {
 
     // 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
+    let isPermitted = false;
+    [...permissionsForBroadcastUseCommands.keys(), ...permissionsForSingleUseCommands.keys()].forEach((commandName) => {
+      // boolean or string[]
+      let permission = permissionsForBroadcastUseCommands.get(commandName);
+      if (permission === undefined) {
+        permission = permissionsForSingleUseCommands.get(commandName);
+      }
+
+      // ex. search OR search:handlerName
       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();
+      // skip this forEach loop if the requested command is not in permissionsForBroadcastUseCommands key
+      if (!commandRegExp.test(command) && !commandRegExp.test(actionId) && !commandRegExp.test(callbackId)) {
+        return;
       }
-    });
 
-    // code below checks permission at command level
-    let isActionSupported = false;
-    supportedGrowiActionsRegExps.forEach((regexp) => {
-      if (regexp.test(actionId) || regexp.test(callbackId)) {
-        isActionSupported = true;
+      // permission check
+      if (permission === true) {
+        isPermitted = true;
+        return;
+      }
+      if (Array.isArray(permission) && permission.includes(fromChannel)) {
+        isPermitted = 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.`);
+    if (isPermitted) {
+      return next();
     }
-
-    next();
+    res.status(403).send(`It is not allowed to run '${command}' command to this GROWI.`);
   }
 
   const addSigningSecretToReq = (req, res, next) => {

+ 5 - 14
packages/slackbot-proxy/src/entities/relation-mock.ts

@@ -4,14 +4,8 @@ import {
 } from 'typeorm';
 import { Installation } from './installation';
 
-
-// expected data see below
-//   commandToChannelMap: {
-//     create: ['srv', 'admin'],
-//     search: ['admin'],
-//   }
-interface PermittedChannelsForEachCommand {
-  channelsObject: { [command: string]: string[] }
+interface PermissionSettingsInterface {
+  [commandName: string]: boolean | string[],
 }
 
 @Entity()
@@ -41,14 +35,11 @@ export class RelationMock {
   @Column()
   growiUri: string;
 
-  @Column('simple-array')
-  supportedCommandsForBroadcastUse: string[];
-
-  @Column('simple-array')
-  supportedCommandsForSingleUse: string[];
+  @Column({ type: 'json' })
+  permissionsForBroadcastUseCommands: PermissionSettingsInterface;
 
   @Column({ type: 'json' })
-  permittedChannelsForEachCommand : PermittedChannelsForEachCommand
+  permissionsForSingleUseCommands: PermissionSettingsInterface;
 
   @Column({ type: 'timestamp' })
   expiredAtCommands: Date;