Yuki Takei 4 лет назад
Родитель
Сommit
4719716cb9

+ 1 - 2
packages/slack/src/index.ts

@@ -12,8 +12,7 @@ export * from './interfaces/request-from-slack';
 export * from './models/errors';
 export * from './models/errors';
 export * from './middlewares/verify-slack-request';
 export * from './middlewares/verify-slack-request';
 export * from './utils/block-creater';
 export * from './utils/block-creater';
-export * from './utils/check-communicable-to-api-server';
+export * from './utils/check-communicable';
 export * from './utils/post-ephemeral-errors';
 export * from './utils/post-ephemeral-errors';
 export * from './utils/slash-command-parser';
 export * from './utils/slash-command-parser';
-export * from './utils/test-slack-api';
 export * from './utils/webclient-factory';
 export * from './utils/webclient-factory';

+ 4 - 0
packages/slack/src/interfaces/connection-status.ts

@@ -0,0 +1,4 @@
+export type ConnectionStatus = {
+  error?: Error,
+  workspaceName?: string,
+}

+ 0 - 16
packages/slack/src/utils/check-communicable-to-api-server.ts

@@ -1,16 +0,0 @@
-import axios, { AxiosError } from 'axios';
-
-/**
- * Check whether the HTML server responds or not.
- *
- * @param serverUri Server URI to connect
- * @returns AxiosError when error is occured
- */
-export const checkCommunicableToApiServer = async(serverUri = 'https://slack.com/api/'): Promise<void|AxiosError> => {
-  try {
-    await axios.get(serverUri, { maxRedirects: 0, timeout: 3000 });
-  }
-  catch (err) {
-    return err as AxiosError;
-  }
-};

+ 83 - 0
packages/slack/src/utils/check-communicable.ts

@@ -0,0 +1,83 @@
+import axios, { AxiosError } from 'axios';
+
+import { WebClient } from '@slack/web-api';
+
+import { generateWebClient } from './webclient-factory';
+import { ConnectionStatus } from '../interfaces/connection-status';
+
+/**
+ * Check whether the HTTP server responds or not.
+ *
+ * @param serverUri Server URI to connect
+ * @returns AxiosError when error is occured
+ */
+export const connectToHttpServer = async(serverUri: string): Promise<void|AxiosError> => {
+  try {
+    await axios.get(serverUri, { maxRedirects: 0, timeout: 3000 });
+  }
+  catch (err) {
+    return err as AxiosError;
+  }
+};
+
+/**
+ * Check whether the Slack API server responds or not.
+ *
+ * @returns AxiosError when error is occured
+ */
+export const connectToSlackApiServer = async(): Promise<void|AxiosError> => {
+  return connectToHttpServer('https://slack.com/api/');
+};
+
+/**
+ * Test Slack API
+ * @param client
+ */
+const testSlackApiServer = async(client: WebClient): Promise<void> => {
+  const result = await client.api.test();
+
+  if (!result.ok) {
+    throw new Error(result.error);
+  }
+};
+
+/**
+ * Retrieve Slack workspace name
+ * @param client
+ */
+const retrieveWorkspaceName = async(client: WebClient): Promise<string> => {
+  const result = await client.team.info();
+
+  if (!result.ok) {
+    throw new Error(result.error);
+  }
+
+  return (result as any).team?.name;
+};
+
+/**
+ * Get token string to ConnectionStatus map
+ * @param tokens Array of bot OAuth token
+ * @returns
+ */
+export const getConnectionStatuses = async(tokens: string[]): Promise<Map<string, ConnectionStatus>> => {
+  return tokens
+    .reduce<Promise<Map<string, ConnectionStatus>>>(async(acc, token) => {
+      const client = generateWebClient(token);
+
+      // try to connect
+      const status: ConnectionStatus = {};
+      try {
+        await testSlackApiServer(client);
+        status.workspaceName = await retrieveWorkspaceName(client);
+      }
+      catch (err) {
+        status.error = err;
+      }
+
+      (await acc).set(token, status);
+
+      return acc;
+
+    }, Promise.resolve(new Map<string, ConnectionStatus>()));
+};

+ 0 - 14
packages/slack/src/utils/test-slack-api.ts

