From 133af09aa058c38665c1ff5f7397f9fee57537ec Mon Sep 17 00:00:00 2001 From: nael Date: Fri, 12 Apr 2024 19:49:45 +0200 Subject: [PATCH] :construction: Wip 2 --- .../crm/services/accelo/accelo.service.ts | 1 - .../crm/services/affinity/affinity.service.ts | 165 ---------------- .../services/insightly/insightly.service.ts | 165 ---------------- .../crm/services/sugarcrm/sugarcrm.service.ts | 187 ------------------ pnpm-lock.yaml | 14 ++ 5 files changed, 14 insertions(+), 518 deletions(-) delete mode 100644 packages/api/src/@core/connections/crm/services/affinity/affinity.service.ts delete mode 100644 packages/api/src/@core/connections/crm/services/insightly/insightly.service.ts delete mode 100644 packages/api/src/@core/connections/crm/services/sugarcrm/sugarcrm.service.ts diff --git a/packages/api/src/@core/connections/crm/services/accelo/accelo.service.ts b/packages/api/src/@core/connections/crm/services/accelo/accelo.service.ts index 39573aec2..97ae8ed0d 100644 --- a/packages/api/src/@core/connections/crm/services/accelo/accelo.service.ts +++ b/packages/api/src/@core/connections/crm/services/accelo/accelo.service.ts @@ -72,7 +72,6 @@ export class AcceloConnectionService implements ICrmConnectionService { redirect_uri: REDIRECT_URI, code: code, }); - //const subdomain = 'panora'; //TODO: if custom oauth then get the actual domain from customer const res = await axios.post( `${CREDENTIALS.SUBDOMAIN}/oauth2/v0/token`, formData.toString(), diff --git a/packages/api/src/@core/connections/crm/services/affinity/affinity.service.ts b/packages/api/src/@core/connections/crm/services/affinity/affinity.service.ts deleted file mode 100644 index 226b8be58..000000000 --- a/packages/api/src/@core/connections/crm/services/affinity/affinity.service.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import axios from 'axios'; -import { PrismaService } from '@@core/prisma/prisma.service'; -import { Action, handleServiceError } from '@@core/utils/errors'; -import { LoggerService } from '@@core/logger/logger.service'; -import { v4 as uuidv4 } from 'uuid'; -import { EnvironmentService } from '@@core/environment/environment.service'; -import { EncryptionService } from '@@core/encryption/encryption.service'; -import { - CallbackParams, - RefreshParams, - ICrmConnectionService, -} from '../../types'; -import { ServiceRegistry } from '../registry.service'; -import { OAuth2AuthData, providerToType } from '@panora/shared'; -import { AuthStrategy } from '@panora/shared'; -import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service'; - -export type AffinityOAuthResponse = { - access_token: string; - refresh_token: string; - expires_at: string; -}; - -@Injectable() -export class AffinityConnectionService implements ICrmConnectionService { - private readonly type: string; - - constructor( - private prisma: PrismaService, - private logger: LoggerService, - private env: EnvironmentService, - private cryptoService: EncryptionService, - private registry: ServiceRegistry, - private cService: ConnectionsStrategiesService, - ) { - this.logger.setContext(AffinityConnectionService.name); - this.registry.registerService('affinity', this); - this.type = providerToType('affinity', 'crm', AuthStrategy.oauth2); - } - - async handleCallback(opts: CallbackParams) { - try { - const { linkedUserId, projectId, code } = opts; - const isNotUnique = await this.prisma.connections.findFirst({ - where: { - id_linked_user: linkedUserId, - provider_slug: `affinity`, - vertical: 'crm', - }, - }); - - //reconstruct the redirect URI that was passed in the githubend it must be the same - const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; - const CREDENTIALS = (await this.cService.getCredentials( - projectId, - this.type, - )) as OAuth2AuthData; - - const formData = new URLSearchParams({ - client_id: CREDENTIALS.CLIENT_ID, - client_secret: CREDENTIALS.CLIENT_SECRET, - redirect_uri: REDIRECT_URI, - code: code, - grant_type: 'authorization_code', - }); - const subdomain = 'panora'; - const res = await axios.post('', formData.toString(), { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', - }, - }); - const data: AffinityOAuthResponse = res.data; - this.logger.log( - 'OAuth credentials : affinity ticketing ' + JSON.stringify(data), - ); - - let db_res; - const connection_token = uuidv4(); - - if (isNotUnique) { - db_res = await this.prisma.connections.update({ - where: { - id_connection: isNotUnique.id_connection, - }, - data: { - access_token: this.cryptoService.encrypt(data.access_token), - refresh_token: this.cryptoService.encrypt(data.refresh_token), - account_url: '', - expiration_timestamp: new Date( - new Date().getTime() + Number(data.expires_at) * 1000, - ), - status: 'valid', - created_at: new Date(), - }, - }); - } else { - db_res = await this.prisma.connections.create({ - data: { - id_connection: uuidv4(), - connection_token: connection_token, - provider_slug: 'affinity', - vertical: 'crm', - token_type: 'oauth', - account_url: '', - access_token: this.cryptoService.encrypt(data.access_token), - refresh_token: this.cryptoService.encrypt(data.refresh_token), - expiration_timestamp: new Date( - new Date().getTime() + Number(data.expires_at) * 1000, - ), - status: 'valid', - created_at: new Date(), - projects: { - connect: { id_project: projectId }, - }, - linked_users: { - connect: { id_linked_user: linkedUserId }, - }, - }, - }); - } - return db_res; - } catch (error) { - handleServiceError(error, this.logger, 'affinity', Action.oauthCallback); - } - } - - async handleTokenRefresh(opts: RefreshParams) { - try { - const { connectionId, refreshToken, projectId } = opts; - const formData = new URLSearchParams({ - grant_type: 'refresh_token', - refresh_token: this.cryptoService.decrypt(refreshToken), - }); - const CREDENTIALS = (await this.cService.getCredentials( - projectId, - this.type, - )) as OAuth2AuthData; - - //const subdomain = 'panora'; - const res = await axios.post('', formData.toString(), { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', - Authorization: `Basic JHt0aGlzLmVudi5nZXRgQWZmaW5pdHlTZWNyZXRgKCkuQ0xJRU5UX0lEfTokewogICAgICAgICAgICAgICAgdGhpcy5lbnYuZ2V0YEFmZmluaXR5U2VjcmV0YCgpLkNMSUVOVF9TRUNSRVQKICAgICAgICAgICAgICB9`, - }, - }); - const data: AffinityOAuthResponse = res.data; - await this.prisma.connections.update({ - where: { - id_connection: connectionId, - }, - data: { - access_token: this.cryptoService.encrypt(data.access_token), - refresh_token: this.cryptoService.encrypt(data.refresh_token), - expiration_timestamp: new Date( - new Date().getTime() + Number(data.expires_at) * 1000, - ), - }, - }); - this.logger.log('OAuth credentials updated : affinity '); - } catch (error) { - handleServiceError(error, this.logger, 'affinity', Action.oauthRefresh); - } - } -} diff --git a/packages/api/src/@core/connections/crm/services/insightly/insightly.service.ts b/packages/api/src/@core/connections/crm/services/insightly/insightly.service.ts deleted file mode 100644 index 223b95cbc..000000000 --- a/packages/api/src/@core/connections/crm/services/insightly/insightly.service.ts +++ /dev/null @@ -1,165 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import axios from 'axios'; -import { PrismaService } from '@@core/prisma/prisma.service'; -import { Action, handleServiceError } from '@@core/utils/errors'; -import { LoggerService } from '@@core/logger/logger.service'; -import { v4 as uuidv4 } from 'uuid'; -import { EnvironmentService } from '@@core/environment/environment.service'; -import { EncryptionService } from '@@core/encryption/encryption.service'; -import { - CallbackParams, - RefreshParams, - ICrmConnectionService, -} from '../../types'; -import { ServiceRegistry } from '../registry.service'; -import { OAuth2AuthData, providerToType } from '@panora/shared'; -import { AuthStrategy } from '@panora/shared'; -import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service'; - -export type InsightlyOAuthResponse = { - access_token: string; - refresh_token: string; - expires_at: string; -}; - -@Injectable() -export class InsightlyConnectionService implements ICrmConnectionService { - private readonly type: string; - - constructor( - private prisma: PrismaService, - private logger: LoggerService, - private env: EnvironmentService, - private cryptoService: EncryptionService, - private registry: ServiceRegistry, - private cService: ConnectionsStrategiesService, - ) { - this.logger.setContext(InsightlyConnectionService.name); - this.registry.registerService('insightly', this); - this.type = providerToType('insightly', 'crm', AuthStrategy.oauth2); - } - - async handleCallback(opts: CallbackParams) { - try { - const { linkedUserId, projectId, code } = opts; - const isNotUnique = await this.prisma.connections.findFirst({ - where: { - id_linked_user: linkedUserId, - provider_slug: `insightly`, - vertical: 'crm', - }, - }); - - //reconstruct the redirect URI that was passed in the githubend it must be the same - const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; - const CREDENTIALS = (await this.cService.getCredentials( - projectId, - this.type, - )) as OAuth2AuthData; - - const formData = new URLSearchParams({ - client_id: CREDENTIALS.CLIENT_ID, - client_secret: CREDENTIALS.CLIENT_SECRET, - redirect_uri: REDIRECT_URI, - code: code, - grant_type: 'authorization_code', - }); - //const subdomain = 'panora'; - const res = await axios.post('', formData.toString(), { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', - }, - }); - const data: InsightlyOAuthResponse = res.data; - this.logger.log( - 'OAuth credentials : insightly ticketing ' + JSON.stringify(data), - ); - - let db_res; - const connection_token = uuidv4(); - - if (isNotUnique) { - db_res = await this.prisma.connections.update({ - where: { - id_connection: isNotUnique.id_connection, - }, - data: { - access_token: this.cryptoService.encrypt(data.access_token), - refresh_token: this.cryptoService.encrypt(data.refresh_token), - account_url: '', - expiration_timestamp: new Date( - new Date().getTime() + Number(data.expires_at) * 1000, - ), - status: 'valid', - created_at: new Date(), - }, - }); - } else { - db_res = await this.prisma.connections.create({ - data: { - id_connection: uuidv4(), - connection_token: connection_token, - provider_slug: 'insightly', - vertical: 'crm', - token_type: 'oauth', - account_url: '', - access_token: this.cryptoService.encrypt(data.access_token), - refresh_token: this.cryptoService.encrypt(data.refresh_token), - expiration_timestamp: new Date( - new Date().getTime() + Number(data.expires_at) * 1000, - ), - status: 'valid', - created_at: new Date(), - projects: { - connect: { id_project: projectId }, - }, - linked_users: { - connect: { id_linked_user: linkedUserId }, - }, - }, - }); - } - return db_res; - } catch (error) { - handleServiceError(error, this.logger, 'insightly', Action.oauthCallback); - } - } - - async handleTokenRefresh(opts: RefreshParams) { - try { - const { connectionId, refreshToken, projectId } = opts; - const formData = new URLSearchParams({ - grant_type: 'refresh_token', - refresh_token: this.cryptoService.decrypt(refreshToken), - }); - const CREDENTIALS = (await this.cService.getCredentials( - projectId, - this.type, - )) as OAuth2AuthData; - - const subdomain = 'panora'; - const res = await axios.post('', formData.toString(), { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', - Authorization: `Basic JHt0aGlzLmVudi5nZXRgSW5zaWdodGx5U2VjcmV0YCgpLkNMSUVOVF9JRH06JHsKICAgICAgICAgICAgICAgIHRoaXMuZW52LmdldGBJbnNpZ2h0bHlTZWNyZXRgKCkuQ0xJRU5UX1NFQ1JFVAogICAgICAgICAgICAgIH0=`, - }, - }); - const data: InsightlyOAuthResponse = res.data; - await this.prisma.connections.update({ - where: { - id_connection: connectionId, - }, - data: { - access_token: this.cryptoService.encrypt(data.access_token), - refresh_token: this.cryptoService.encrypt(data.refresh_token), - expiration_timestamp: new Date( - new Date().getTime() + Number(data.expires_at) * 1000, - ), - }, - }); - this.logger.log('OAuth credentials updated : insightly '); - } catch (error) { - handleServiceError(error, this.logger, 'insightly', Action.oauthRefresh); - } - } -} diff --git a/packages/api/src/@core/connections/crm/services/sugarcrm/sugarcrm.service.ts b/packages/api/src/@core/connections/crm/services/sugarcrm/sugarcrm.service.ts deleted file mode 100644 index 37dc5c191..000000000 --- a/packages/api/src/@core/connections/crm/services/sugarcrm/sugarcrm.service.ts +++ /dev/null @@ -1,187 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import axios from 'axios'; -import { PrismaService } from '@@core/prisma/prisma.service'; -import { Action, handleServiceError } from '@@core/utils/errors'; -import { LoggerService } from '@@core/logger/logger.service'; -import { v4 as uuidv4 } from 'uuid'; -import { EnvironmentService } from '@@core/environment/environment.service'; -import { EncryptionService } from '@@core/encryption/encryption.service'; -import { - CallbackParams, - RefreshParams, - ICrmConnectionService, -} from '../../types'; -import { ServiceRegistry } from '../registry.service'; -import { - OAuth2AuthData, - providersConfig, - providerToType, -} from '@panora/shared'; -import { AuthStrategy } from '@panora/shared'; -import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service'; - -export type SugarcrmOAuthResponse = { - access_token: string; - expires_in: number; - token_type: string; - scope: string; - refresh_token: string; - refresh_expires_in: number; - download_token: string; -}; - -@Injectable() -export class SugarcrmConnectionService implements ICrmConnectionService { - private readonly type: string; - - constructor( - private prisma: PrismaService, - private logger: LoggerService, - private env: EnvironmentService, - private cryptoService: EncryptionService, - private registry: ServiceRegistry, - private cService: ConnectionsStrategiesService, - ) { - this.logger.setContext(SugarcrmConnectionService.name); - this.registry.registerService('sugarcrm', this); - this.type = providerToType('sugarcrm', 'crm', AuthStrategy.oauth2); - } - - async handleCallback(opts: CallbackParams) { - try { - const { linkedUserId, projectId, code } = opts; - const isNotUnique = await this.prisma.connections.findFirst({ - where: { - id_linked_user: linkedUserId, - provider_slug: `sugarcrm`, - vertical: 'crm', - }, - }); - - //reconstruct the redirect URI that was passed in the githubend it must be the same - const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; - const CREDENTIALS = (await this.cService.getCredentials( - projectId, - this.type, - )) as OAuth2AuthData; - - const formData = new URLSearchParams({ - client_id: CREDENTIALS.CLIENT_ID, - client_secret: CREDENTIALS.CLIENT_SECRET, - grant_type: 'password', - username: '', - password: '', - platform: 'custom', - }); - //const subdomain = 'panora'; - const res = await axios.post( - `${CREDENTIALS.SUBDOMAIN}/rest/v11/oauth2/token`, - formData.toString(), - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', - }, - }, - ); - const data: SugarcrmOAuthResponse = res.data; - this.logger.log( - 'OAuth credentials : sugarcrm ticketing ' + JSON.stringify(data), - ); - - let db_res; - const connection_token = uuidv4(); - //get the right BASE URL API - const BASE_API_URL = - CREDENTIALS.SUBDOMAIN + providersConfig['crm']['sugarcrm'].apiUrl; - - if (isNotUnique) { - db_res = await this.prisma.connections.update({ - where: { - id_connection: isNotUnique.id_connection, - }, - data: { - access_token: this.cryptoService.encrypt(data.access_token), - refresh_token: this.cryptoService.encrypt(data.refresh_token), - account_url: BASE_API_URL, - expiration_timestamp: new Date( - new Date().getTime() + Number(data.expires_in) * 1000, - ), - status: 'valid', - created_at: new Date(), - }, - }); - } else { - db_res = await this.prisma.connections.create({ - data: { - id_connection: uuidv4(), - connection_token: connection_token, - provider_slug: 'sugarcrm', - vertical: 'crm', - token_type: 'oauth', - account_url: BASE_API_URL, - access_token: this.cryptoService.encrypt(data.access_token), - refresh_token: this.cryptoService.encrypt(data.refresh_token), - expiration_timestamp: new Date( - new Date().getTime() + Number(data.expires_in) * 1000, - ), - status: 'valid', - created_at: new Date(), - projects: { - connect: { id_project: projectId }, - }, - linked_users: { - connect: { id_linked_user: linkedUserId }, - }, - }, - }); - } - return db_res; - } catch (error) { - handleServiceError(error, this.logger, 'sugarcrm', Action.oauthCallback); - } - } - - async handleTokenRefresh(opts: RefreshParams) { - try { - const { connectionId, refreshToken, projectId } = opts; - const CREDENTIALS = (await this.cService.getCredentials( - projectId, - this.type, - )) as OAuth2AuthData; - - const formData = new URLSearchParams({ - client_id: CREDENTIALS.CLIENT_ID, - client_secret: CREDENTIALS.CLIENT_SECRET, - grant_type: 'refresh_token', - platform: 'custom', - refresh_token: this.cryptoService.decrypt(refreshToken), - }); - //const subdomain = 'panora'; - const res = await axios.post( - `${CREDENTIALS.SUBDOMAIN}/rest/v11/oauth2/token`, - formData.toString(), - { - headers: { - 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', - }, - }, - ); - const data: SugarcrmOAuthResponse = res.data; - await this.prisma.connections.update({ - where: { - id_connection: connectionId, - }, - data: { - access_token: this.cryptoService.encrypt(data.access_token), - refresh_token: this.cryptoService.encrypt(data.refresh_token), - expiration_timestamp: new Date( - new Date().getTime() + Number(data.expires_in) * 1000, - ), - }, - }); - this.logger.log('OAuth credentials updated : sugarcrm '); - } catch (error) { - handleServiceError(error, this.logger, 'sugarcrm', Action.oauthRefresh); - } - } -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 86b053edb..3937b5d3c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -511,6 +511,9 @@ importers: dotenv: specifier: ^16.3.1 version: 16.4.5 + randomstring: + specifier: ^1.3.0 + version: 1.3.0 devDependencies: '@nestjs/common': specifier: ^10.0.0 @@ -10863,12 +10866,23 @@ packages: engines: {node: '>=10'} dev: false + /randombytes@2.0.3: + resolution: {integrity: sha512-lDVjxQQFoCG1jcrP06LNo2lbWp4QTShEXnhActFBwYuHprllQV6VUpwreApsYqCgD+N1mHoqJ/BI/4eV4R2GYg==} + dev: false + /randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} dependencies: safe-buffer: 5.2.1 dev: true + /randomstring@1.3.0: + resolution: {integrity: sha512-gY7aQ4i1BgwZ8I1Op4YseITAyiDiajeZOPQUbIq9TPGPhUm5FX59izIaOpmKbME1nmnEiABf28d9K2VSii6BBg==} + hasBin: true + dependencies: + randombytes: 2.0.3 + dev: false + /range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'}