From 28724be39bd84ef6b861dfec28bbdd742ac757f8 Mon Sep 17 00:00:00 2001 From: nael Date: Wed, 20 Dec 2023 14:47:22 +0100 Subject: [PATCH] :sparkles: Reworked env in server --- packages/api/package.json | 2 + .../@core/connections/connections.module.ts | 1 - .../connections/crm/crm-connection.module.ts | 4 + .../crm/services/hubspot/hubspot.service.ts | 43 +++---- .../services/pipedrive/pipedrive.service.ts | 43 ++++--- .../crm/services/zendesk/zendesk.service.ts | 45 ++++--- .../crm/services/zoho/zoho.service.ts | 45 ++++--- packages/api/src/@core/core.module.ts | 5 + .../@core/encryption/encryption.service.ts | 47 +++++++ .../environment/environement.validation.ts | 72 +++++++++++ .../@core/environment/environment.module.ts | 19 +++ .../@core/environment/environment.service.ts | 65 ++++++++++ .../field-mapping/field-mapping.module.ts | 8 +- .../field-mapping/field-mapping.service.ts | 12 +- .../@core/passthrough/passthrough.module.ts | 8 +- .../@core/passthrough/passthrough.service.ts | 12 +- packages/api/src/@core/tasks/tasks.service.ts | 3 + packages/api/src/@core/utils/config.ts | 20 --- packages/api/src/@core/utils/crypto.ts | 41 ------ packages/api/src/app.module.ts | 7 +- packages/api/src/app.service.ts | 3 +- .../api/src/crm/contact/contact.module.ts | 2 + .../crm/contact/services/freshsales/index.ts | 16 ++- .../src/crm/contact/services/hubspot/index.ts | 16 ++- .../crm/contact/services/pipedrive/index.ts | 16 ++- .../src/crm/contact/services/zendesk/index.ts | 16 ++- .../src/crm/contact/services/zoho/index.ts | 12 +- packages/api/src/main.ts | 4 + packages/api/swagger/swagger-spec.json | 5 +- pnpm-lock.yaml | 118 +++++++++--------- 30 files changed, 477 insertions(+), 233 deletions(-) create mode 100644 packages/api/src/@core/encryption/encryption.service.ts create mode 100644 packages/api/src/@core/environment/environement.validation.ts create mode 100644 packages/api/src/@core/environment/environment.module.ts create mode 100644 packages/api/src/@core/environment/environment.service.ts delete mode 100644 packages/api/src/@core/utils/config.ts delete mode 100644 packages/api/src/@core/utils/crypto.ts diff --git a/packages/api/package.json b/packages/api/package.json index adb8066dd..a36a41cf8 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -42,6 +42,8 @@ "axios": "^1.5.1", "bcrypt": "^5.1.1", "bull": "^4.11.5", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.0", "crypto": "^1.0.1", "dotenv": "^16.3.1", "install": "^0.13.0", diff --git a/packages/api/src/@core/connections/connections.module.ts b/packages/api/src/@core/connections/connections.module.ts index c7da12c35..437919282 100644 --- a/packages/api/src/@core/connections/connections.module.ts +++ b/packages/api/src/@core/connections/connections.module.ts @@ -3,7 +3,6 @@ import { CrmConnectionModule } from './crm/crm-connection.module'; import { ConnectionsController } from './connections.controller'; import { LoggerService } from '@@core/logger/logger.service'; import { PrismaService } from '@@core/prisma/prisma.service'; -import { WebhookService } from '@@core/webhook/webhook.service'; @Module({ controllers: [ConnectionsController], diff --git a/packages/api/src/@core/connections/crm/crm-connection.module.ts b/packages/api/src/@core/connections/crm/crm-connection.module.ts index 7b8e36b4f..e02b8b192 100644 --- a/packages/api/src/@core/connections/crm/crm-connection.module.ts +++ b/packages/api/src/@core/connections/crm/crm-connection.module.ts @@ -9,6 +9,8 @@ import { ZohoConnectionService } from './services/zoho/zoho.service'; import { LoggerService } from '@@core/logger/logger.service'; import { WebhookService } from '@@core/webhook/webhook.service'; import { WebhookModule } from '@@core/webhook/webhook.module'; +import { EnvironmentService } from '@@core/environment/environment.service'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Module({ imports: [WebhookModule], @@ -22,6 +24,8 @@ import { WebhookModule } from '@@core/webhook/webhook.module'; ZohoConnectionService, LoggerService, WebhookService, + EnvironmentService, + EncryptionService, ], exports: [CrmConnectionsService], }) diff --git a/packages/api/src/@core/connections/crm/services/hubspot/hubspot.service.ts b/packages/api/src/@core/connections/crm/services/hubspot/hubspot.service.ts index 8028906e5..562265329 100644 --- a/packages/api/src/@core/connections/crm/services/hubspot/hubspot.service.ts +++ b/packages/api/src/@core/connections/crm/services/hubspot/hubspot.service.ts @@ -1,20 +1,21 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from '@@core/prisma/prisma.service'; import axios from 'axios'; -import config from '@@core/utils/config'; import { HubspotOAuthResponse } from '../../types'; import { LoggerService } from '@@core/logger/logger.service'; -import { - Action, - NotUniqueRecord, - handleServiceError, -} from '@@core/utils/errors'; +import { Action, handleServiceError } from '@@core/utils/errors'; import { v4 as uuidv4 } from 'uuid'; -import { decrypt, encrypt } from '@@core/utils/crypto'; +import { EnvironmentService } from '@@core/environment/environment.service'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class HubspotConnectionService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private env: EnvironmentService, + private cryptoService: EncryptionService, + ) { this.logger.setContext(HubspotConnectionService.name); } @@ -36,11 +37,11 @@ export class HubspotConnectionService { if (isNotUnique) return; //reconstruct the redirect URI that was passed in the frontend it must be the same - const REDIRECT_URI = `${config.OAUTH_REDIRECT_BASE}/connections/oauth/callback`; + const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; const formData = new URLSearchParams({ grant_type: 'authorization_code', - client_id: config.HUBSPOT_CLIENT_ID, - client_secret: config.HUBSPOT_CLIENT_SECRET, + client_id: this.env.getHubspotAuth().CLIENT_ID, + client_secret: this.env.getHubspotAuth().CLIENT_SECRET, redirect_uri: REDIRECT_URI, code: code, }); @@ -63,8 +64,8 @@ export class HubspotConnectionService { id_connection: isNotUnique.id_connection, }, data: { - access_token: encrypt(data.access_token), - refresh_token: encrypt(data.refresh_token), + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: this.cryptoService.encrypt(data.refresh_token), expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), @@ -79,8 +80,8 @@ export class HubspotConnectionService { id_connection: uuidv4(), provider_slug: 'hubspot', token_type: 'oauth', - access_token: encrypt(data.access_token), - refresh_token: encrypt(data.refresh_token), + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: this.cryptoService.encrypt(data.refresh_token), expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), @@ -104,13 +105,13 @@ export class HubspotConnectionService { async handleHubspotTokenRefresh(connectionId: string, refresh_token: string) { try { - const REDIRECT_URI = `${config.OAUTH_REDIRECT_BASE}/connections/oauth/callback`; //tocheck + const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; //tocheck const formData = new URLSearchParams({ grant_type: 'refresh_token', - client_id: config.HUBSPOT_CLIENT_ID, - client_secret: config.HUBSPOT_CLIENT_SECRET, + client_id: this.env.getHubspotAuth().CLIENT_ID, + client_secret: this.env.getHubspotAuth().CLIENT_SECRET, redirect_uri: REDIRECT_URI, - refresh_token: decrypt(refresh_token), + refresh_token: this.cryptoService.decrypt(refresh_token), }); const res = await axios.post( 'https://api.hubapi.com/oauth/v1/token', @@ -127,8 +128,8 @@ export class HubspotConnectionService { id_connection: connectionId, }, data: { - access_token: encrypt(data.access_token), - refresh_token: encrypt(data.refresh_token), + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: this.cryptoService.encrypt(data.refresh_token), expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), diff --git a/packages/api/src/@core/connections/crm/services/pipedrive/pipedrive.service.ts b/packages/api/src/@core/connections/crm/services/pipedrive/pipedrive.service.ts index edc726889..d2c0c4c89 100644 --- a/packages/api/src/@core/connections/crm/services/pipedrive/pipedrive.service.ts +++ b/packages/api/src/@core/connections/crm/services/pipedrive/pipedrive.service.ts @@ -1,20 +1,21 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from '@@core/prisma/prisma.service'; import axios from 'axios'; -import config from '@@core/utils/config'; import { PipeDriveOAuthResponse } from '../../types'; -import { - Action, - NotUniqueRecord, - handleServiceError, -} from '@@core/utils/errors'; +import { Action, handleServiceError } from '@@core/utils/errors'; import { LoggerService } from '@@core/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; -import { decrypt, encrypt } from '@@core/utils/crypto'; +import { EnvironmentService } from '@@core/environment/environment.service'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class PipedriveConnectionService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private env: EnvironmentService, + private cryptoService: EncryptionService, + ) { this.logger.setContext(PipedriveConnectionService.name); } @@ -32,7 +33,7 @@ export class PipedriveConnectionService { }); //reconstruct the redirect URI that was passed in the frontend it must be the same - const REDIRECT_URI = `${config.OAUTH_REDIRECT_BASE}/connections/oauth/callback`; + const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; const formData = new URLSearchParams({ grant_type: 'authorization_code', @@ -46,7 +47,9 @@ export class PipedriveConnectionService { headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', Authorization: `Basic ${Buffer.from( - `${config.PIPEDRIVE_CLIENT_ID}:${config.PIPEDRIVE_CLIENT_SECRET}`, + `${this.env.getPipedriveSecret().CLIENT_ID}:${ + this.env.getPipedriveSecret().CLIENT_SECRET + }`, ).toString('base64')}`, }, }, @@ -61,8 +64,8 @@ export class PipedriveConnectionService { id_connection: uuidv4(), provider_slug: 'pipedrive', token_type: 'oauth', - access_token: encrypt(data.access_token), - refresh_token: encrypt(data.refresh_token), + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: this.cryptoService.encrypt(data.refresh_token), expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), @@ -76,8 +79,8 @@ export class PipedriveConnectionService { }, }, update: { - access_token: encrypt(data.access_token), - refresh_token: encrypt(data.refresh_token), + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: this.cryptoService.encrypt(data.refresh_token), expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), @@ -96,12 +99,12 @@ export class PipedriveConnectionService { refresh_token: string, ) { try { - const REDIRECT_URI = `${config.OAUTH_REDIRECT_BASE}/connections/oauth/callback`; + const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; const formData = new URLSearchParams({ grant_type: 'refresh_token', redirect_uri: REDIRECT_URI, - refresh_token: decrypt(refresh_token), + refresh_token: this.cryptoService.decrypt(refresh_token), }); const res = await axios.post( 'https://oauth.pipedrive.com/oauth/token', @@ -110,7 +113,9 @@ export class PipedriveConnectionService { headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', Authorization: `Basic ${Buffer.from( - `${config.PIPEDRIVE_CLIENT_ID}:${config.PIPEDRIVE_CLIENT_SECRET}`, + `${this.env.getPipedriveSecret().CLIENT_ID}:${ + this.env.getPipedriveSecret().CLIENT_SECRET + }`, ).toString('base64')}`, }, }, @@ -121,8 +126,8 @@ export class PipedriveConnectionService { id_connection: connectionId, }, data: { - access_token: encrypt(data.access_token), - refresh_token: encrypt(data.refresh_token), + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: this.cryptoService.encrypt(data.refresh_token), expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), diff --git a/packages/api/src/@core/connections/crm/services/zendesk/zendesk.service.ts b/packages/api/src/@core/connections/crm/services/zendesk/zendesk.service.ts index cfd08c8d3..c66ea50d2 100644 --- a/packages/api/src/@core/connections/crm/services/zendesk/zendesk.service.ts +++ b/packages/api/src/@core/connections/crm/services/zendesk/zendesk.service.ts @@ -1,20 +1,21 @@ import { Injectable } from '@nestjs/common'; import axios from 'axios'; -import config from '@@core/utils/config'; import { PrismaService } from '@@core/prisma/prisma.service'; import { ZendeskOAuthResponse } from '../../types'; -import { - Action, - NotUniqueRecord, - handleServiceError, -} from '@@core/utils/errors'; +import { Action, handleServiceError } from '@@core/utils/errors'; import { LoggerService } from '@@core/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; -import { decrypt, encrypt } from '@@core/utils/crypto'; +import { EnvironmentService } from '@@core/environment/environment.service'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class ZendeskConnectionService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private env: EnvironmentService, + private cryptoService: EncryptionService, + ) { this.logger.setContext(ZendeskConnectionService.name); } async handleZendeskCallback( @@ -31,7 +32,7 @@ export class ZendeskConnectionService { }); //reconstruct the redirect URI that was passed in the frontend it must be the same - const REDIRECT_URI = `${config.OAUTH_REDIRECT_BASE}/connections/oauth/callback`; + const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; const formData = new URLSearchParams({ grant_type: 'authorization_code', @@ -45,7 +46,9 @@ export class ZendeskConnectionService { headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', Authorization: `Basic ${Buffer.from( - `${config.ZENDESK_CLIENT_ID}:${config.ZENDESK_CLIENT_SECRET}`, + `${this.env.getZendeskSecret().CLIENT_ID}:${ + this.env.getZendeskSecret().CLIENT_SECRET + }`, ).toString('base64')}`, }, }, @@ -61,8 +64,10 @@ export class ZendeskConnectionService { id_connection: uuidv4(), provider_slug: 'zendesk', token_type: 'oauth', - access_token: encrypt(data.access_token), - refresh_token: data.refresh_token ? encrypt(data.refresh_token) : '', + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: data.refresh_token + ? this.cryptoService.encrypt(data.refresh_token) + : '', expiration_timestamp: data.expires_in ? new Date(new Date().getTime() + data.expires_in * 1000) : new Date(), @@ -76,8 +81,10 @@ export class ZendeskConnectionService { }, }, update: { - access_token: encrypt(data.access_token), - refresh_token: data.refresh_token ? encrypt(data.refresh_token) : '', + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: data.refresh_token + ? this.cryptoService.encrypt(data.refresh_token) + : '', expiration_timestamp: data.expires_in ? new Date(new Date().getTime() + data.expires_in * 1000) : new Date(), @@ -94,7 +101,7 @@ export class ZendeskConnectionService { try { const formData = new URLSearchParams({ grant_type: 'refresh_token', - refresh_token: decrypt(refresh_token), + refresh_token: this.cryptoService.decrypt(refresh_token), }); const res = await axios.post( 'https://api.getbase.com/oauth2/token', @@ -103,7 +110,9 @@ export class ZendeskConnectionService { headers: { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8', Authorization: `Basic ${Buffer.from( - `${config.ZENDESK_CLIENT_ID}:${config.ZENDESK_CLIENT_SECRET}`, + `${this.env.getZendeskSecret().CLIENT_ID}:${ + this.env.getZendeskSecret().CLIENT_SECRET + }`, ).toString('base64')}`, }, }, @@ -114,8 +123,8 @@ export class ZendeskConnectionService { id_connection: connectionId, }, data: { - access_token: encrypt(data.access_token), - refresh_token: encrypt(data.refresh_token), + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: this.cryptoService.encrypt(data.refresh_token), expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), diff --git a/packages/api/src/@core/connections/crm/services/zoho/zoho.service.ts b/packages/api/src/@core/connections/crm/services/zoho/zoho.service.ts index 5d035247e..55eb9b96f 100644 --- a/packages/api/src/@core/connections/crm/services/zoho/zoho.service.ts +++ b/packages/api/src/@core/connections/crm/services/zoho/zoho.service.ts @@ -1,16 +1,12 @@ import { Injectable } from '@nestjs/common'; import axios from 'axios'; -import config from '@@core/utils/config'; import { PrismaService } from '@@core/prisma/prisma.service'; import { ZohoOAuthResponse } from '../../types'; import { LoggerService } from '@@core/logger/logger.service'; -import { - Action, - NotUniqueRecord, - handleServiceError, -} from '@@core/utils/errors'; +import { Action, handleServiceError } from '@@core/utils/errors'; import { v4 as uuidv4 } from 'uuid'; -import { decrypt, encrypt } from '@@core/utils/crypto'; +import { EnvironmentService } from '@@core/environment/environment.service'; +import { EncryptionService } from '@@core/encryption/encryption.service'; const ZOHOLocations = { us: 'https://accounts.zoho.com', @@ -21,7 +17,12 @@ const ZOHOLocations = { }; @Injectable() export class ZohoConnectionService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private env: EnvironmentService, + private cryptoService: EncryptionService, + ) { this.logger.setContext(ZohoConnectionService.name); } async handleZohoCallback( @@ -39,12 +40,12 @@ export class ZohoConnectionService { }); //reconstruct the redirect URI that was passed in the frontend it must be the same - const REDIRECT_URI = `${config.OAUTH_REDIRECT_BASE}/connections/oauth/callback`; + const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; const formData = new URLSearchParams({ grant_type: 'authorization_code', - client_id: config.ZOHOCRM_CLIENT_ID, - client_secret: config.ZOHOCRM_CLIENT_SECRET, + client_id: this.env.getZohoSecret().CLIENT_ID, + client_secret: this.env.getZohoSecret().CLIENT_SECRET, redirect_uri: REDIRECT_URI, code: code, }); @@ -69,8 +70,10 @@ export class ZohoConnectionService { id_connection: uuidv4(), provider_slug: 'zoho', token_type: 'oauth', - access_token: encrypt(data.access_token), - refresh_token: data.refresh_token ? encrypt(data.refresh_token) : '', + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: data.refresh_token + ? this.cryptoService.encrypt(data.refresh_token) + : '', expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), @@ -85,8 +88,10 @@ export class ZohoConnectionService { account_url: domain, }, update: { - access_token: encrypt(data.access_token), - refresh_token: data.refresh_token ? encrypt(data.refresh_token) : '', + access_token: this.cryptoService.encrypt(data.access_token), + refresh_token: data.refresh_token + ? this.cryptoService.encrypt(data.refresh_token) + : '', expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), @@ -106,13 +111,13 @@ export class ZohoConnectionService { domain: string, ) { try { - const REDIRECT_URI = `${config.OAUTH_REDIRECT_BASE}/connections/oauth/callback`; + const REDIRECT_URI = `${this.env.getOAuthRredirectBaseUrl()}/connections/oauth/callback`; const formData = new URLSearchParams({ grant_type: 'refresh_token', - client_id: config.ZOHOCRM_CLIENT_ID, - client_secret: config.ZOHOCRM_CLIENT_SECRET, + client_id: this.env.getZohoSecret().CLIENT_ID, + client_secret: this.env.getZohoSecret().CLIENT_SECRET, redirect_uri: REDIRECT_URI, - refresh_token: decrypt(refresh_token), + refresh_token: this.cryptoService.decrypt(refresh_token), }); const res = await axios.post( @@ -130,7 +135,7 @@ export class ZohoConnectionService { id_connection: connectionId, }, data: { - access_token: encrypt(data.access_token), + access_token: this.cryptoService.encrypt(data.access_token), expiration_timestamp: new Date( new Date().getTime() + data.expires_in * 1000, ), diff --git a/packages/api/src/@core/core.module.ts b/packages/api/src/@core/core.module.ts index d7fbdcda8..4ed982981 100644 --- a/packages/api/src/@core/core.module.ts +++ b/packages/api/src/@core/core.module.ts @@ -9,6 +9,8 @@ import { EventsModule } from './events/events.module'; import { MagicLinkModule } from './magic-link/magic-link.module'; import { PassthroughModule } from './passthrough/passthrough.module'; import { WebhookModule } from './webhook/webhook.module'; +import { EnvironmentModule } from './environment/environment.module'; +import { EncryptionService } from './encryption/encryption.service'; @Module({ imports: [ @@ -22,6 +24,7 @@ import { WebhookModule } from './webhook/webhook.module'; MagicLinkModule, PassthroughModule, WebhookModule, + EnvironmentModule, ], exports: [ AuthModule, @@ -34,6 +37,8 @@ import { WebhookModule } from './webhook/webhook.module'; MagicLinkModule, PassthroughModule, WebhookModule, + EnvironmentModule, ], + providers: [EncryptionService], }) export class CoreModule {} diff --git a/packages/api/src/@core/encryption/encryption.service.ts b/packages/api/src/@core/encryption/encryption.service.ts new file mode 100644 index 000000000..1707b7a2a --- /dev/null +++ b/packages/api/src/@core/encryption/encryption.service.ts @@ -0,0 +1,47 @@ +import { EnvironmentService } from '@@core/environment/environment.service'; +import { Injectable } from '@nestjs/common'; +import * as crypto from 'crypto'; + +@Injectable() +export class EncryptionService { + private secretKey: string; + private iv = crypto.randomBytes(16); + + constructor(private env: EnvironmentService) { + this.secretKey = this.env.getCryptoKey(); + } + + encrypt(data: string): string { + try { + const cipher = crypto.createCipheriv( + 'aes-256-cbc', + Buffer.from(this.secretKey, 'utf-8'), + this.iv, + ); + let encrypted = cipher.update(data, 'utf8', 'hex'); + encrypted += cipher.final('hex'); + const encryptedWithIv = this.iv.toString('hex') + ':' + encrypted; + return encryptedWithIv; + } catch (error) { + throw new Error('Encrypting error... ' + error); + } + } + + decrypt(encryptedData: string): string { + try { + const textParts = encryptedData.split(':'); + const ivFromText = Buffer.from(textParts.shift() as string, 'hex'); + const encryptedText = textParts.join(':'); + const decipher = crypto.createDecipheriv( + 'aes-256-cbc', + Buffer.from(this.secretKey), + ivFromText, + ); + let decrypted = decipher.update(encryptedText, 'hex', 'utf8'); + decrypted += decipher.final('utf8'); + return decrypted; + } catch (error) { + throw new Error('Decrypting error... ' + error); + } + } +} diff --git a/packages/api/src/@core/environment/environement.validation.ts b/packages/api/src/@core/environment/environement.validation.ts new file mode 100644 index 000000000..f36c87461 --- /dev/null +++ b/packages/api/src/@core/environment/environement.validation.ts @@ -0,0 +1,72 @@ +import { plainToClass } from 'class-transformer'; +import { IsOptional, IsString, validateSync } from 'class-validator'; + +export class EnvVars { + @IsString() + @IsOptional() + ENV?: string; + + @IsString() + @IsOptional() + DISTRIBUTION?: string; + + @IsString() + DATABASE_URL: string; + + @IsString() + JWT_SECRET: string; + + @IsString() + @IsOptional() + SENTRY_DSN?: string; + + //CRM + @IsString() + HUBSPOT_CLIENT_ID: string; + + @IsString() + HUBSPOT_CLIENT_SECRET: string; + + @IsString() + ZOHOCRM_CLIENT_ID: string; + + @IsString() + ZOHOCRM_CLIENT_SECRET: string; + + @IsString() + PIPEDRIVE_CLIENT_ID: string; + + @IsString() + PIPEDRIVE_CLIENT_SECRET: string; + + @IsString() + FRESHSALES_CLIENT_ID: string; + + @IsString() + FRESHSALES_CLIENT_SECRET: string; + + @IsString() + ZENDESK_CLIENT_ID: string; + + @IsString() + ZENDESK_CLIENT_SECRET: string; + + @IsString() + OAUTH_REDIRECT_BASE: string; + + @IsString() + ENCRYPT_CRYPTO_SECRET_KEY: string; + + @IsString() + REDIS_HOST: string; +} + +export const validate = (config: Record) => { + const validatedConfig = plainToClass(EnvVars, config); + + const errors = validateSync(validatedConfig); + + if (errors.length) throw new Error(errors.toString()); + + return validatedConfig; +}; diff --git a/packages/api/src/@core/environment/environment.module.ts b/packages/api/src/@core/environment/environment.module.ts new file mode 100644 index 000000000..d17150d0a --- /dev/null +++ b/packages/api/src/@core/environment/environment.module.ts @@ -0,0 +1,19 @@ +import { Global, Module } from '@nestjs/common'; +import { ConfigModule } from '@nestjs/config'; + +import { EnvironmentService } from './environment.service'; +import { validate } from './environement.validation'; + +@Global() +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + expandVariables: true, + validate, + }), + ], + providers: [EnvironmentService], + exports: [EnvironmentService], +}) +export class EnvironmentModule {} diff --git a/packages/api/src/@core/environment/environment.service.ts b/packages/api/src/@core/environment/environment.service.ts new file mode 100644 index 000000000..0205834ce --- /dev/null +++ b/packages/api/src/@core/environment/environment.service.ts @@ -0,0 +1,65 @@ +import { Injectable } from '@nestjs/common'; +import { ConfigService } from '@nestjs/config'; + +export type OAuth = { + CLIENT_ID: string; + CLIENT_SECRET: string; +}; + +@Injectable() +export class EnvironmentService { + constructor(private configService: ConfigService) {} + + getEnvMode(): string { + return this.configService.get('ENV'); + } + getSentryDsn(): string { + return this.configService.get('SENTRY_DSN'); + } + getDistributionMode(): string { + return this.configService.get('DISTRIBUTION'); + } + getDatabaseURL(): string { + return this.configService.get('DATABASE_URL'); + } + getOAuthRredirectBaseUrl(): string { + return this.configService.get('OAUTH_REDIRECT_BASE'); + } + getRedisHost(): string { + return this.configService.get('REDIS_HOST'); + } + + getCryptoKey(): string { + return this.configService.get('ENCRYPT_CRYPTO_SECRET_KEY'); + } + getHubspotAuth(): OAuth { + return { + CLIENT_ID: this.configService.get('HUBSPOT_CLIENT_ID'), + CLIENT_SECRET: this.configService.get('HUBSPOT_CLIENT_SECRET'), + }; + } + getZohoSecret(): OAuth { + return { + CLIENT_ID: this.configService.get('ZOHO_CLIENT_ID'), + CLIENT_SECRET: this.configService.get('ZOHO_CLIENT_SECRET'), + }; + } + getZendeskSecret(): OAuth { + return { + CLIENT_ID: this.configService.get('ZENDESK_CLIENT_ID'), + CLIENT_SECRET: this.configService.get('ZENDESK_CLIENT_SECRET'), + }; + } + getFreshsalesSecret(): OAuth { + return { + CLIENT_ID: this.configService.get('FRESHSALES_CLIENT_ID'), + CLIENT_SECRET: this.configService.get('FRESHSALES_CLIENT_SECRET'), + }; + } + getPipedriveSecret(): OAuth { + return { + CLIENT_ID: this.configService.get('PIPEDRIVE_CLIENT_ID'), + CLIENT_SECRET: this.configService.get('PIPEDRIVE_CLIENT_SECRET'), + }; + } +} diff --git a/packages/api/src/@core/field-mapping/field-mapping.module.ts b/packages/api/src/@core/field-mapping/field-mapping.module.ts index 11d3ebc42..7b48699c4 100644 --- a/packages/api/src/@core/field-mapping/field-mapping.module.ts +++ b/packages/api/src/@core/field-mapping/field-mapping.module.ts @@ -3,9 +3,15 @@ import { FieldMappingService } from './field-mapping.service'; import { FieldMappingController } from './field-mapping.controller'; import { PrismaService } from '../prisma/prisma.service'; import { LoggerService } from '../logger/logger.service'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Module({ - providers: [FieldMappingService, PrismaService, LoggerService], + providers: [ + FieldMappingService, + PrismaService, + LoggerService, + EncryptionService, + ], controllers: [FieldMappingController], }) export class FieldMappingModule {} diff --git a/packages/api/src/@core/field-mapping/field-mapping.service.ts b/packages/api/src/@core/field-mapping/field-mapping.service.ts index f0579d509..eb74f3c0e 100644 --- a/packages/api/src/@core/field-mapping/field-mapping.service.ts +++ b/packages/api/src/@core/field-mapping/field-mapping.service.ts @@ -8,13 +8,17 @@ import { import { v4 as uuidv4 } from 'uuid'; import { customPropertiesUrls, getProviderVertical } from '../utils/types'; import axios from 'axios'; -import { decrypt } from '@@core/utils/crypto'; import { ActionType, handleServiceError } from '@@core/utils/errors'; import { CrmObject } from '@crm/@types'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class FieldMappingService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + ) { this.logger.setContext(FieldMappingService.name); } @@ -126,7 +130,9 @@ export class FieldMappingService { { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${decrypt(connection.access_token)}`, + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, }, }, ); diff --git a/packages/api/src/@core/passthrough/passthrough.module.ts b/packages/api/src/@core/passthrough/passthrough.module.ts index d3ff5006d..8f596a9a5 100644 --- a/packages/api/src/@core/passthrough/passthrough.module.ts +++ b/packages/api/src/@core/passthrough/passthrough.module.ts @@ -3,9 +3,15 @@ import { PassthroughService } from './passthrough.service'; import { PassthroughController } from './passthrough.controller'; import { LoggerService } from '@@core/logger/logger.service'; import { PrismaService } from '@@core/prisma/prisma.service'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Module({ - providers: [PassthroughService, LoggerService, PrismaService], + providers: [ + PassthroughService, + LoggerService, + PrismaService, + EncryptionService, + ], controllers: [PassthroughController], }) export class PassthroughModule {} diff --git a/packages/api/src/@core/passthrough/passthrough.service.ts b/packages/api/src/@core/passthrough/passthrough.service.ts index a6889a197..76d7435aa 100644 --- a/packages/api/src/@core/passthrough/passthrough.service.ts +++ b/packages/api/src/@core/passthrough/passthrough.service.ts @@ -5,13 +5,17 @@ import { PassThroughResponse } from './types'; import axios, { AxiosResponse } from 'axios'; import { PrismaService } from '@@core/prisma/prisma.service'; import { v4 as uuidv4 } from 'uuid'; -import { decrypt } from '@@core/utils/crypto'; import { LoggerService } from '@@core/logger/logger.service'; import { handleServiceError } from '@@core/utils/errors'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class PassthroughService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + ) { this.logger.setContext(PassthroughService.name); } @@ -52,7 +56,9 @@ export class PassthroughService { headers: { ...headers, 'Content-Type': 'application/json', - Authorization: `Bearer ${decrypt(connection.access_token)}`, + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, }, }); diff --git a/packages/api/src/@core/tasks/tasks.service.ts b/packages/api/src/@core/tasks/tasks.service.ts index 293b07c20..19a67f793 100644 --- a/packages/api/src/@core/tasks/tasks.service.ts +++ b/packages/api/src/@core/tasks/tasks.service.ts @@ -3,12 +3,14 @@ import { Injectable, OnModuleInit } from '@nestjs/common'; import { Cron, CronExpression } from '@nestjs/schedule'; import { PrismaService } from '../prisma/prisma.service'; import { CrmConnectionsService } from '../connections/crm/services/crm-connection.service'; +import { LoggerService } from '@@core/logger/logger.service'; @Injectable() export class TasksService implements OnModuleInit { constructor( private prisma: PrismaService, private crmConnectionsService: CrmConnectionsService, + private logger: LoggerService, ) {} onModuleInit() { @@ -17,6 +19,7 @@ export class TasksService implements OnModuleInit { @Cron(CronExpression.EVERY_HOUR) async handleCron() { + this.logger.log('decrypting ??????'); // refresh all tokens that expire in less than 10 hours const tenHoursFromNow = new Date(); tenHoursFromNow.setHours(tenHoursFromNow.getHours() + 10); diff --git a/packages/api/src/@core/utils/config.ts b/packages/api/src/@core/utils/config.ts deleted file mode 100644 index 40b957e48..000000000 --- a/packages/api/src/@core/utils/config.ts +++ /dev/null @@ -1,20 +0,0 @@ -const config = { - HUBSPOT_CLIENT_ID: process.env.HUBSPOT_CLIENT_ID, - HUBSPOT_CLIENT_SECRET: process.env.HUBSPOT_CLIENT_SECRET, - ZOHOCRM_CLIENT_ID: process.env.ZOHOCRM_CLIENT_ID, - ZOHOCRM_CLIENT_SECRET: process.env.ZOHOCRM_CLIENT_SECRET, - PIPEDRIVE_CLIENT_ID: process.env.PIPEDRIVE_CLIENT_ID, - PIPEDRIVE_CLIENT_SECRET: process.env.PIPEDRIVE_CLIENT_SECRET, - FRESHSALES_CLIENT_ID: process.env.FRESHSALES_CLIENT_ID, - FRESHSALES_CLIENT_SECRET: process.env.FRESHSALES_CLIENT_SECRET, - ZENDESK_CLIENT_ID: process.env.ZENDESK_CLIENT_ID, - ZENDESK_CLIENT_SECRET: process.env.ZENDESK_CLIENT_SECRET, - OAUTH_REDIRECT_BASE: process.env.OAUTH_REDIRECT_BASE, - SENTRY_DSN: process.env.SENTRY_DSN, - NODE_ENV: process.env.ENV, - DISTRIBUTION: process.env.DISTRIBUTION, - ENCRYPT_CRYPTO_SECRET_KEY: process.env.ENCRYPT_CRYPTO_SECRET_KEY, - REDIS_HOST: process.env.REDIS_HOST, -}; - -export default config; diff --git a/packages/api/src/@core/utils/crypto.ts b/packages/api/src/@core/utils/crypto.ts deleted file mode 100644 index 95d297b96..000000000 --- a/packages/api/src/@core/utils/crypto.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as crypto from 'crypto'; -import config from './config'; - -const secretKey = config.ENCRYPT_CRYPTO_SECRET_KEY; -const iv = crypto.randomBytes(16); - -export function encrypt(data: string): string { - try { - const cipher = crypto.createCipheriv( - 'aes-256-cbc', - Buffer.from(secretKey, 'utf-8'), - iv, - ); - let encrypted = cipher.update(data, 'utf8', 'hex'); - encrypted += cipher.final('hex'); - const encryptedWithIv = iv.toString('hex') + ':' + encrypted; // Prepend IV to the encrypted data - return encryptedWithIv; - } catch (error) { - throw new Error('Encrypting error... ' + error); - } -} - -export function decrypt(encryptedData: string): string { - try { - const textParts = encryptedData.split(':'); - // Extract the IV from the first half of the value - const ivFromText = Buffer.from(textParts.shift() as string, 'hex'); - // Extract the encrypted text without the IV - const encryptedText = textParts.join(':'); - const decipher = crypto.createDecipheriv( - 'aes-256-cbc', - Buffer.from(secretKey), - ivFromText, - ); - let decrypted = decipher.update(encryptedText, 'hex', 'utf8'); - decrypted += decipher.final('utf8'); - return decrypted; - } catch (error) { - throw new Error('Decrypting error... ' + error); - } -} diff --git a/packages/api/src/app.module.ts b/packages/api/src/app.module.ts index 0e5f3d15e..7a81cda55 100644 --- a/packages/api/src/app.module.ts +++ b/packages/api/src/app.module.ts @@ -16,7 +16,6 @@ import { APP_INTERCEPTOR } from '@nestjs/core'; import { LoggerService } from '@@core/logger/logger.service'; import { CoreModule } from '@@core/core.module'; import { BullModule } from '@nestjs/bull'; -import config from '@@core/utils/config'; @Module({ imports: [ @@ -28,10 +27,10 @@ import config from '@@core/utils/config'; FileStorageModule, CrmModule, ConfigModule.forRoot({ isGlobal: true }), - ...(config.DISTRIBUTION === 'managed' + ...(process.env.DISTRIBUTION === 'managed' ? [ SentryModule.forRoot({ - dsn: config.SENTRY_DSN, + dsn: process.env.SENTRY_DSN, debug: true, environment: 'dev', release: 'some_release', @@ -55,7 +54,7 @@ import config from '@@core/utils/config'; }), BullModule.forRoot({ redis: { - host: config.REDIS_HOST, + host: process.env.REDIS_HOST, port: 6379, }, }), diff --git a/packages/api/src/app.service.ts b/packages/api/src/app.service.ts index 257ce8cde..0555c1ed3 100644 --- a/packages/api/src/app.service.ts +++ b/packages/api/src/app.service.ts @@ -1,8 +1,9 @@ +import { EnvironmentService } from '@@core/environment/environment.service'; import { Injectable } from '@nestjs/common'; @Injectable() export class AppService { getHello(): string { - return 'Hello You Are On The Panora API!'; + return `Hello You Are On The Panora API!`; } } diff --git a/packages/api/src/crm/contact/contact.module.ts b/packages/api/src/crm/contact/contact.module.ts index b52c495b1..66e03d3b3 100644 --- a/packages/api/src/crm/contact/contact.module.ts +++ b/packages/api/src/crm/contact/contact.module.ts @@ -12,6 +12,7 @@ import { FieldMappingService } from '@@core/field-mapping/field-mapping.service' import { SyncContactsService } from './sync/sync.service'; import { WebhookService } from '@@core/webhook/webhook.service'; import { BullModule } from '@nestjs/bull'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Module({ imports: [ @@ -32,6 +33,7 @@ import { BullModule } from '@nestjs/bull'; FieldMappingService, SyncContactsService, WebhookService, + EncryptionService, ], exports: [SyncContactsService], }) diff --git a/packages/api/src/crm/contact/services/freshsales/index.ts b/packages/api/src/crm/contact/services/freshsales/index.ts index 125fbb707..9e6e1fe07 100644 --- a/packages/api/src/crm/contact/services/freshsales/index.ts +++ b/packages/api/src/crm/contact/services/freshsales/index.ts @@ -10,11 +10,15 @@ import { import { PrismaService } from '@@core/prisma/prisma.service'; import { LoggerService } from '@@core/logger/logger.service'; import { ActionType, handleServiceError } from '@@core/utils/errors'; -import { decrypt } from '@@core/utils/crypto'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class FreshSalesService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + ) { this.logger.setContext( CrmObject.contact.toUpperCase() + ':' + FreshSalesService.name, ); @@ -38,7 +42,9 @@ export class FreshSalesService { JSON.stringify(dataBody), { headers: { - Authorization: `Token token=${decrypt(connection.access_token)}`, + Authorization: `Token token=${this.cryptoService.decrypt( + connection.access_token, + )}`, 'Content-Type': 'application/json', }, }, @@ -74,7 +80,9 @@ export class FreshSalesService { { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${decrypt(connection.access_token)}`, + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, }, }, ); diff --git a/packages/api/src/crm/contact/services/hubspot/index.ts b/packages/api/src/crm/contact/services/hubspot/index.ts index 6aec39a27..fe0e4ff75 100644 --- a/packages/api/src/crm/contact/services/hubspot/index.ts +++ b/packages/api/src/crm/contact/services/hubspot/index.ts @@ -10,11 +10,15 @@ import axios from 'axios'; import { PrismaService } from '@@core/prisma/prisma.service'; import { LoggerService } from '@@core/logger/logger.service'; import { ActionType, handleServiceError } from '@@core/utils/errors'; -import { decrypt } from '@@core/utils/crypto'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class HubspotService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + ) { this.logger.setContext( CrmObject.contact.toUpperCase() + ':' + HubspotService.name, ); @@ -40,7 +44,9 @@ export class HubspotService { { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${decrypt(connection.access_token)}`, + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, }, }, ); @@ -87,7 +93,9 @@ export class HubspotService { const resp = await axios.get(url, { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${decrypt(connection.access_token)}`, + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, }, }); this.logger.log(`Synced hubspot contacts !`); diff --git a/packages/api/src/crm/contact/services/pipedrive/index.ts b/packages/api/src/crm/contact/services/pipedrive/index.ts index 9aed8545b..45811429b 100644 --- a/packages/api/src/crm/contact/services/pipedrive/index.ts +++ b/packages/api/src/crm/contact/services/pipedrive/index.ts @@ -9,11 +9,15 @@ import axios from 'axios'; import { PrismaService } from '@@core/prisma/prisma.service'; import { LoggerService } from '@@core/logger/logger.service'; import { ActionType, handleServiceError } from '@@core/utils/errors'; -import { decrypt } from '@@core/utils/crypto'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class PipedriveService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + ) { this.logger.setContext( CrmObject.contact.toUpperCase() + ':' + PipedriveService.name, ); @@ -37,7 +41,9 @@ export class PipedriveService { { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${decrypt(connection.access_token)}`, + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, }, }, ); @@ -72,7 +78,9 @@ export class PipedriveService { const resp = await axios.get(`https://api.pipedrive.com/v1/persons`, { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${decrypt(connection.access_token)}`, + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, }, }); diff --git a/packages/api/src/crm/contact/services/zendesk/index.ts b/packages/api/src/crm/contact/services/zendesk/index.ts index 4ae755ce8..d53f76695 100644 --- a/packages/api/src/crm/contact/services/zendesk/index.ts +++ b/packages/api/src/crm/contact/services/zendesk/index.ts @@ -9,10 +9,14 @@ import axios from 'axios'; import { LoggerService } from '@@core/logger/logger.service'; import { PrismaService } from '@@core/prisma/prisma.service'; import { ActionType, handleServiceError } from '@@core/utils/errors'; -import { decrypt } from '@@core/utils/crypto'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class ZendeskService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + ) { this.logger.setContext( CrmObject.contact.toUpperCase() + ':' + ZendeskService.name, ); @@ -38,7 +42,9 @@ export class ZendeskService { { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${decrypt(connection.access_token)}`, + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, }, }, ); @@ -74,7 +80,9 @@ export class ZendeskService { const resp = await axios.get(`https://api.getbase.com/v2/contacts`, { headers: { 'Content-Type': 'application/json', - Authorization: `Bearer ${decrypt(connection.access_token)}`, + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, }, }); const finalData = resp.data.items.map((item) => { diff --git a/packages/api/src/crm/contact/services/zoho/index.ts b/packages/api/src/crm/contact/services/zoho/index.ts index 381096896..399980e5a 100644 --- a/packages/api/src/crm/contact/services/zoho/index.ts +++ b/packages/api/src/crm/contact/services/zoho/index.ts @@ -5,11 +5,15 @@ import axios from 'axios'; import { LoggerService } from '@@core/logger/logger.service'; import { PrismaService } from '@@core/prisma/prisma.service'; import { ActionType, handleServiceError } from '@@core/utils/errors'; -import { decrypt } from '@@core/utils/crypto'; +import { EncryptionService } from '@@core/encryption/encryption.service'; @Injectable() export class ZohoService { - constructor(private prisma: PrismaService, private logger: LoggerService) { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + ) { this.logger.setContext( CrmObject.contact.toUpperCase() + ':' + ZohoService.name, ); @@ -33,7 +37,7 @@ export class ZohoService { { headers: { 'Content-Type': 'application/json', - Authorization: `Zoho-oauthtoken ${decrypt( + Authorization: `Zoho-oauthtoken ${this.cryptoService.decrypt( connection.access_token, )}`, }, @@ -75,7 +79,7 @@ export class ZohoService { { headers: { 'Content-Type': 'application/json', - Authorization: `Zoho-oauthtoken ${decrypt( + Authorization: `Zoho-oauthtoken ${this.cryptoService.decrypt( connection.access_token, )}`, }, diff --git a/packages/api/src/main.ts b/packages/api/src/main.ts index cfb961d1c..7ce74385a 100644 --- a/packages/api/src/main.ts +++ b/packages/api/src/main.ts @@ -3,6 +3,7 @@ import { AppModule } from './app.module'; import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; import { Logger, LoggerErrorInterceptor } from 'nestjs-pino'; import * as fs from 'fs'; +import { useContainer } from 'class-validator'; async function bootstrap() { const app = await NestFactory.create(AppModule); @@ -12,6 +13,9 @@ async function bootstrap() { .setVersion('1.0') .build(); const document = SwaggerModule.createDocument(app, config); + + useContainer(app.select(AppModule), { fallbackOnErrors: true }); + SwaggerModule.setup('docs', app, document); //fs.writeFileSync('./swagger/swagger-spec.yaml', yaml.dump(document)); fs.writeFileSync( diff --git a/packages/api/swagger/swagger-spec.json b/packages/api/swagger/swagger-spec.json index bab393170..aad7d14eb 100644 --- a/packages/api/swagger/swagger-spec.json +++ b/packages/api/swagger/swagger-spec.json @@ -984,7 +984,10 @@ "type": "string" }, "scope": { - "type": "string" + "type": "array", + "items": { + "type": "string" + } } }, "required": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49c76524d..e4a202b0b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -270,7 +270,7 @@ importers: version: 10.0.1(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(bull@4.11.5) '@nestjs/common': specifier: ^10.0.0 - version: 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + version: 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/config': specifier: ^3.1.1 version: 3.1.1(@nestjs/common@10.0.0)(reflect-metadata@0.1.13) @@ -282,7 +282,7 @@ importers: version: 10.1.1(@nestjs/common@10.0.0) '@nestjs/mapped-types': specifier: '*' - version: 0.0.1(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13) + version: 0.0.1(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) '@nestjs/passport': specifier: ^10.0.2 version: 10.0.2(@nestjs/common@10.0.0)(passport@0.6.0) @@ -294,10 +294,10 @@ importers: version: 4.0.0(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(reflect-metadata@0.1.13) '@nestjs/swagger': specifier: ^7.1.14 - version: 7.1.14(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13) + version: 7.1.14(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) '@ntegral/nestjs-sentry': specifier: ^4.0.0 - version: 4.0.0(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(@sentry/hub@7.80.1)(@sentry/node@7.80.0)(class-transformer@0.2.3)(class-validator@0.11.1)(graphql@16.8.1)(reflect-metadata@0.1.13)(rimraf@3.0.2)(rxjs@7.8.1) + version: 4.0.0(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(@sentry/hub@7.80.1)(@sentry/node@7.80.0)(class-transformer@0.5.1)(class-validator@0.14.0)(graphql@16.8.1)(reflect-metadata@0.1.13)(rimraf@3.0.2)(rxjs@7.8.1) '@prisma/client': specifier: ^5.4.2 version: 5.4.2(prisma@5.4.2) @@ -316,6 +316,12 @@ importers: bull: specifier: ^4.11.5 version: 4.11.5 + class-transformer: + specifier: ^0.5.1 + version: 0.5.1 + class-validator: + specifier: ^0.14.0 + version: 0.14.0 crypto: specifier: ^1.0.1 version: 1.0.1 @@ -2089,7 +2095,7 @@ packages: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 '@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0 dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/core': 10.0.0(@nestjs/common@10.0.0)(@nestjs/platform-express@10.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) tslib: 2.6.0 dev: false @@ -2102,7 +2108,7 @@ packages: bull: ^3.3 || ^4.0.0 dependencies: '@nestjs/bull-shared': 10.0.1(@nestjs/common@10.0.0)(@nestjs/core@10.0.0) - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/core': 10.0.0(@nestjs/common@10.0.0)(@nestjs/platform-express@10.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) bull: 4.11.5 tslib: 2.6.0 @@ -2149,7 +2155,7 @@ packages: - webpack-cli dev: true - /@nestjs/common@10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1): + /@nestjs/common@10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1): resolution: {integrity: sha512-Fa2GDQJrO5TTTcpISWfm0pdPS62V+8YbxeG5CA01zMUI+dCO3v3oFf+BSjqCGUUo7GDNzDsjAejwGXuqA54RPw==} peerDependencies: class-transformer: '*' @@ -2162,8 +2168,8 @@ packages: class-validator: optional: true dependencies: - class-transformer: 0.2.3 - class-validator: 0.11.1 + class-transformer: 0.5.1 + class-validator: 0.14.0 iterare: 1.2.1 reflect-metadata: 0.1.13 rxjs: 7.8.1 @@ -2176,7 +2182,7 @@ packages: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 reflect-metadata: ^0.1.13 dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) dotenv: 16.3.1 dotenv-expand: 10.0.0 lodash: 4.17.21 @@ -2202,7 +2208,7 @@ packages: '@nestjs/websockets': optional: true dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/platform-express': 10.0.0(@nestjs/common@10.0.0)(@nestjs/core@10.0.0) '@nuxtjs/opencollective': 0.3.2 fast-safe-stringify: 2.1.1 @@ -2215,7 +2221,7 @@ packages: transitivePeerDependencies: - encoding - /@nestjs/graphql@10.2.1(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(class-transformer@0.2.3)(class-validator@0.11.1)(graphql@16.8.1)(reflect-metadata@0.1.13): + /@nestjs/graphql@10.2.1(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(class-transformer@0.5.1)(class-validator@0.14.0)(graphql@16.8.1)(reflect-metadata@0.1.13): resolution: {integrity: sha512-FBzYTymT4oopiGMpej7GTRyhz1BgJxLlXZPUueamC5J9u1WxCwJyETkzBI/zeUkUydlklF/xd5zDd/Md6//hEw==} requiresBuild: true peerDependencies: @@ -2240,12 +2246,12 @@ packages: '@graphql-tools/merge': 8.3.18(graphql@16.8.1) '@graphql-tools/schema': 9.0.16(graphql@16.8.1) '@graphql-tools/utils': 9.2.1(graphql@16.8.1) - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/core': 10.0.0(@nestjs/common@10.0.0)(@nestjs/platform-express@10.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) - '@nestjs/mapped-types': 1.2.2(@nestjs/common@10.0.0)(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13) + '@nestjs/mapped-types': 1.2.2(@nestjs/common@10.0.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) chokidar: 3.5.3 - class-transformer: 0.2.3 - class-validator: 0.11.1 + class-transformer: 0.5.1 + class-validator: 0.14.0 fast-glob: 3.2.12 graphql: 16.8.1 graphql-tag: 2.12.6(graphql@16.8.1) @@ -2268,24 +2274,24 @@ packages: peerDependencies: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@types/jsonwebtoken': 9.0.2 jsonwebtoken: 9.0.0 dev: false - /@nestjs/mapped-types@0.0.1(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13): + /@nestjs/mapped-types@0.0.1(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-4G4Ui7Sj0UqXiZsUFk/6cPD3K7uZEFSElzkOftaJ3/lXW+HUi1/vfWXabF53qrzO1enTRQDxt1plDbP6SsqXEg==} peerDependencies: class-transformer: ^0.2.3 class-validator: ^0.11.1 reflect-metadata: ^0.1.12 dependencies: - class-transformer: 0.2.3 - class-validator: 0.11.1 + class-transformer: 0.5.1 + class-validator: 0.14.0 reflect-metadata: 0.1.13 dev: false - /@nestjs/mapped-types@1.2.2(@nestjs/common@10.0.0)(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13): + /@nestjs/mapped-types@1.2.2(@nestjs/common@10.0.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-3dHxLXs3M0GPiriAcCFFJQHoDFUuzTD5w6JDhE7TyfT89YKpe6tcCCIqOZWdXmt9AZjjK30RkHRSFF+QEnWFQg==} peerDependencies: '@nestjs/common': ^7.0.8 || ^8.0.0 || ^9.0.0 @@ -2298,14 +2304,14 @@ packages: class-validator: optional: true dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) - class-transformer: 0.2.3 - class-validator: 0.11.1 + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + class-transformer: 0.5.1 + class-validator: 0.14.0 reflect-metadata: 0.1.13 dev: false optional: true - /@nestjs/mapped-types@2.0.2(@nestjs/common@10.0.0)(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13): + /@nestjs/mapped-types@2.0.2(@nestjs/common@10.0.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-V0izw6tWs6fTp9+KiiPUbGHWALy563Frn8X6Bm87ANLRuE46iuBMD5acKBDP5lKL/75QFvrzSJT7HkCbB0jTpg==} peerDependencies: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 @@ -2318,9 +2324,9 @@ packages: class-validator: optional: true dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) - class-transformer: 0.2.3 - class-validator: 0.11.1 + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) + class-transformer: 0.5.1 + class-validator: 0.14.0 reflect-metadata: 0.1.13 dev: false @@ -2330,7 +2336,7 @@ packages: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 passport: ^0.4.0 || ^0.5.0 || ^0.6.0 dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) passport: 0.6.0 dev: false @@ -2340,7 +2346,7 @@ packages: '@nestjs/common': ^10.0.0 '@nestjs/core': ^10.0.0 dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/core': 10.0.0(@nestjs/common@10.0.0)(@nestjs/platform-express@10.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) body-parser: 1.20.2 cors: 2.8.5 @@ -2357,7 +2363,7 @@ packages: '@nestjs/core': ^8.0.0 || ^9.0.0 || ^10.0.0 reflect-metadata: ^0.1.12 dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/core': 10.0.0(@nestjs/common@10.0.0)(@nestjs/platform-express@10.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) cron: 3.1.3 reflect-metadata: 0.1.13 @@ -2379,7 +2385,7 @@ packages: - chokidar dev: true - /@nestjs/swagger@7.1.14(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13): + /@nestjs/swagger@7.1.14(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13): resolution: {integrity: sha512-2Ol4S6qHeYVVmkshkWBM8E/qkmEqEOUj2QIewr0jLSyo30H7f3v81pJyks6pTLy4PK0LGUXojMvIfFIE3mmGQQ==} peerDependencies: '@fastify/static': ^6.0.0 @@ -2396,11 +2402,11 @@ packages: class-validator: optional: true dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/core': 10.0.0(@nestjs/common@10.0.0)(@nestjs/platform-express@10.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) - '@nestjs/mapped-types': 2.0.2(@nestjs/common@10.0.0)(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13) - class-transformer: 0.2.3 - class-validator: 0.11.1 + '@nestjs/mapped-types': 2.0.2(@nestjs/common@10.0.0)(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13) + class-transformer: 0.5.1 + class-validator: 0.14.0 js-yaml: 4.1.0 lodash: 4.17.21 path-to-regexp: 3.2.0 @@ -2421,7 +2427,7 @@ packages: '@nestjs/platform-express': optional: true dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/core': 10.0.0(@nestjs/common@10.0.0)(@nestjs/platform-express@10.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/platform-express': 10.0.0(@nestjs/common@10.0.0)(@nestjs/core@10.0.0) tslib: 2.5.3 @@ -2445,7 +2451,7 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - /@ntegral/nestjs-sentry@4.0.0(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(@sentry/hub@7.80.1)(@sentry/node@7.80.0)(class-transformer@0.2.3)(class-validator@0.11.1)(graphql@16.8.1)(reflect-metadata@0.1.13)(rimraf@3.0.2)(rxjs@7.8.1): + /@ntegral/nestjs-sentry@4.0.0(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(@sentry/hub@7.80.1)(@sentry/node@7.80.0)(class-transformer@0.5.1)(class-validator@0.14.0)(graphql@16.8.1)(reflect-metadata@0.1.13)(rimraf@3.0.2)(rxjs@7.8.1): resolution: {integrity: sha512-6WHZcK7NLeg7ue1y3Z61msEBzCGZeXQ0hWhliH1ddQH0kPbZ6lXLxduGMWYb0N/fPjXAX1Astz8urqnoTOZBQw==} peerDependencies: '@nestjs/common': ^9.0.4 @@ -2456,7 +2462,7 @@ packages: rimraf: ^3.0.2 rxjs: ^7.2.0 dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@nestjs/core': 10.0.0(@nestjs/common@10.0.0)(@nestjs/platform-express@10.0.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) '@sentry/hub': 7.80.1 '@sentry/node': 7.80.0 @@ -2464,7 +2470,7 @@ packages: rimraf: 3.0.2 rxjs: 7.8.1 optionalDependencies: - '@nestjs/graphql': 10.2.1(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(class-transformer@0.2.3)(class-validator@0.11.1)(graphql@16.8.1)(reflect-metadata@0.1.13) + '@nestjs/graphql': 10.2.1(@nestjs/common@10.0.0)(@nestjs/core@10.0.0)(class-transformer@0.5.1)(class-validator@0.14.0)(graphql@16.8.1)(reflect-metadata@0.1.13) transitivePeerDependencies: - '@apollo/subgraph' - bufferutil @@ -4215,8 +4221,8 @@ packages: resolution: {integrity: sha512-WUtIVRUZ9i5dYXefDEAI7sh9/O7jGvHg7Df/5O/gtH3Yabe5odI3UWopVR1qbPXQtvOxWu3mM4XxlYeZtMWF4g==} dev: true - /@types/validator@10.11.3: - resolution: {integrity: sha512-GKF2VnEkMmEeEGvoo03ocrP9ySMuX1ypKazIYMlsjfslfBMhOAtC5dmEWKdJioW4lJN7MZRS88kalTsVClyQ9w==} + /@types/validator@13.11.7: + resolution: {integrity: sha512-q0JomTsJ2I5Mv7dhHhQLGjMvX0JJm5dyZ1DXQySIUzU1UlwzB8bt+R6+LODUbz0UDIOvEzGc28tk27gBJw2N8Q==} /@types/yargs-parser@21.0.2: resolution: {integrity: sha512-5qcvofLPbfjmBfKaLfj/+f+Sbd6pN4zl7w7VSVI5uz7m9QZTuB2aZAa2uo1wHFBNN2x6g/SoTkXmd8mQnQF2Cw==} @@ -5559,15 +5565,15 @@ packages: resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} dev: true - /class-transformer@0.2.3: - resolution: {integrity: sha512-qsP+0xoavpOlJHuYsQJsN58HXSl8Jvveo+T37rEvCEeRfMWoytAyR0Ua/YsFgpM6AZYZ/og2PJwArwzJl1aXtQ==} + /class-transformer@0.5.1: + resolution: {integrity: sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw==} - /class-validator@0.11.1: - resolution: {integrity: sha512-6CGdjwJLmKw+sQbK5ZDo1v1yTajkqfPOUDWSYVIlhUiCh6Phy8sAnMFE2XKHAcKAdoOz4jJUQhjPQWPYUuHxrA==} + /class-validator@0.14.0: + resolution: {integrity: sha512-ct3ltplN8I9fOwUd8GrP8UQixwff129BkEtuWDKL5W45cQuLd19xqmTLu5ge78YDm/fdje6FMt0hGOhl0lii3A==} dependencies: - '@types/validator': 10.11.3 - google-libphonenumber: 3.2.33 - validator: 12.0.0 + '@types/validator': 13.11.7 + libphonenumber-js: 1.10.52 + validator: 13.11.0 /class-variance-authority@0.7.0: resolution: {integrity: sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==} @@ -7414,10 +7420,6 @@ packages: csstype: 3.1.2 dev: false - /google-libphonenumber@3.2.33: - resolution: {integrity: sha512-1QKCvAlfq8zY1mviORI9lDzM3I/hwm9+h0CwYBTLq59DBbSHMd5zBOLqHZFiBLicRpwIz46Nynvbywj1XApKvA==} - engines: {node: '>=0.10'} - /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: @@ -8704,6 +8706,9 @@ packages: type-check: 0.4.0 dev: true + /libphonenumber-js@1.10.52: + resolution: {integrity: sha512-6vCuCHgem+OW1/VCAKgkasfegItCea8zIT7s9/CG/QxdCMIM7GfzbEBG5d7lGO3rzipjt5woOQL3DiHa8Fy78Q==} + /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} @@ -9209,7 +9214,7 @@ packages: '@nestjs/common': ^8.0.0 || ^9.0.0 || ^10.0.0 pino-http: ^6.4.0 || ^7.0.0 || ^8.0.0 dependencies: - '@nestjs/common': 10.0.0(class-transformer@0.2.3)(class-validator@0.11.1)(reflect-metadata@0.1.13)(rxjs@7.8.1) + '@nestjs/common': 10.0.0(class-transformer@0.5.1)(class-validator@0.14.0)(reflect-metadata@0.1.13)(rxjs@7.8.1) pino-http: 8.5.1 dev: false @@ -12333,14 +12338,9 @@ packages: spdx-expression-parse: 3.0.1 dev: false - /validator@12.0.0: - resolution: {integrity: sha512-r5zA1cQBEOgYlesRmSEwc9LkbfNLTtji+vWyaHzRZUxCTHdsX3bd+sdHfs5tGZ2W6ILGGsxWxCNwT/h3IY/3ng==} - engines: {node: '>= 0.10'} - /validator@13.11.0: resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} engines: {node: '>= 0.10'} - dev: false /value-or-promise@1.0.12: resolution: {integrity: sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==}