116 lines
3.2 KiB
TypeScript
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,
|
|
};
|
|
}
|
|
}
|