slack-integration-settings.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  1. import loggerFactory from '~/utils/logger';
  2. const mongoose = require('mongoose');
  3. const express = require('express');
  4. const { body, query, param } = require('express-validator');
  5. const axios = require('axios');
  6. const urljoin = require('url-join');
  7. const {
  8. getConnectionStatus, getConnectionStatuses, sendSuccessMessage, defaultSupportedCommandsNameForBroadcastUse, defaultSupportedCommandsNameForSingleUse,
  9. } = require('@growi/slack');
  10. const ErrorV3 = require('../../models/vo/error-apiv3');
  11. const logger = loggerFactory('growi:routes:apiv3:slack-integration-settings');
  12. const router = express.Router();
  13. /**
  14. * @swagger
  15. * tags:
  16. * name: SlackIntegrationSettings
  17. */
  18. /**
  19. * @swagger
  20. *
  21. * components:
  22. * schemas:
  23. * BotType:
  24. * description: BotType
  25. * properties:
  26. * currentBotType:
  27. * type: string
  28. * SlackIntegration:
  29. * description: SlackIntegration
  30. * type: object
  31. * properties:
  32. * currentBotType:
  33. * type: string
  34. */
  35. module.exports = (crowi) => {
  36. const accessTokenParser = require('../../middlewares/access-token-parser')(crowi);
  37. const loginRequiredStrictly = require('../../middlewares/login-required')(crowi);
  38. const adminRequired = require('../../middlewares/admin-required')(crowi);
  39. const csrf = require('../../middlewares/csrf')(crowi);
  40. const apiV3FormValidator = require('../../middlewares/apiv3-form-validator')(crowi);
  41. const SlackAppIntegration = mongoose.model('SlackAppIntegration');
  42. const validator = {
  43. BotType: [
  44. body('currentBotType').isString(),
  45. ],
  46. SlackIntegration: [
  47. body('currentBotType')
  48. .isIn(['officialBot', 'customBotWithoutProxy', 'customBotWithProxy']),
  49. ],
  50. proxyUri: [
  51. body('proxyUri').if(value => value !== '').trim().matches(/^(https?:\/\/)/)
  52. .isURL({ require_tld: false }),
  53. ],
  54. updateSupportedCommands: [
  55. body('supportedCommandsForSingleUse').toArray(),
  56. body('supportedCommandsForBroadcastUse').toArray(),
  57. param('id').isMongoId().withMessage('id is required'),
  58. ],
  59. RelationTest: [
  60. body('slackAppIntegrationId').isMongoId(),
  61. body('channel').trim().isString(),
  62. ],
  63. deleteIntegration: [
  64. query('integrationIdToDelete').isMongoId(),
  65. ],
  66. SlackChannel: [
  67. body('channel').trim().not().isEmpty()
  68. .isString(),
  69. ],
  70. };
  71. async function resetAllBotSettings() {
  72. await SlackAppIntegration.deleteMany();
  73. const params = {
  74. 'slackbot:currentBotType': null,
  75. 'slackbot:signingSecret': null,
  76. 'slackbot:token': null,
  77. 'slackbot:proxyServerUri': null,
  78. };
  79. const { configManager } = crowi;
  80. // update config without publishing S2sMessage
  81. return configManager.updateConfigsInTheSameNamespace('crowi', params, true);
  82. }
  83. async function updateSlackBotSettings(params) {
  84. const { configManager } = crowi;
  85. // update config without publishing S2sMessage
  86. return configManager.updateConfigsInTheSameNamespace('crowi', params, true);
  87. }
  88. async function getConnectionStatusesFromProxy(tokens) {
  89. const csv = tokens.join(',');
  90. const proxyUri = crowi.configManager.getConfig('crowi', 'slackbot:proxyServerUri');
  91. const result = await axios.get(urljoin(proxyUri, '/g2s/connection-status'), {
  92. headers: {
  93. 'x-growi-gtop-tokens': csv,
  94. },
  95. });
  96. return result.data;
  97. }
  98. async function requestToProxyServer(token, method, endpoint, body) {
  99. const proxyUri = crowi.configManager.getConfig('crowi', 'slackbot:proxyServerUri');
  100. if (proxyUri == null) {
  101. throw new Error('Proxy URL is not registered');
  102. }
  103. const headers = {
  104. 'x-growi-gtop-tokens': token,
  105. };
  106. const result = await axios[method](urljoin(proxyUri, endpoint), body, { headers });
  107. return result.data;
  108. }
  109. /**
  110. * @swagger
  111. *
  112. * /slack-integration-settings/:
  113. * get:
  114. * tags: [SlackBotSettingParams]
  115. * operationId: getSlackBotSettingParams
  116. * summary: get /slack-integration
  117. * description: Get current settings and connection statuses.
  118. * responses:
  119. * 200:
  120. * description: Succeeded to get info.
  121. */
  122. router.get('/', accessTokenParser, loginRequiredStrictly, adminRequired, async(req, res) => {
  123. const { configManager } = crowi;
  124. const currentBotType = configManager.getConfig('crowi', 'slackbot:currentBotType');
  125. // retrieve settings
  126. const settings = {};
  127. if (currentBotType === 'customBotWithoutProxy') {
  128. settings.slackSigningSecretEnvVars = configManager.getConfigFromEnvVars('crowi', 'slackbot:signingSecret');
  129. settings.slackBotTokenEnvVars = configManager.getConfigFromEnvVars('crowi', 'slackbot:token');
  130. settings.slackSigningSecret = configManager.getConfig('crowi', 'slackbot:signingSecret');
  131. settings.slackBotToken = configManager.getConfig('crowi', 'slackbot:token');
  132. }
  133. else {
  134. settings.proxyServerUri = crowi.configManager.getConfig('crowi', 'slackbot:proxyServerUri');
  135. settings.proxyUriEnvVars = configManager.getConfigFromEnvVars('crowi', 'slackbot:proxyServerUri');
  136. }
  137. // retrieve connection statuses
  138. let connectionStatuses = {};
  139. let errorMsg;
  140. let errorCode;
  141. if (currentBotType == null) {
  142. // no need to do anything
  143. }
  144. else if (currentBotType === 'customBotWithoutProxy') {
  145. const token = settings.slackBotToken;
  146. // check the token is not null
  147. if (token != null) {
  148. try {
  149. connectionStatuses = await getConnectionStatuses([token]);
  150. }
  151. catch (e) {
  152. errorMsg = 'Error occured in getting connection statuses';
  153. errorCode = 'get-connection-failed';
  154. logger.error(errorMsg, e);
  155. }
  156. }
  157. }
  158. else {
  159. try {
  160. const slackAppIntegrations = await SlackAppIntegration.find();
  161. settings.slackAppIntegrations = slackAppIntegrations;
  162. }
  163. catch (e) {
  164. errorMsg = 'Error occured in finding SlackAppIntegration entities.';
  165. errorCode = 'get-slackappintegration-failed';
  166. logger.error(errorMsg, e);
  167. }
  168. const proxyServerUri = settings.proxyServerUri;
  169. if (proxyServerUri != null && settings.slackAppIntegrations != null && settings.slackAppIntegrations.length > 0) {
  170. try {
  171. // key: slackAppIntegration.tokenGtoP, value: slackAppIntegration._id
  172. const tokenGtoPToSlackAppIntegrationId = {};
  173. settings.slackAppIntegrations.forEach((slackAppIntegration) => {
  174. tokenGtoPToSlackAppIntegrationId[slackAppIntegration.tokenGtoP] = slackAppIntegration._id;
  175. });
  176. const result = (await getConnectionStatusesFromProxy(Object.keys(tokenGtoPToSlackAppIntegrationId)));
  177. Object.entries(result.connectionStatuses).forEach(([tokenGtoP, connectionStatus]) => {
  178. connectionStatuses[tokenGtoPToSlackAppIntegrationId[tokenGtoP]] = connectionStatus;
  179. });
  180. }
  181. catch (e) {
  182. errorMsg = 'Incorrect Proxy URL';
  183. errorCode = 'test-connection-failed';
  184. logger.error(errorMsg, e);
  185. }
  186. }
  187. }
  188. return res.apiv3({
  189. currentBotType, settings, connectionStatuses, errorMsg, errorCode,
  190. });
  191. });
  192. /**
  193. * @swagger
  194. *
  195. * /slack-integration-settings/:
  196. * put:
  197. * tags: [SlackIntegration]
  198. * operationId: putSlackIntegration
  199. * summary: put /slack-integration
  200. * description: Put SlackIntegration setting.
  201. * requestBody:
  202. * required: true
  203. * content:
  204. * application/json:
  205. * schema:
  206. * $ref: '#/components/schemas/SlackIntegration'
  207. * responses:
  208. * 200:
  209. * description: Succeeded to put Slack Integration setting.
  210. */
  211. router.put('/', accessTokenParser, loginRequiredStrictly, adminRequired, csrf, validator.SlackIntegration, apiV3FormValidator, async(req, res) => {
  212. const { currentBotType } = req.body;
  213. const requestParams = {
  214. 'slackbot:currentBotType': currentBotType,
  215. };
  216. try {
  217. await updateSlackBotSettings(requestParams);
  218. crowi.slackBotService.publishUpdatedMessage();
  219. const slackIntegrationSettingsParams = {
  220. currentBotType: crowi.configManager.getConfig('crowi', 'slackbot:currentBotType'),
  221. };
  222. return res.apiv3({ slackIntegrationSettingsParams });
  223. }
  224. catch (error) {
  225. const msg = 'Error occured in updating Slack bot setting';
  226. logger.error('Error', error);
  227. return res.apiv3Err(new ErrorV3(msg, 'update-SlackIntegrationSetting-failed'), 500);
  228. }
  229. });
  230. /**
  231. * @swagger
  232. *
  233. * /slack-integration-settings/bot-type/:
  234. * put:
  235. * tags: [botType]
  236. * operationId: putBotType
  237. * summary: /slack-integration/bot-type
  238. * description: Put botType setting.
  239. * requestBody:
  240. * required: true
  241. * content:
  242. * application/json:
  243. * schema:
  244. * $ref: '#/components/schemas/BotType'
  245. * responses:
  246. * 200:
  247. * description: Succeeded to put botType setting.
  248. */
  249. router.put('/bot-type', accessTokenParser, loginRequiredStrictly, adminRequired, csrf, validator.BotType, apiV3FormValidator, async(req, res) => {
  250. const { currentBotType } = req.body;
  251. await resetAllBotSettings();
  252. const requestParams = { 'slackbot:currentBotType': currentBotType };
  253. if (currentBotType === 'officialBot') {
  254. requestParams['slackbot:proxyServerUri'] = 'https://slackbot-proxy.growi.org';
  255. }
  256. try {
  257. await updateSlackBotSettings(requestParams);
  258. crowi.slackBotService.publishUpdatedMessage();
  259. // TODO Impl to delete AccessToken both of Proxy and GROWI when botType changes.
  260. const slackBotTypeParam = { slackBotType: crowi.configManager.getConfig('crowi', 'slackbot:currentBotType') };
  261. return res.apiv3({ slackBotTypeParam });
  262. }
  263. catch (error) {
  264. const msg = 'Error occured in updating Custom bot setting';
  265. logger.error('Error', error);
  266. return res.apiv3Err(new ErrorV3(msg, 'update-CustomBotSetting-failed'), 500);
  267. }
  268. });
  269. /**
  270. * @swagger
  271. *
  272. * /slack-integration/bot-type/:
  273. * delete:
  274. * tags: [botType]
  275. * operationId: deleteBotType
  276. * summary: /slack-integration/bot-type
  277. * description: Delete botType setting.
  278. * requestBody:
  279. * content:
  280. * application/json:
  281. * schema:
  282. * $ref: '#/components/schemas/BotType'
  283. * responses:
  284. * 200:
  285. * description: Succeeded to delete botType setting.
  286. */
  287. router.delete('/bot-type', accessTokenParser, loginRequiredStrictly, adminRequired, csrf, apiV3FormValidator, async(req, res) => {
  288. await resetAllBotSettings();
  289. const params = { 'slackbot:currentBotType': null };
  290. try {
  291. await updateSlackBotSettings(params);
  292. crowi.slackBotService.publishUpdatedMessage();
  293. // TODO Impl to delete AccessToken both of Proxy and GROWI when botType changes.
  294. const slackBotTypeParam = { slackBotType: crowi.configManager.getConfig('crowi', 'slackbot:currentBotType') };
  295. return res.apiv3({ slackBotTypeParam });
  296. }
  297. catch (error) {
  298. const msg = 'Error occured in updating Custom bot setting';
  299. logger.error('Error', error);
  300. return res.apiv3Err(new ErrorV3(msg, 'update-CustomBotSetting-failed'), 500);
  301. }
  302. });
  303. /**
  304. * @swagger
  305. *
  306. * /slack-integration-settings/without-proxy/update-settings/:
  307. * put:
  308. * tags: [UpdateWithoutProxySettings]
  309. * operationId: putWithoutProxySettings
  310. * summary: update customBotWithoutProxy settings
  311. * description: Update customBotWithoutProxy setting.
  312. * responses:
  313. * 200:
  314. * description: Succeeded to put CustomBotWithoutProxy setting.
  315. */
  316. router.put('/without-proxy/update-settings', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
  317. const currentBotType = crowi.configManager.getConfig('crowi', 'slackbot:currentBotType');
  318. if (currentBotType !== 'customBotWithoutProxy') {
  319. const msg = 'Not CustomBotWithoutProxy';
  320. return res.apiv3Err(new ErrorV3(msg, 'not-customBotWithoutProxy'), 400);
  321. }
  322. const { slackSigningSecret, slackBotToken } = req.body;
  323. const requestParams = {
  324. 'slackbot:signingSecret': slackSigningSecret,
  325. 'slackbot:token': slackBotToken,
  326. };
  327. try {
  328. await updateSlackBotSettings(requestParams);
  329. crowi.slackBotService.publishUpdatedMessage();
  330. const customBotWithoutProxySettingParams = {
  331. slackSigningSecret: crowi.configManager.getConfig('crowi', 'slackbot:signingSecret'),
  332. slackBotToken: crowi.configManager.getConfig('crowi', 'slackbot:token'),
  333. };
  334. return res.apiv3({ customBotWithoutProxySettingParams });
  335. }
  336. catch (error) {
  337. const msg = 'Error occured in updating Custom bot setting';
  338. logger.error('Error', error);
  339. return res.apiv3Err(new ErrorV3(msg, 'update-CustomBotSetting-failed'), 500);
  340. }
  341. });
  342. /**
  343. * @swagger
  344. *
  345. * /slack-integration-settings/slack-app-integrations:
  346. * put:
  347. * tags: [SlackIntegration]
  348. * operationId: putSlackAppIntegrations
  349. * summary: /slack-integration
  350. * description: Generate SlackAppIntegrations
  351. * responses:
  352. * 200:
  353. * description: Succeeded to create slack app integration
  354. */
  355. router.put('/slack-app-integrations', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
  356. const SlackAppIntegrationRecordsNum = await SlackAppIntegration.countDocuments();
  357. if (SlackAppIntegrationRecordsNum >= 10) {
  358. const msg = 'Not be able to create more than 10 slack workspace integration settings';
  359. logger.error('Error', msg);
  360. return res.apiv3Err(new ErrorV3(msg, 'create-slackAppIntegeration-failed'), 500);
  361. }
  362. const { tokenGtoP, tokenPtoG } = await SlackAppIntegration.generateUniqueAccessTokens();
  363. try {
  364. const slackAppTokens = await SlackAppIntegration.create({
  365. tokenGtoP,
  366. tokenPtoG,
  367. supportedCommandsForBroadcastUse: defaultSupportedCommandsNameForBroadcastUse,
  368. supportedCommandsForSingleUse: defaultSupportedCommandsNameForSingleUse,
  369. });
  370. // MOCK DATA DELETE THIS GW-6972 ---------------
  371. const SlackAppIntegrationMock = mongoose.model('SlackAppIntegrationMock');
  372. const MOCK = await SlackAppIntegrationMock.create({
  373. tokenGtoP,
  374. tokenPtoG,
  375. supportedCommandsForBroadcastUse: defaultSupportedCommandsNameForBroadcastUse,
  376. supportedCommandsForSingleUse: defaultSupportedCommandsNameForSingleUse,
  377. permittedChannelsForEachCommand: {
  378. channelsObject: new Map(),
  379. },
  380. });
  381. // MOCK DATA DELETE THIS GW-6972 ---------------
  382. return res.apiv3(slackAppTokens, 200);
  383. }
  384. catch (error) {
  385. const msg = 'Error occurred during creating slack integration settings procedure';
  386. logger.error('Error', error);
  387. return res.apiv3Err(new ErrorV3(msg, 'creating-slack-integration-settings-procedure-failed'), 500);
  388. }
  389. });
  390. /**
  391. * @swagger
  392. *
  393. * /slack-integration-settings/regenerate-tokens:
  394. * put:
  395. * tags: [SlackIntegration]
  396. * operationId: putRegenerateTokens
  397. * summary: /slack-integration
  398. * description: Regenerate SlackAppTokens
  399. * responses:
  400. * 200:
  401. * description: Succeeded to regenerate slack app tokens
  402. */
  403. router.put('/regenerate-tokens', loginRequiredStrictly, adminRequired, csrf, async(req, res) => {
  404. const { slackAppIntegrationId } = req.body;
  405. try {
  406. const { tokenGtoP, tokenPtoG } = await SlackAppIntegration.generateUniqueAccessTokens();
  407. const slackAppTokens = await SlackAppIntegration.findByIdAndUpdate(slackAppIntegrationId, { tokenGtoP, tokenPtoG });
  408. return res.apiv3(slackAppTokens, 200);
  409. }
  410. catch (error) {
  411. const msg = 'Error occurred during regenerating slack app tokens';
  412. logger.error('Error', error);
  413. return res.apiv3Err(new ErrorV3(msg, 'regenerating-slackAppTokens-failed'), 500);
  414. }
  415. });
  416. /**
  417. * @swagger
  418. *
  419. * /slack-integration-settings/slack-app-integration:
  420. * delete:
  421. * tags: [SlackIntegration]
  422. * operationId: deleteAccessTokens
  423. * summary: delete accessTokens
  424. * description: Delete accessTokens
  425. * responses:
  426. * 200:
  427. * description: Succeeded to delete access tokens for slack
  428. */
  429. router.delete('/slack-app-integration', validator.deleteIntegration, apiV3FormValidator, async(req, res) => {
  430. const SlackAppIntegration = mongoose.model('SlackAppIntegration');
  431. const { integrationIdToDelete } = req.query;
  432. try {
  433. const response = await SlackAppIntegration.findOneAndDelete({ _id: integrationIdToDelete });
  434. return res.apiv3({ response });
  435. }
  436. catch (error) {
  437. const msg = 'Error occured in deleting access token for slack app tokens';
  438. logger.error('Error', error);
  439. return res.apiv3Err(new ErrorV3(msg, 'update-slackAppTokens-failed'), 500);
  440. }
  441. });
  442. router.put('/proxy-uri', loginRequiredStrictly, adminRequired, csrf, validator.proxyUri, apiV3FormValidator, async(req, res) => {
  443. const { proxyUri } = req.body;
  444. const requestParams = { 'slackbot:proxyServerUri': proxyUri };
  445. try {
  446. await updateSlackBotSettings(requestParams);
  447. crowi.slackBotService.publishUpdatedMessage();
  448. return res.apiv3({});
  449. }
  450. catch (error) {
  451. const msg = 'Error occured in updating Custom bot setting';
  452. logger.error('Error', error);
  453. return res.apiv3Err(new ErrorV3(msg, 'update-CustomBotSetting-failed'), 500);
  454. }
  455. });
  456. /**
  457. * @swagger
  458. *
  459. * /slack-integration-settings/:id/supported-commands:
  460. * put:
  461. * tags: [SlackIntegration]
  462. * operationId: putSupportedCommands
  463. * summary: /slack-integration-settings/:id/supported-commands
  464. * description: update supported commands
  465. * responses:
  466. * 200:
  467. * description: Succeeded to update supported commands
  468. */
  469. router.put('/:id/supported-commands', loginRequiredStrictly, adminRequired, csrf, validator.updateSupportedCommands, apiV3FormValidator, async(req, res) => {
  470. const { supportedCommandsForBroadcastUse, supportedCommandsForSingleUse } = req.body;
  471. const { id } = req.params;
  472. try {
  473. const slackAppIntegration = await SlackAppIntegration.findByIdAndUpdate(
  474. id,
  475. { supportedCommandsForBroadcastUse, supportedCommandsForSingleUse },
  476. { new: true },
  477. );
  478. await requestToProxyServer(
  479. slackAppIntegration.tokenGtoP,
  480. 'put',
  481. '/g2s/supported-commands',
  482. {
  483. supportedCommandsForBroadcastUse: slackAppIntegration.supportedCommandsForBroadcastUse,
  484. supportedCommandsForSingleUse: slackAppIntegration.supportedCommandsForSingleUse,
  485. },
  486. );
  487. return res.apiv3({ slackAppIntegration });
  488. }
  489. catch (error) {
  490. const msg = 'Error occured in updating Custom bot setting';
  491. logger.error('Error', error);
  492. return res.apiv3Err(new ErrorV3(msg, 'update-CustomBotSetting-failed'), 500);
  493. }
  494. });
  495. /**
  496. * @swagger
  497. *
  498. * /slack-integration-settings/with-proxy/relation-test:
  499. * post:
  500. * tags: [botType]
  501. * operationId: postRelationTest
  502. * summary: /slack-integration/bot-type
  503. * description: Delete botType setting.
  504. * requestBody:
  505. * content:
  506. * application/json:
  507. * schema:
  508. * properties:
  509. * slackAppIntegrationId:
  510. * type: string
  511. * responses:
  512. * 200:
  513. * description: Succeeded to delete botType setting.
  514. */
  515. router.post('/with-proxy/relation-test', loginRequiredStrictly, adminRequired, csrf, validator.RelationTest, apiV3FormValidator, async(req, res) => {
  516. const currentBotType = crowi.configManager.getConfig('crowi', 'slackbot:currentBotType');
  517. if (currentBotType === 'customBotWithoutProxy') {
  518. const msg = 'Not Proxy Type';
  519. return res.apiv3Err(new ErrorV3(msg, 'not-proxy-type'), 400);
  520. }
  521. const { slackAppIntegrationId } = req.body;
  522. let slackBotToken;
  523. try {
  524. const slackAppIntegration = await SlackAppIntegration.findOne({ _id: slackAppIntegrationId });
  525. if (slackAppIntegration == null) {
  526. const msg = 'Could not find SlackAppIntegration by id';
  527. return res.apiv3Err(new ErrorV3(msg, 'find-slackAppIntegration-failed'), 400);
  528. }
  529. const result = await requestToProxyServer(
  530. slackAppIntegration.tokenGtoP,
  531. 'post',
  532. '/g2s/relation-test',
  533. {
  534. supportedCommandsForBroadcastUse: slackAppIntegration.supportedCommandsForBroadcastUse,
  535. supportedCommandsForSingleUse: slackAppIntegration.supportedCommandsForSingleUse,
  536. },
  537. );
  538. slackBotToken = result.slackBotToken;
  539. if (slackBotToken == null) {
  540. const msg = 'Could not find slackBotToken by relation';
  541. return res.apiv3Err(new ErrorV3(msg, 'find-slackBotToken-failed'), 400);
  542. }
  543. }
  544. catch (error) {
  545. logger.error('Error', error);
  546. return res.apiv3Err(new ErrorV3(`Error occured while testing. Cause: ${error.message}`, 'test-failed', error.stack));
  547. }
  548. const { channel } = req.body;
  549. const appSiteURL = crowi.configManager.getConfig('crowi', 'app:siteUrl');
  550. try {
  551. await sendSuccessMessage(slackBotToken, channel, appSiteURL);
  552. }
  553. catch (error) {
  554. return res.apiv3Err(new ErrorV3(`Error occured while sending message. Cause: ${error.message}`, 'send-message-failed', error.stack));
  555. }
  556. return res.apiv3();
  557. });
  558. /**
  559. * @swagger
  560. *
  561. * /slack-integration-settings/without-proxy/test:
  562. * post:
  563. * tags: [botType]
  564. * operationId: postTest
  565. * summary: test the connection
  566. * description: Test the connection with slack work space.
  567. * requestBody:
  568. * content:
  569. * application/json:
  570. * schema:
  571. * properties:
  572. * testChannel:
  573. * type: string
  574. * responses:
  575. * 200:
  576. * description: Succeeded to connect to slack work space.
  577. */
  578. router.post('/without-proxy/test', loginRequiredStrictly, adminRequired, csrf, validator.SlackChannel, apiV3FormValidator, async(req, res) => {
  579. const currentBotType = crowi.configManager.getConfig('crowi', 'slackbot:currentBotType');
  580. if (currentBotType !== 'customBotWithoutProxy') {
  581. const msg = 'Select Without Proxy Type';
  582. return res.apiv3Err(new ErrorV3(msg, 'select-not-proxy-type'), 400);
  583. }
  584. const slackBotToken = crowi.configManager.getConfig('crowi', 'slackbot:token');
  585. const status = await getConnectionStatus(slackBotToken);
  586. if (status.error != null) {
  587. return res.apiv3Err(new ErrorV3(`Error occured while getting connection. ${status.error}`, 'send-message-failed'));
  588. }
  589. const { channel } = req.body;
  590. const appSiteURL = crowi.configManager.getConfig('crowi', 'app:siteUrl');
  591. try {
  592. await sendSuccessMessage(slackBotToken, channel, appSiteURL);
  593. }
  594. catch (error) {
  595. return res.apiv3Err(new ErrorV3(`Error occured while sending message. Cause: ${error.message}`, 'send-message-failed', error.stack));
  596. }
  597. return res.apiv3();
  598. });
  599. return router;
  600. };