Răsfoiți Sursa

Merge pull request #3564 from weseek/feat/4937-5495-implement-access-token-without-user

Feat/4937 5495 implement access token without user
Yuki Takei 5 ani în urmă
părinte
comite
a13b135fdf

+ 24 - 3
src/server/routes/apiv3/slack-bot.js

@@ -1,6 +1,10 @@
 
 
 const express = require('express');
 const express = require('express');
 
 
+const loggerFactory = require('@alias/logger');
+
+const logger = loggerFactory('growi:routes:apiv3:slack-bot');
+
 const router = express.Router();
 const router = express.Router();
 
 
 module.exports = (crowi) => {
 module.exports = (crowi) => {
@@ -8,13 +12,30 @@ module.exports = (crowi) => {
   const { boltService } = crowi;
   const { boltService } = crowi;
   const requestHandler = boltService.receiver.requestHandler.bind(boltService.receiver);
   const requestHandler = boltService.receiver.requestHandler.bind(boltService.receiver);
 
 
-  router.post('/', async(req, res) => {
+
+  // Check if the access token is correct
+  function verificationAccessToken(req, res, next) {
+    const slackBotAccessToken = req.body.slack_bot_access_token || null;
+
+    if (slackBotAccessToken == null || slackBotAccessToken !== this.crowi.configManager.getConfig('crowi', 'slackbot:access-token')) {
+      logger.error('slack_bot_access_token is invalid.');
+      return res.send('*Access token is inValid*');
+    }
+
+    return next();
+  }
+
+  function verificationRequestUrl(req, res, next) {
     // for verification request URL on Event Subscriptions
     // for verification request URL on Event Subscriptions
     if (req.body.type === 'url_verification') {
     if (req.body.type === 'url_verification') {
-      res.send(req.body);
-      return;
+      return res.send(req.body);
     }
     }
 
 
+    return next();
+  }
+
+  router.post('/', verificationRequestUrl, verificationAccessToken, async(req, res) => {
+
     // Send response immediately to avoid opelation_timeout error
     // Send response immediately to avoid opelation_timeout error
     // See https://api.slack.com/apis/connections/events-api#the-events-api__responding-to-events
     // See https://api.slack.com/apis/connections/events-api#the-events-api__responding-to-events
     res.send();
     res.send();

+ 37 - 0
src/server/routes/apiv3/slack-integration.js

@@ -3,6 +3,7 @@ const loggerFactory = require('@alias/logger');
 const logger = loggerFactory('growi:routes:apiv3:notification-setting');
 const logger = loggerFactory('growi:routes:apiv3:notification-setting');
 const express = require('express');
 const express = require('express');
 const { body } = require('express-validator');
 const { body } = require('express-validator');
+const crypto = require('crypto');
 const ErrorV3 = require('../../models/vo/error-apiv3');
 const ErrorV3 = require('../../models/vo/error-apiv3');
 
 
 const router = express.Router();
 const router = express.Router();
@@ -53,6 +54,14 @@ module.exports = (crowi) => {
     return configManager.updateConfigsInTheSameNamespace('crowi', params, true);
     return configManager.updateConfigsInTheSameNamespace('crowi', params, true);
   }
   }
 
 
+
+  function generateAccessToken(user) {
+    const hasher = crypto.createHash('sha512');
+    hasher.update(new Date().getTime() + user._id);
+
+    return hasher.digest('base64');
+  }
+
   /**
   /**
    * @swagger
    * @swagger
    *
    *
@@ -138,5 +147,33 @@ module.exports = (crowi) => {
       }
       }
     });
     });
 
 
+  /**
+   * @swagger
+   *
+   *    /slack-integration/access-token:
+   *      put:
+   *        tags: [SlackIntegration]
+   *        operationId: getCustomBotSetting
+   *        summary: /slack-integration
+   *        description: Generate accessToken
+   *        responses:
+   *          200:
+   *            description: Succeeded to update access token for slack
+   */
+  router.put('/access-token', loginRequiredStrictly, adminRequired, async(req, res) => {
+
+    try {
+      const accessToken = generateAccessToken(req.user);
+      await updateSlackBotSettings({ 'slackbot:access-token': accessToken });
+
+      return res.apiv3({ accessToken });
+    }
+    catch (error) {
+      const msg = 'Error occured in updating access token for access token';
+      logger.error('Error', error);
+      return res.apiv3Err(new ErrorV3(msg, 'update-accessToken-failed'));
+    }
+  });
+
   return router;
   return router;
 };
 };

+ 4 - 20
src/server/service/bolt.js

@@ -1,4 +1,5 @@
 const logger = require('@alias/logger')('growi:service:BoltService');
 const logger = require('@alias/logger')('growi:service:BoltService');
+const mongoose = require('mongoose');
 
 
 const PAGINGLIMIT = 10;
 const PAGINGLIMIT = 10;
 
 
@@ -293,20 +294,6 @@ class BoltService {
   }
   }
 
 
   async createModal(command, client, body) {
   async createModal(command, client, body) {
-    const User = this.crowi.model('User');
-    const slackUser = await User.findUserByUsername('slackUser');
-
-    // if "slackUser" is null, don't show create Modal
-    if (slackUser == null) {
-      logger.error('Failed to create a page because slackUser is not found.');
-      this.client.chat.postEphemeral({
-        channel: command.channel_id,
-        user: command.user_id,
-        blocks: [this.generateMarkdownSectionBlock('*slackUser does not exist.*')],
-      });
-      throw new Error('/growi command:create: slackUser is not found');
-    }
-
     try {
     try {
       await client.views.open({
       await client.views.open({
         trigger_id: body.trigger_id,
         trigger_id: body.trigger_id,
@@ -349,23 +336,20 @@ class BoltService {
 
 
   // Submit action in create Modal
   // Submit action in create Modal
   async createPageInGrowi(view, body) {
   async createPageInGrowi(view, body) {
-    const User = this.crowi.model('User');
     const Page = this.crowi.model('Page');
     const Page = this.crowi.model('Page');
     const pathUtils = require('growi-commons').pathUtils;
     const pathUtils = require('growi-commons').pathUtils;
 
 
     const contentsBody = view.state.values.contents.contents_input.value;
     const contentsBody = view.state.values.contents.contents_input.value;
 
 
     try {
     try {
-      // search "slackUser" to create page in slack
-      const slackUser = await User.findUserByUsername('slackUser');
-
       let path = view.state.values.path.path_input.value;
       let path = view.state.values.path.path_input.value;
       // sanitize path
       // sanitize path
       path = this.crowi.xss.process(path);
       path = this.crowi.xss.process(path);
       path = pathUtils.normalizePath(path);
       path = pathUtils.normalizePath(path);
 
 
-      const user = slackUser._id;
-      await Page.create(path, contentsBody, user, {});
+      // generate a dummy id because Operation to create a page needs ObjectId
+      const dummyObjectIdOfUser = new mongoose.Types.ObjectId();
+      await Page.create(path, contentsBody, dummyObjectIdOfUser, {});
     }
     }
     catch (err) {
     catch (err) {
       this.client.chat.postMessage({
       this.client.chat.postMessage({