@@ -1,14 +0,0 @@
-import { generateWebClient } from './webclient-factory';
-
-/**
- * Test Slack API with specified token
- * @param token Bot OAuth token
- */
-export const testSlackApiServer = async(token: string): Promise<void> => {
-  const client = generateWebClient(token);
-  const result = await client.api.test();
-
-  if (!result.ok) {
-    throw new Error(result.error);
-  }
-};

+ 32 - 26
src/server/routes/apiv3/slack-integration-settings.js

@@ -1,10 +1,11 @@
 const loggerFactory = require('@alias/logger');
 const loggerFactory = require('@alias/logger');
 
 
+const { getConnectionStatuses } = require('@growi/slack');
+
 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 crypto = require('crypto');
-const { WebClient, LogLevel } = require('@slack/web-api');
 const ErrorV3 = require('../../models/vo/error-apiv3');
 const ErrorV3 = require('../../models/vo/error-apiv3');
 
 
 const router = express.Router();
 const router = express.Router();
@@ -84,35 +85,40 @@ module.exports = (crowi) => {
    *        tags: [SlackBotSettingParams]
    *        tags: [SlackBotSettingParams]
    *        operationId: getSlackBotSettingParams
    *        operationId: getSlackBotSettingParams
    *        summary: get /slack-integration
    *        summary: get /slack-integration
-   *        description: Get slackBot setting params.
+   *        description: Get current settings and connection statuses.
    *        responses:
    *        responses:
    *          200:
    *          200:
-   *            description: Succeeded to get slackBot setting params.
+   *            description: Succeeded to get info.
    */
    */
   router.get('/', accessTokenParser, loginRequiredStrictly, adminRequired, async(req, res) => {
   router.get('/', accessTokenParser, loginRequiredStrictly, adminRequired, async(req, res) => {
-    const slackBotSettingParams = {
-      accessToken: crowi.configManager.getConfig('crowi', 'slackbot:access-token'),
-      currentBotType: crowi.configManager.getConfig('crowi', 'slackbot:currentBotType'),
-      // TODO impl when creating official bot
-      officialBotSettings: {
-        // TODO impl this after GW-4939
-        // AccessToken: "tempaccessdatahogehoge",
-      },
-      customBotWithoutProxySettings: {
-        // TODO impl this after GW-4939
-        // AccessToken: "tempaccessdatahogehoge",
-        slackSigningSecretEnvVars: crowi.configManager.getConfigFromEnvVars('crowi', 'slackbot:signingSecret'),
-        slackBotTokenEnvVars: crowi.configManager.getConfigFromEnvVars('crowi', 'slackbot:token'),
-        slackSigningSecret: crowi.configManager.getConfig('crowi', 'slackbot:signingSecret'),
-        slackBotToken: crowi.configManager.getConfig('crowi', 'slackbot:token'),
-      },
-      // TODO imple when creating with proxy
-      customBotWithProxySettings: {
-        // TODO impl this after GW-4939
-        // AccessToken: "tempaccessdatahogehoge",
-      },
-    };
-    return res.apiv3({ slackBotSettingParams });
+    const { configManager } = crowi;
+    const currentBotType = configManager.getConfig('crowi', 'slackbot:currentBotType');
+
+    // retrieve settings
+    const settings = {};
+    if (currentBotType === 'customBotWithoutProxy') {
+      settings.slackSigningSecretEnvVars = configManager.getConfigFromEnvVars('crowi', 'slackbot:signingSecret');
+      settings.slackBotTokenEnvVars = configManager.getConfigFromEnvVars('crowi', 'slackbot:token');
+      settings.slackSigningSecret = configManager.getConfig('crowi', 'slackbot:signingSecret');
+      settings.slackBotToken = configManager.getConfig('crowi', 'slackbot:token');
+    }
+    else {
+      // settings.proxyUriEnvVars = ;
+      // settings.proxyUri = ;
+      // settings.tokenPtoG = ;
+      // settings.tokenGtoP = ;
+    }
+
+    // retrieve connection statuses
+    let connectionStatuses;
+    if (currentBotType === 'customBotWithoutProxy') {
+      connectionStatuses = Object.fromEntries(await getConnectionStatuses([settings.slackBotToken]));
+    }
+    else {
+      // connectionStatuses = getConnectionStatusesFromProxy();
+    }
+
+    return res.apiv3({ currentBotType, settings, connectionStatuses });
   });
   });
 
 
   /**
   /**