postiz/libraries/nestjs-libraries/src/integrations/refresh.integration.service.ts

116 lines
3.2 KiB
TypeScript

import { forwardRef, Inject, Injectable } from '@nestjs/common';
import { Integration } from '@prisma/client';
import { IntegrationManager } from '@gitroom/nestjs-libraries/integrations/integration.manager';
import { IntegrationService } from '@gitroom/nestjs-libraries/database/prisma/integrations/integration.service';
import {
AuthTokenDetails,
SocialProvider,
} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
import { TemporalService } from 'nestjs-temporal-core';
@Injectable()
export class RefreshIntegrationService {
constructor(
private _integrationManager: IntegrationManager,
@Inject(forwardRef(() => IntegrationService))
private _integrationService: IntegrationService,
private _temporalService: TemporalService
) {}
async refresh(integration: Integration): Promise<false | AuthTokenDetails> {
const socialProvider = this._integrationManager.getSocialIntegration(
integration.providerIdentifier
);
const refresh = await this.refreshProcess(integration, socialProvider);
if (!refresh) {
return false as const;
}
await this._integrationService.createOrUpdateIntegration(
undefined,
!!socialProvider.oneTimeToken,
integration.organizationId,
integration.name,
integration.picture!,
'social',
integration.internalId,
integration.providerIdentifier,
refresh.accessToken,
refresh.refreshToken,
refresh.expiresIn
);
return refresh;
}
public async setBetweenSteps(integration: Integration) {
await this._integrationService.setBetweenRefreshSteps(integration.id);
await this._integrationService.informAboutRefreshError(
integration.organizationId,
integration
);
}
public async startRefreshWorkflow(orgId: string, id: string, integration: SocialProvider) {
if (!integration.refreshCron) {
return false;
}
return this._temporalService.client
.getRawClient()
?.workflow.start(`refreshTokenWorkflow`, {
workflowId: `refresh_${id}`,
args: [{integrationId: id, organizationId: orgId}],
taskQueue: 'main',
workflowIdConflictPolicy: 'TERMINATE_EXISTING',
});
}
private async refreshProcess(
integration: Integration,
socialProvider: SocialProvider
): Promise<AuthTokenDetails | false> {
const refresh: false | AuthTokenDetails = await socialProvider
.refreshToken(integration.refreshToken)
.catch((err) => false);
if (!refresh || !refresh.accessToken) {
await this._integrationService.refreshNeeded(
integration.organizationId,
integration.id
);
await this._integrationService.informAboutRefreshError(
integration.organizationId,
integration
);
await this._integrationService.disconnectChannel(
integration.organizationId,
integration
);
return false;
}
if (
!socialProvider.reConnect ||
integration.rootInternalId === integration.internalId
) {
return refresh;
}
const reConnect = await socialProvider.reConnect(
integration.rootInternalId,
integration.internalId,
refresh.accessToken
);
return {
...refresh,
...reConnect,
};
}
}