Просмотр исходного кода

Merge pull request #3777 from weseek/imprv/switch-display-by-passing-test

Imprv/switch display by passing test
Sizma yosimaz 4 лет назад
Родитель
Сommit
cee3836c74

+ 24 - 3
packages/slack/src/utils/check-communicable.ts

@@ -33,12 +33,24 @@ export const connectToSlackApiServer = async(): Promise<void|AxiosError> => {
  * Test Slack API
  * Test Slack API
  * @param client
  * @param client
  */
  */
-const testSlackApiServer = async(client: WebClient): Promise<void> => {
+const testSlackApiServer = async(client: WebClient): Promise<any> => {
   const result = await client.api.test();
   const result = await client.api.test();
 
 
   if (!result.ok) {
   if (!result.ok) {
     throw new Error(result.error);
     throw new Error(result.error);
   }
   }
+
+  return result;
+};
+
+const checkSlackScopes = (resultTestSlackApiServer: any) => {
+  const slackScopes = resultTestSlackApiServer.response_metadata.scopes;
+  const correctScopes = ['commands', 'team:read', 'chat:write'];
+  const isPassedScopeCheck = correctScopes.every(e => slackScopes.includes(e));
+
+  if (!isPassedScopeCheck) {
+    throw new Error('The scopes is not appropriate. Required scopes is [\'commands\', \'team:read\', \'chat:write\']');
+  }
 };
 };
 
 
 /**
 /**
@@ -94,7 +106,16 @@ export const getConnectionStatuses = async(tokens: string[]): Promise<{[key: str
  * @param token bot OAuth token
  * @param token bot OAuth token
  * @returns
  * @returns
  */
  */
-export const relationTestToSlack = async(token:string): Promise<void> => {
+export const testToSlack = async(token:string): Promise<void> => {
+  const client = generateWebClient(token);
+  const res = await testSlackApiServer(client);
+  await checkSlackScopes(res);
+};
+
+export const sendSuccessMessage = async(token:string, channel:string, appSiteUrl:string): Promise<void> => {
   const client = generateWebClient(token);
   const client = generateWebClient(token);
-  await testSlackApiServer(client);
+  await client.chat.postMessage({
+    channel,
+    text: `Successfully tested with ${appSiteUrl}.`,
+  });
 };
 };

+ 16 - 3
packages/slackbot-proxy/src/controllers/growi-to-slack.ts

@@ -6,7 +6,7 @@ import axios from 'axios';
 import { WebAPICallResult } from '@slack/web-api';
 import { WebAPICallResult } from '@slack/web-api';
 
 
 import {
 import {
-  verifyGrowiToSlackRequest, getConnectionStatuses, relationTestToSlack, generateWebClient,
+  verifyGrowiToSlackRequest, getConnectionStatuses, testToSlack, generateWebClient,
 } from '@growi/slack';
 } from '@growi/slack';
 
 
 import { GrowiReq } from '~/interfaces/growi-to-slack/growi-req';
 import { GrowiReq } from '~/interfaces/growi-to-slack/growi-req';
@@ -107,7 +107,14 @@ export class GrowiToSlackCtrl {
         return res.status(400).send({ message: `failed to request to GROWI. err: ${err.message}` });
         return res.status(400).send({ message: `failed to request to GROWI. err: ${err.message}` });
       }
       }
 
 
-      await relationTestToSlack(token);
+      try {
+        await testToSlack(token);
+      }
+      catch (err) {
+        logger.error(err);
+        return res.status(400).send({ message: `failed to test. err: ${err.message}` });
+      }
+
       return res.send({ relation });
       return res.send({ relation });
     }
     }
 
 
@@ -138,7 +145,13 @@ export class GrowiToSlackCtrl {
       return res.status(400).send({ message: 'installation is invalid' });
       return res.status(400).send({ message: 'installation is invalid' });
     }
     }
 
 
-    await relationTestToSlack(token);
+    try {
+      await testToSlack(token);
+    }
+    catch (err) {
+      logger.error(err);
+      return res.status(400).send({ message: `failed to test. err: ${err.message}` });
+    }
 
 
     logger.debug('relation test is success', order);
     logger.debug('relation test is success', order);
 
 

