All files / src/Batch OutlookSubscribeWebhook.ts

52.63% Statements 20/38
25% Branches 2/8
50% Functions 2/4
54.05% Lines 20/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 1027x 7x   7x 7x 7x   7x 7x     7x   7x     7x       1x 1x 1x   1x 1x 1x     1x 1x   1x                                                                                           1x                                              
import { ApplicationInstall } from '@orchesty/nodejs-sdk/dist/lib/Application/Database/ApplicationInstall';
import Webhook from '@orchesty/nodejs-sdk/dist/lib/Application/Database/Webhook';
import WebhookRepository from '@orchesty/nodejs-sdk/dist/lib/Application/Database/WebhookRepository';
import ABatchNode from '@orchesty/nodejs-sdk/dist/lib/Batch/ABatchNode';
import { orchestyOptions } from '@orchesty/nodejs-sdk/dist/lib/Config/Config';
import { HttpMethods } from '@orchesty/nodejs-sdk/dist/lib/Transport/HttpMethods';
import BatchProcessDto from '@orchesty/nodejs-sdk/dist/lib/Utils/BatchProcessDto';
import ResultCode from '@orchesty/nodejs-sdk/dist/lib/Utils/ResultCode';
import crypto from 'crypto';
import OutlookApplication from '../OutlookApplication';
 
export const NAME = 'outlook-subscribe-webhook';
 
export default class OutlookSubscribeWebhook extends ABatchNode {
 
    public getName(): string {
        return NAME;
    }
 
    public async processAction(dto: BatchProcessDto): Promise<BatchProcessDto> {
        const app = this.getApplication<OutlookApplication>();
        const appInstall = await this.getApplicationInstallFromProcess(dto, null, true);
        const repo = this.getDbClient().getRepository(Webhook) as WebhookRepository;
 
        let dbWebhooks: Webhook[] = [];
        Eif (dto.getBatchCursor('firstRun') === 'firstRun') {
            dbWebhooks = await repo.findMany({ users: [appInstall.getUser()], apps: [app.getName()] });
        }
 
        const webhookIndex = Number(dto.getBatchCursor('0'));
        const webhooks = app.getWebhookSubscriptions();
 
        Iif (webhooks.length > 0) {
            const webhook = webhooks[webhookIndex];
            const backendUrl = orchestyOptions.backend;
            const token = this.getRandomToken();
            const expiration = new Date();
            expiration.setDate(expiration.getDate() + 6);
            const requestDto = app.getRequestDto(
                dto,
                appInstall,
                HttpMethods.POST,
                '/subscriptions',
                {
                    notificationUrl: `${backendUrl}/api/applications/${app.getName()}/sync/notificationCallback?pf_user=${dto.getUser()}&pf_wh_token=${token}&pf_topology=${webhook.getTopology()}&pf_node=${webhook.getNode()}`,
                    changeType: webhook.getParameters().changeType,
                    resource: webhook.getName(),
                    expirationDateTime: expiration.toISOString(),
                },
            );
 
            let res;
            try {
                res = await this.getSender().send<IResponseJson>(requestDto, [201]);
                const respBody = res.getJsonBody();
 
                await repo.insert(new Webhook()
                    .setWebhookId(respBody.id)
                    .setUser(appInstall.getUser())
                    .setNode(webhooks[webhookIndex].getNode())
                    .setToken(token)
                    .setApplication(app.getName())
                    .setTopology(webhooks[webhookIndex].getTopology())
                    .setName(webhooks[webhookIndex].getName()));
 
                if (webhooks.length - 1 > webhookIndex) {
                    dto.setItemList(dbWebhooks.map((w) => ({ id: w.getId() })));
                    dto.setBatchCursor((webhookIndex + 1).toString());
                }
                // eslint-disable-next-line @typescript-eslint/no-unused-vars
            } catch (e) {
                appInstall.setEnabled(false);
                await this.getDbClient().getRepository(ApplicationInstall).update(appInstall);
 
                dto.setStopProcess(ResultCode.STOP_AND_FAILED, res?.getBody() ?? 'Webhook could not be registered!');
            }
        }
 
        return dto;
    }
 
    private getRandomToken(): string {
        return crypto.randomBytes(64).toString('hex');
    }
 
}
 
export interface IResponseJson {
    // eslint-disable-next-line @typescript-eslint/naming-convention
    '@odata.context': string;
    id: string;
    resource: string;
    applicationId: string;
    changeType: string;
    clientState: string;
    notificationUrl: string;
    expirationDateTime: string;
    creatorId: string;
    latestSupportedTlsVersion: string;
    notificationContentType: string;
}