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

Merge pull request #3878 from weseek/feat/6209-6211-implement-unregister

Feat/6209 6211 implement unregister
itizawa 4 лет назад
Родитель
Сommit
f9acdfda18

+ 23 - 0
packages/slackbot-proxy/src/controllers/slack.ts

@@ -19,6 +19,7 @@ import { AddSigningSecretToReq } from '~/middlewares/slack-to-growi/add-signing-
 import { AuthorizeCommandMiddleware, AuthorizeInteractionMiddleware } from '~/middlewares/slack-to-growi/authorizer';
 import { AuthorizeCommandMiddleware, AuthorizeInteractionMiddleware } from '~/middlewares/slack-to-growi/authorizer';
 import { InstallerService } from '~/services/InstallerService';
 import { InstallerService } from '~/services/InstallerService';
 import { RegisterService } from '~/services/RegisterService';
 import { RegisterService } from '~/services/RegisterService';
+import { UnregisterService } from '~/services/UnregisterService';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
 
 
@@ -43,6 +44,9 @@ export class SlackCtrl {
   @Inject()
   @Inject()
   registerService: RegisterService;
   registerService: RegisterService;
 
 
+  @Inject()
+  unregisterService: UnregisterService;
+
   @Get('/install')
   @Get('/install')
   async install(): Promise<string> {
   async install(): Promise<string> {
     const url = await this.installerService.installer.generateInstallUrl({
     const url = await this.installerService.installer.generateInstallUrl({
@@ -83,6 +87,19 @@ export class SlackCtrl {
       return this.registerService.process(growiCommand, authorizeResult, body as {[key:string]:string});
       return this.registerService.process(growiCommand, authorizeResult, body as {[key:string]:string});
     }
     }
 
 
+    // unregister
+    if (growiCommand.growiCommandType === 'unregister') {
+      if (growiCommand.growiCommandArgs.length === 0) {
+        return 'GROWI Urls is required.';
+      }
+
+      // Send response immediately to avoid opelation_timeout error
+      // See https://api.slack.com/apis/connections/events-api#the-events-api__responding-to-events
+      res.send();
+
+      return this.unregisterService.process(growiCommand, authorizeResult, body as {[key:string]:string});
+    }
+
     const installationId = authorizeResult.enterpriseId || authorizeResult.teamId;
     const installationId = authorizeResult.enterpriseId || authorizeResult.teamId;
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
     const installation = await this.installationRepository.findByTeamIdOrEnterpriseId(installationId!);
     const installation = await this.installationRepository.findByTeamIdOrEnterpriseId(installationId!);
@@ -173,6 +190,12 @@ export class SlackCtrl {
       return;
       return;
     }
     }
 
 
+    // unregister
+    if (callBackId === 'unregister') {
+      await this.unregisterService.unregister(this.relationRepository, installation, authorizeResult, payload);
+      return;
+    }
+
     /*
     /*
      * forward to GROWI server
      * forward to GROWI server
      */
      */

+ 72 - 0
packages/slackbot-proxy/src/services/UnregisterService.ts

@@ -0,0 +1,72 @@
+import { Service } from '@tsed/di';
+import { WebClient, LogLevel } from '@slack/web-api';
+import { GrowiCommand, generateMarkdownSectionBlock } from '@growi/slack';
+import { AuthorizeResult } from '@slack/oauth';
+import { GrowiCommandProcessor } from '~/interfaces/slack-to-growi/growi-command-processor';
+import { RelationRepository } from '~/repositories/relation';
+import { Installation } from '~/entities/installation';
+
+const isProduction = process.env.NODE_ENV === 'production';
+
+@Service()
+export class UnregisterService implements GrowiCommandProcessor {
+
+  async process(growiCommand: GrowiCommand, authorizeResult: AuthorizeResult, body: {[key:string]:string}): Promise<void> {
+    const { botToken } = authorizeResult;
+    const client = new WebClient(botToken, { logLevel: isProduction ? LogLevel.DEBUG : LogLevel.INFO });
+    const growiUrls = growiCommand.growiCommandArgs;
+    await client.views.open({
+      trigger_id: body.trigger_id,
+      view: {
+        type: 'modal',
+        callback_id: 'unregister',
+        title: {
+          type: 'plain_text',
+          text: 'Unregister Credentials',
+        },
+        submit: {
+          type: 'plain_text',
+          text: 'Submit',
+        },
+        close: {
+          type: 'plain_text',
+          text: 'Close',
+        },
+        private_metadata: JSON.stringify({ channel: body.channel_name, growiUrls }),
+
+        blocks: [
+          ...growiUrls.map(growiCommandArg => generateMarkdownSectionBlock(`GROWI url: ${growiCommandArg}.`)),
+        ],
+      },
+    });
+  }
+
+  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
+  async unregister(relationRepository:RelationRepository, installation:Installation | undefined, authorizeResult: AuthorizeResult, payload: any):Promise<void> {
+    const { botToken } = authorizeResult;
+    const { channel, growiUrls } = JSON.parse(payload.view.private_metadata);
+    const client = new WebClient(botToken, { logLevel: isProduction ? LogLevel.DEBUG : LogLevel.INFO });
+
+    const deleteResult = await relationRepository.createQueryBuilder('relation')
+      .where('relation.growiUri IN (:uris)', { uris: growiUrls })
+      .andWhere('relation.installationId = :installationId', { installationId: installation?.id })
+      .delete()
+      .execute();
+
+    await client.chat.postEphemeral({
+      channel,
+      user: payload.user.id,
+      // Recommended including 'text' to provide a fallback when using blocks
+      // refer to https://api.slack.com/methods/chat.postEphemeral#text_usage
+      text: 'Delete Relations',
+      blocks: [
+        generateMarkdownSectionBlock(`Deleted ${deleteResult.affected} Relations.`),
+      ],
+    });
+
+    return;
+
+  }
+
+
+}