+ 58 - 40
src/client/js/components/Admin/SlackIntegration/CustomBotWithoutProxyIntegrationCard.jsx

@@ -4,16 +4,70 @@ import PropTypes from 'prop-types';
 
 
 import { UncontrolledTooltip } from 'reactstrap';
 import { UncontrolledTooltip } from 'reactstrap';
 
 
-const CustomBotWithoutProxyIntegrationCard = (props) => {
+const IntegrationSuccess = () => {
+  const { t } = useTranslation();
+
+  return (
+    <>
+      <div className="d-none d-lg-block">
+        <p className="text-success small mt-5">
+          <i className="fa fa-check mr-1" />
+          {t('admin:slack_integration.integration_sentence.integration_successful')}
+        </p>
+        <hr className="align-self-center admin-border-success border-success"></hr>
+      </div>
+      <div id="integration-line-for-tooltip" className="d-block d-lg-none mt-5">
+        <i className="fa fa-check mr-1 text-success" />
+        <hr className="align-self-center admin-border-success border-success"></hr>
+      </div>
+      <UncontrolledTooltip placement="top" fade={false} target="integration-line-for-tooltip">
+        <small>
+          {t('admin:slack_integration.integration_sentence.integration_successful')}
+        </small>
+      </UncontrolledTooltip>
+    </>
+  );
+};
 
 
+const IntegrationFailed = () => {
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
+  return (
+    <>
+      <div className="d-none d-lg-block">
+        <p className="mt-4">
+          <small
+            className="text-danger m-0"
+          // eslint-disable-next-line react/no-danger
+            dangerouslySetInnerHTML={{ __html: t('admin:slack_integration.integration_sentence.integration_is_not_complete') }}
+          />
+        </p>
+        <hr className="align-self-center admin-border-danger border-danger"></hr>
+
+      </div>
+      <div id="integration-line-for-tooltip" className="d-block d-lg-none mt-5">
+        <i className="icon-info text-danger" />
+        <hr className="align-self-center admin-border-danger border-danger"></hr>
+      </div>
+      <UncontrolledTooltip placement="top" fade={false} target="integration-line-for-tooltip">
+        <small
+          className="m-0"
+        // eslint-disable-next-line react/no-danger
+          dangerouslySetInnerHTML={{ __html: t('admin:slack_integration.integration_sentence.integration_is_not_complete') }}
+        />
+      </UncontrolledTooltip>
+    </>
+  );
+};
+
+const CustomBotWithoutProxyIntegrationCard = (props) => {
+
   return (
   return (
     <div className="d-flex justify-content-center my-5 bot-integration">
     <div className="d-flex justify-content-center my-5 bot-integration">
       <div className="card rounded shadow border-0 w-50 admin-bot-card mb-0">
       <div className="card rounded shadow border-0 w-50 admin-bot-card mb-0">
         <h5 className="card-title font-weight-bold mt-3 ml-4">Slack</h5>
         <h5 className="card-title font-weight-bold mt-3 ml-4">Slack</h5>
         <div className="card-body p-2 w-50 mx-auto">
         <div className="card-body p-2 w-50 mx-auto">
-          {props.slackWSNameInWithoutProxy != null && (
+          {props.isIntegrationSuccess && props.slackWSNameInWithoutProxy != null && (
             <div className="card slack-work-space-name-card">
             <div className="card slack-work-space-name-card">
               <div className="m-2 text-center">
               <div className="m-2 text-center">
                 <h5 className="font-weight-bold">{props.slackWSNameInWithoutProxy}</h5>
                 <h5 className="font-weight-bold">{props.slackWSNameInWithoutProxy}</h5>
@@ -25,32 +79,7 @@ const CustomBotWithoutProxyIntegrationCard = (props) => {
       </div>
       </div>
 
 
       <div className="text-center w-25">
       <div className="text-center w-25">
-
-        <div className="d-none d-lg-block">
-          {/* TODO GW-5998 switching logic */}
-          {/* <p className="text-success small mt-5">
-            <i className="fa fa-check mr-1" />
-            {t('admin:slack_integration.integration_sentence.integration_successful')}
-          </p> */}
-
-          <p className="mt-4">
-            <small
-              className="text-danger m-0"
-              // eslint-disable-next-line react/no-danger
-              dangerouslySetInnerHTML={{ __html: t('admin:slack_integration.integration_sentence.integration_is_not_complete') }}
-            />
-          </p>
-        </div>
-
-        {/* TODO GW-5998  */}
-        <div id="integration-line-for-tooltip" className="d-block d-lg-none mt-5">
-          {/* <i className="fa fa-check mr-1 text-success" /> */}
-          <i className="icon-info text-danger" />
-        </div>
-
-        {/* TODO GW-5998 */}
-        {/* <hr className="align-self-center admin-border-success border-success"></hr> */}
-        <hr className="align-self-center admin-border-danger border-danger"></hr>
+        {props.isIntegrationSuccess ? <IntegrationSuccess /> : <IntegrationFailed />}
       </div>
       </div>
 
 
       <div className="card rounded-lg shadow border-0 w-50 admin-bot-card mb-0">
       <div className="card rounded-lg shadow border-0 w-50 admin-bot-card mb-0">
@@ -59,18 +88,6 @@ const CustomBotWithoutProxyIntegrationCard = (props) => {
           <div className="btn btn-primary">{ props.siteName }</div>
           <div className="btn btn-primary">{ props.siteName }</div>
         </div>
         </div>
       </div>
       </div>
-
-      <UncontrolledTooltip placement="top" fade={false} target="integration-line-for-tooltip">
-        {/* TODO GW-5998 */}
-        {/* <small>
-          {t('admin:slack_integration.integration_sentence.integration_successful')}
-        </small> */}
-        <small
-          className="m-0"
-          // eslint-disable-next-line react/no-danger
-          dangerouslySetInnerHTML={{ __html: t('admin:slack_integration.integration_sentence.integration_is_not_complete') }}
-        />
-      </UncontrolledTooltip>
     </div>
     </div>
   );
   );
 };
 };
@@ -78,6 +95,7 @@ const CustomBotWithoutProxyIntegrationCard = (props) => {
 CustomBotWithoutProxyIntegrationCard.propTypes = {
 CustomBotWithoutProxyIntegrationCard.propTypes = {
   siteName: PropTypes.string.isRequired,
   siteName: PropTypes.string.isRequired,
   slackWSNameInWithoutProxy: PropTypes.string,
   slackWSNameInWithoutProxy: PropTypes.string,
+  isIntegrationSuccess: PropTypes.bool,
 };
 };
 
 
 export default CustomBotWithoutProxyIntegrationCard;
 export default CustomBotWithoutProxyIntegrationCard;

+ 32 - 0
src/client/js/components/Admin/SlackIntegration/CustomBotWithoutProxySettings.jsx

@@ -14,6 +14,10 @@ const CustomBotWithoutProxySettings = (props) => {
 
 
   const [siteName, setSiteName] = useState('');
   const [siteName, setSiteName] = useState('');
   const [isDeleteConfirmModalShown, setIsDeleteConfirmModalShown] = useState(false);
   const [isDeleteConfirmModalShown, setIsDeleteConfirmModalShown] = useState(false);
+  const [isIntegrationSuccess, setIsIntegrationSuccess] = useState(false);
+  const [connectionMessage, setConnectionMessage] = useState('');
+  const [connectionErrorCode, setConnectionErrorCode] = useState(null);
+  const [testChannel, setTestChannel] = useState('');
 
 
   const resetSettings = async() => {
   const resetSettings = async() => {
     if (onResetSettings == null) {
     if (onResetSettings == null) {
@@ -22,6 +26,25 @@ const CustomBotWithoutProxySettings = (props) => {
     onResetSettings();
     onResetSettings();
   };
   };
 
 
+  const testConnection = async() => {
+    setConnectionErrorCode(null);
+    setConnectionMessage(null);
+    try {
+      await appContainer.apiv3.post('/slack-integration-settings/without-proxy/test', { channel: testChannel });
+      setConnectionMessage('Send the message to slack work space.');
+      setIsIntegrationSuccess(true);
+    }
+    catch (err) {
+      setConnectionErrorCode(err[0].code);
+      setConnectionMessage(err[0].message);
+      setIsIntegrationSuccess(false);
+    }
+  };
+
+  const inputTestChannelHandler = (channel) => {
+    setTestChannel(channel);
+  };
+
   useEffect(() => {
   useEffect(() => {
     const siteName = appContainer.config.crowi.title;
     const siteName = appContainer.config.crowi.title;
     setSiteName(siteName);
     setSiteName(siteName);
@@ -34,6 +57,7 @@ const CustomBotWithoutProxySettings = (props) => {
       <CustomBotWithoutProxyIntegrationCard
       <CustomBotWithoutProxyIntegrationCard
         siteName={siteName}
         siteName={siteName}
         slackWSNameInWithoutProxy={props.slackWSNameInWithoutProxy}
         slackWSNameInWithoutProxy={props.slackWSNameInWithoutProxy}
+        isIntegrationSuccess={isIntegrationSuccess}
       />
       />
 
 
       <h2 className="admin-setting-header">{t('admin:slack_integration.integration_procedure')}</h2>
       <h2 className="admin-setting-header">{t('admin:slack_integration.integration_procedure')}</h2>
@@ -51,6 +75,13 @@ const CustomBotWithoutProxySettings = (props) => {
         <CustomBotWithoutProxySettingsAccordion
         <CustomBotWithoutProxySettingsAccordion
           {...props}
           {...props}
           activeStep={botInstallationStep.CREATE_BOT}
           activeStep={botInstallationStep.CREATE_BOT}
+          connectionMessage={connectionMessage}
+          connectionErrorCode={connectionErrorCode}
+          isIntegrationSuccess={isIntegrationSuccess}
+          testChannel={testChannel}
+          onTestFormSubmitted={testConnection}
+          inputTestChannelHandler={inputTestChannelHandler}
+
         />
         />
       </div>
       </div>
       <DeleteSlackBotSettingsModal
       <DeleteSlackBotSettingsModal
@@ -73,6 +104,7 @@ CustomBotWithoutProxySettings.propTypes = {
   slackBotToken: PropTypes.string,
   slackBotToken: PropTypes.string,
   slackBotTokenEnv: PropTypes.string,
   slackBotTokenEnv: PropTypes.string,
   isRgisterSlackCredentials: PropTypes.bool,
   isRgisterSlackCredentials: PropTypes.bool,
+  isIntegrationSuccess: PropTypes.bool,
   slackWSNameInWithoutProxy: PropTypes.string,
   slackWSNameInWithoutProxy: PropTypes.string,
   onResetSettings: PropTypes.func,
   onResetSettings: PropTypes.func,
 };
 };

+ 31 - 47
src/client/js/components/Admin/SlackIntegration/CustomBotWithoutProxySettingsAccordion.jsx

@@ -16,19 +16,15 @@ export const botInstallationStep = {
 };
 };
 
 
 const CustomBotWithoutProxySettingsAccordion = ({
 const CustomBotWithoutProxySettingsAccordion = ({
-  appContainer, activeStep, fetchSlackIntegrationData,
-  slackSigningSecret, slackSigningSecretEnv, slackBotToken, slackBotTokenEnv,
-  isRegisterSlackCredentials, isSendTestMessage,
-  onSetSlackSigningSecret, onSetSlackBotToken, onSetIsSendTestMessage,
+  appContainer, activeStep,
+  connectionMessage, connectionErrorCode, testChannel, slackSigningSecret, slackSigningSecretEnv, slackBotToken, slackBotTokenEnv,
+  isRegisterSlackCredentials, isIntegrationSuccess,
+  fetchSlackIntegrationData, inputTestChannelHandler, onTestFormSubmitted, onSetSlackSigningSecret, onSetSlackBotToken,
 }) => {
 }) => {
   const { t } = useTranslation();
   const { t } = useTranslation();
   // TODO: GW-5644 Store default open accordion
   // TODO: GW-5644 Store default open accordion
   // eslint-disable-next-line no-unused-vars
   // eslint-disable-next-line no-unused-vars
   const [defaultOpenAccordionKeys, setDefaultOpenAccordionKeys] = useState(new Set([activeStep]));
   const [defaultOpenAccordionKeys, setDefaultOpenAccordionKeys] = useState(new Set([activeStep]));
-  const [connectionErrorCode, setConnectionErrorCode] = useState(null);
-  const [connectionErrorMessage, setConnectionErrorMessage] = useState(null);
-  const [connectionSuccessMessage, setConnectionSuccessMessage] = useState(null);
-  const [testChannel, setTestChannel] = useState('');
   const currentBotType = 'customBotWithoutProxy';
   const currentBotType = 'customBotWithoutProxy';
 
 
 
 
@@ -63,42 +59,22 @@ const CustomBotWithoutProxySettingsAccordion = ({
     }
     }
   };
   };
 
 
-  const testConnection = async() => {
-    setConnectionErrorCode(null);
-    setConnectionErrorMessage(null);
-    setConnectionSuccessMessage(null);
-    // TODO: 5921 Add new Test endpoint
-    try {
-      // eslint-disable-next-line no-console
-      console.log('Test');
-      // const res = await appContainer.apiv3.post('/slack-integration-settings//without-proxy/test', {
-      //   channel: testChannel,
-      // });
-      // setConnectionSuccessMessage(res.data.message);
-      // onSetIsSendTestMessage(true);
-    }
-    catch (err) {
-      onSetIsSendTestMessage(false);
-      setConnectionErrorCode('dummy-error-code');
-      setConnectionErrorMessage('This is a sample error message');
-    }
-  };
-
   const submitForm = (e) => {
   const submitForm = (e) => {
     e.preventDefault();
     e.preventDefault();
-    testConnection();
-  };
 
 
-  const inputTestChannelHandler = (channel) => {
-    setTestChannel(channel);
+    if (onTestFormSubmitted == null) {
+      return;
+    }
+    onTestFormSubmitted();
   };
   };
 
 
+
   let value = '';
   let value = '';
-  if (connectionErrorMessage != null) {
-    value = [connectionErrorCode, connectionErrorMessage];
+  if (connectionMessage === 'Send the message to slack work space.' || connectionMessage === '') {
+    value = connectionMessage;
   }
   }
-  if (connectionSuccessMessage != null) {
-    value = connectionSuccessMessage;
+  else {
+    value = [connectionErrorCode, connectionMessage];
   }
   }
 
 
   return (
   return (
@@ -159,7 +135,7 @@ const CustomBotWithoutProxySettingsAccordion = ({
       <Accordion
       <Accordion
         defaultIsActive={defaultOpenAccordionKeys.has(botInstallationStep.CONNECTION_TEST)}
         defaultIsActive={defaultOpenAccordionKeys.has(botInstallationStep.CONNECTION_TEST)}
         // eslint-disable-next-line max-len
         // eslint-disable-next-line max-len
-        title={<><span className="mr-2">④</span>{t('admin:slack_integration.accordion.test_connection')}{isSendTestMessage && <i className="ml-3 text-success fa fa-check"></i>}</>}
+        title={<><span className="mr-2">④</span>{t('admin:slack_integration.accordion.test_connection')}{isIntegrationSuccess && <i className="ml-3 text-success fa fa-check"></i>}</>}
       >
       >
         <p className="text-center m-4">{t('admin:slack_integration.accordion.test_connection_by_pressing_button')}</p>
         <p className="text-center m-4">{t('admin:slack_integration.accordion.test_connection_by_pressing_button')}</p>
         <div className="d-flex justify-content-center">
         <div className="d-flex justify-content-center">
@@ -184,10 +160,17 @@ const CustomBotWithoutProxySettingsAccordion = ({
             </button>
             </button>
           </form>
           </form>
         </div>
         </div>
-        {connectionErrorMessage != null
-          && <p className="text-danger text-center my-4">{t('admin:slack_integration.accordion.error_check_logs_below')}</p>}
-        {connectionSuccessMessage != null
-          && <p className="text-info text-center my-4">{t('admin:slack_integration.accordion.send_message_to_slack_work_space')}</p>}
+        {connectionMessage === ''
+          ? <p></p>
+          : (
+            <>
+              {connectionMessage === 'Send the message to slack work space.'
+                ? <p className="text-info text-center my-4">{t('admin:slack_integration.accordion.send_message_to_slack_work_space')}</p>
+                : <p className="text-danger text-center my-4">{t('admin:slack_integration.accordion.error_check_logs_below')}</p>
+              }
+            </>
+          )
+        }
         <form>
         <form>
           <div className="row my-3 justify-content-center">
           <div className="row my-3 justify-content-center">
             <div className="form-group slack-connection-log col-md-4">
             <div className="form-group slack-connection-log col-md-4">
@@ -214,15 +197,16 @@ CustomBotWithoutProxySettingsAccordion.propTypes = {
   slackSigningSecretEnv: PropTypes.string,
   slackSigningSecretEnv: PropTypes.string,
   slackBotToken: PropTypes.string,
   slackBotToken: PropTypes.string,
   slackBotTokenEnv: PropTypes.string,
   slackBotTokenEnv: PropTypes.string,
+  testChannel: PropTypes.string,
   isRegisterSlackCredentials: PropTypes.bool,
   isRegisterSlackCredentials: PropTypes.bool,
-  isSendTestMessage: PropTypes.bool,
+  isIntegrationSuccess: PropTypes.bool,
   fetchSlackIntegrationData: PropTypes.func,
   fetchSlackIntegrationData: PropTypes.func,
+  inputTestChannelHandler: PropTypes.func,
+  onTestFormSubmitted: PropTypes.func,
   onSetSlackSigningSecret: PropTypes.func,
   onSetSlackSigningSecret: PropTypes.func,
   onSetSlackBotToken: PropTypes.func,
   onSetSlackBotToken: PropTypes.func,
-  onSetIsSendTestMessage: PropTypes.func,
-  onSetIsRegisterSlackCredentials: PropTypes.func,
-  setSlackWSNameInWithoutProxy: PropTypes.func,
-
+  connectionMessage: PropTypes.string,
+  connectionErrorCode: PropTypes.string,
   adminAppContainer: PropTypes.instanceOf(AdminAppContainer).isRequired,
   adminAppContainer: PropTypes.instanceOf(AdminAppContainer).isRequired,
   activeStep: PropTypes.oneOf(Object.values(botInstallationStep)).isRequired,
   activeStep: PropTypes.oneOf(Object.values(botInstallationStep)).isRequired,
 };
 };

+ 0 - 4
src/client/js/components/Admin/SlackIntegration/SlackIntegration.jsx

@@ -24,7 +24,6 @@ const SlackIntegration = (props) => {
   const [slackSigningSecretEnv, setSlackSigningSecretEnv] = useState('');
   const [slackSigningSecretEnv, setSlackSigningSecretEnv] = useState('');
   const [slackBotTokenEnv, setSlackBotTokenEnv] = useState('');
   const [slackBotTokenEnv, setSlackBotTokenEnv] = useState('');
   const [isRegisterSlackCredentials, setIsRegisterSlackCredentials] = useState(false);
   const [isRegisterSlackCredentials, setIsRegisterSlackCredentials] = useState(false);
-  const [isSendTestMessage, setIsSendTestMessage] = useState(false);
   const [slackWSNameInWithoutProxy, setSlackWSNameInWithoutProxy] = useState(null);
   const [slackWSNameInWithoutProxy, setSlackWSNameInWithoutProxy] = useState(null);
   const [isDeleteConfirmModalShown, setIsDeleteConfirmModalShown] = useState(false);
   const [isDeleteConfirmModalShown, setIsDeleteConfirmModalShown] = useState(false);
   const [slackAppIntegrations, setSlackAppIntegrations] = useState();
   const [slackAppIntegrations, setSlackAppIntegrations] = useState();
@@ -93,7 +92,6 @@ const SlackIntegration = (props) => {
       setIsRegisterSlackCredentials(false);
       setIsRegisterSlackCredentials(false);
       setSlackSigningSecret(null);
       setSlackSigningSecret(null);
       setSlackBotToken(null);
       setSlackBotToken(null);
-      setIsSendTestMessage(false);
       setSlackWSNameInWithoutProxy(null);
       setSlackWSNameInWithoutProxy(null);
     }
     }
     catch (err) {
     catch (err) {
@@ -129,7 +127,6 @@ const SlackIntegration = (props) => {
     case 'customBotWithoutProxy':
     case 'customBotWithoutProxy':
       settingsComponent = (
       settingsComponent = (
         <CustomBotWithoutProxySettings
         <CustomBotWithoutProxySettings
-          isSendTestMessage={isSendTestMessage}
           isRegisterSlackCredentials={isRegisterSlackCredentials}
           isRegisterSlackCredentials={isRegisterSlackCredentials}
           slackBotTokenEnv={slackBotTokenEnv}
           slackBotTokenEnv={slackBotTokenEnv}
           slackBotToken={slackBotToken}
           slackBotToken={slackBotToken}
@@ -138,7 +135,6 @@ const SlackIntegration = (props) => {
           slackWSNameInWithoutProxy={slackWSNameInWithoutProxy}
           slackWSNameInWithoutProxy={slackWSNameInWithoutProxy}
           onSetSlackSigningSecret={setSlackSigningSecret}
           onSetSlackSigningSecret={setSlackSigningSecret}
           onSetSlackBotToken={setSlackBotToken}
           onSetSlackBotToken={setSlackBotToken}
-          onSetIsSendTestMessage={setIsSendTestMessage}
           onResetSettings={resetWithOutSettings}
           onResetSettings={resetWithOutSettings}
           fetchSlackIntegrationData={fetchSlackIntegrationData}
           fetchSlackIntegrationData={fetchSlackIntegrationData}
         />
         />

+ 14 - 5
src/server/routes/apiv3/slack-integration-settings.js

@@ -5,7 +5,7 @@ const axios = require('axios');
 const urljoin = require('url-join');
 const urljoin = require('url-join');
 const loggerFactory = require('@alias/logger');
 const loggerFactory = require('@alias/logger');
 
 
-const { getConnectionStatuses, relationTestToSlack } = require('@growi/slack');
+const { getConnectionStatuses, testToSlack, sendSuccessMessage } = require('@growi/slack');
 
 
 const ErrorV3 = require('../../models/vo/error-apiv3');
 const ErrorV3 = require('../../models/vo/error-apiv3');
 
 
@@ -510,17 +510,26 @@ module.exports = (crowi) => {
       const msg = 'Select Without Proxy Type';
       const msg = 'Select Without Proxy Type';
       return res.apiv3Err(new ErrorV3(msg, 'select-not-proxy-type'), 400);
       return res.apiv3Err(new ErrorV3(msg, 'select-not-proxy-type'), 400);
     }
     }
-    // TODO impl req.body at GW-5998
-    // const { channel } = req.body;
+
     const slackBotToken = crowi.configManager.getConfig('crowi', 'slackbot:token');
     const slackBotToken = crowi.configManager.getConfig('crowi', 'slackbot:token');
     try {
     try {
-      await relationTestToSlack(slackBotToken);
-      // TODO impl return response after imple 5996, 6002
+      await testToSlack(slackBotToken);
     }
     }
     catch (error) {
     catch (error) {
       logger.error('Error', error);
       logger.error('Error', error);
       return res.apiv3Err(new ErrorV3(`Error occured while testing. Cause: ${error.message}`, 'test-failed', error.stack));
       return res.apiv3Err(new ErrorV3(`Error occured while testing. Cause: ${error.message}`, 'test-failed', error.stack));
     }
     }
+
+    const { channel } = req.body;
+    const appSiteURL = crowi.configManager.getConfig('crowi', 'app:siteUrl');
+    try {
+      await sendSuccessMessage(slackBotToken, channel, appSiteURL);
+    }
+    catch (error) {
+      return res.apiv3Err(new ErrorV3(`Error occured while sending message. Cause: ${error.message}`, 'send-message-failed', error.stack));
+    }
+
+    return res.apiv3();
   });
   });
 
 
   return router;
   return router;