From 4c49dbc0ea3cef5c0f7ea89b2cb059790a0acb04 Mon Sep 17 00:00:00 2001 From: Arthur Simas Date: Thu, 7 Jul 2022 15:00:59 -0300 Subject: [PATCH 1/5] FEAT: protospack-v2 updated --- package-lock.json | 14 +++---- package.json | 2 +- src/modules/auth/auth.service.ts | 42 ++++++------------- .../permissions/permissions.service.ts | 9 ++-- src/utils/grpcHandler.ts | 19 --------- 5 files changed, 23 insertions(+), 63 deletions(-) delete mode 100644 src/utils/grpcHandler.ts diff --git a/package-lock.json b/package-lock.json index e149c54..6126ab4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "passport-hubspot-oauth2": "^1.0.3", "passport-mailchimp": "^1.1.0", "protospack": "2.5.1", - "protospack-v2": "1.1.1", + "protospack-v2": "3.0.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.5.5", @@ -8997,9 +8997,9 @@ } }, "node_modules/protospack-v2": { - "version": "1.1.1", - "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack-v2/-/protospack-v2-1.1.1.tgz", - "integrity": "sha512-BqIJSORaqauAT9kF4/cP/uJNCyoT3KxkVkamd7SWARMxnywFB/mpYJg/VDGcyvVOAU4IOLyjnXkrvRuylE0Q2w==", + "version": "3.0.0", + "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack-v2/-/protospack-v2-3.0.0.tgz", + "integrity": "sha512-GEFbf8+vVaq/lA28K4nFf7bOSlghQJn/aeVnrYzh4YJUaa1+ccNz3uQs9p5OGbfjt2u/fFE5rHGEBUtueAA8KA==", "dependencies": { "rxjs": "^7.5.5", "ts-proto": "^1.112.2" @@ -17198,9 +17198,9 @@ } }, "protospack-v2": { - "version": "1.1.1", - "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack-v2/-/protospack-v2-1.1.1.tgz", - "integrity": "sha512-BqIJSORaqauAT9kF4/cP/uJNCyoT3KxkVkamd7SWARMxnywFB/mpYJg/VDGcyvVOAU4IOLyjnXkrvRuylE0Q2w==", + "version": "3.0.0", + "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com:443/npm/dadosfera-npm/protospack-v2/-/protospack-v2-3.0.0.tgz", + "integrity": "sha512-GEFbf8+vVaq/lA28K4nFf7bOSlghQJn/aeVnrYzh4YJUaa1+ccNz3uQs9p5OGbfjt2u/fFE5rHGEBUtueAA8KA==", "requires": { "rxjs": "^7.5.5", "ts-proto": "^1.112.2" diff --git a/package.json b/package.json index a8030ea..c3e5c80 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "passport-hubspot-oauth2": "^1.0.3", "passport-mailchimp": "^1.1.0", "protospack": "2.5.1", - "protospack-v2": "1.1.1", + "protospack-v2": "3.0.0", "reflect-metadata": "^0.1.13", "rimraf": "^3.0.2", "rxjs": "^7.5.5", diff --git a/src/modules/auth/auth.service.ts b/src/modules/auth/auth.service.ts index 3cbd01c..664dcbb 100644 --- a/src/modules/auth/auth.service.ts +++ b/src/modules/auth/auth.service.ts @@ -1,35 +1,23 @@ import { OnModuleInit, Inject, Injectable } from '@nestjs/common'; import { ClientGrpc } from '@nestjs/microservices'; import { DadosferaLogger } from 'dadosfera-logs'; +import { lastValueFrom } from 'rxjs'; import { ProtoServices } from 'protospack-v2/dist/lib/Duc'; import { AuthProtoService as AuthServiceInterface } from 'protospack-v2/dist/lib/Duc/interfaces/write-service'; import { - AuthGetPublicKeysResponse, AuthSignInRequest, - AuthSignInResponse, AuthRefreshAccessTokenRequest, - AuthRefreshAccessTokenResponse, AuthEnableTotpMfaRequest, - AuthEnableTotpMfaResponse, AuthDisableTotpMfaRequest, - AuthDisableTotpMfaResponse, AuthDismissTotpMfaRequest, - AuthDismissTotpMfaResponse, AuthVerifyTotpMfaRequest, - AuthVerifyTotpMfaResponse, AuthChangePasswordRequest, - AuthChangePasswordResponse, AuthResetPasswordRequest, - AuthResetPasswordResponse, AuthVerifyResetPasswordCodeRequest, - AuthVerifyResetPasswordCodeResponse, AuthConfirmResetPasswordRequest, - AuthConfirmResetPasswordResponse, } from 'protospack-v2/dist/lib/Duc/interfaces/messages'; -import grpcHandler from '../../utils/grpcHandler'; - @Injectable() export class AuthClientService implements OnModuleInit { logger: any; @@ -52,15 +40,13 @@ export class AuthClientService implements OnModuleInit { async getPublicKeys() { this.logger.info('GetPublicKeys'); - return grpcHandler( - this.authService.AuthGetPublicKeys({}), - ); + return lastValueFrom(this.authService.AuthGetPublicKeys({})); } async signIn({ username, password, totp }: AuthSignInRequest) { this.logger.info('SignIn'); - return grpcHandler( + return lastValueFrom( this.authService.AuthSignIn({ username, password, totp }), ); } @@ -68,7 +54,7 @@ export class AuthClientService implements OnModuleInit { async refreshAccessToken({ refreshToken }: AuthRefreshAccessTokenRequest) { this.logger.info('RefreshAccessToken'); - return grpcHandler( + return lastValueFrom( this.authService.AuthRefreshAccessToken({ refreshToken }), ); } @@ -80,7 +66,7 @@ export class AuthClientService implements OnModuleInit { }: AuthChangePasswordRequest) { this.logger.info('ChangePassword'); - return grpcHandler( + return lastValueFrom( this.authService.AuthChangePassword({ accessToken, oldPassword, @@ -92,9 +78,7 @@ export class AuthClientService implements OnModuleInit { async resetPassword({ username }: AuthResetPasswordRequest) { this.logger.info('resetPassword'); - return grpcHandler( - this.authService.AuthResetPassword({ username }), - ); + return lastValueFrom(this.authService.AuthResetPassword({ username })); } async verifyResetPasswordCode({ @@ -103,7 +87,7 @@ export class AuthClientService implements OnModuleInit { }: AuthVerifyResetPasswordCodeRequest) { this.logger.info('verifyResetPasswordCode'); - return grpcHandler( + return lastValueFrom( this.authService.AuthVerifyResetPasswordCode({ username, code }), ); } @@ -115,7 +99,7 @@ export class AuthClientService implements OnModuleInit { }: AuthConfirmResetPasswordRequest) { this.logger.info('confirmResetPassword'); - return grpcHandler( + return lastValueFrom( this.authService.AuthConfirmResetPassword({ username, code, @@ -127,7 +111,7 @@ export class AuthClientService implements OnModuleInit { async enableTotpMFA({ accessToken, password }: AuthEnableTotpMfaRequest) { this.logger.info('enableTotpMFA'); - return grpcHandler( + return lastValueFrom( this.authService.AuthEnableTotpMfa({ accessToken, password }), ); } @@ -135,7 +119,7 @@ export class AuthClientService implements OnModuleInit { async disableTotpMFA({ accessToken, password }: AuthDisableTotpMfaRequest) { this.logger.info('disableTotpMFA'); - return grpcHandler( + return lastValueFrom( this.authService.AuthDisableTotpMfa({ accessToken, password }), ); } @@ -143,15 +127,13 @@ export class AuthClientService implements OnModuleInit { async dismissTotpMFA({ accessToken }: AuthDismissTotpMfaRequest) { this.logger.info('dismissTotpMFA'); - return grpcHandler( - this.authService.AuthDismissTotpMfa({ accessToken }), - ); + return lastValueFrom(this.authService.AuthDismissTotpMfa({ accessToken })); } async verifyTotp({ accessToken, totp }: AuthVerifyTotpMfaRequest) { this.logger.info('disableTotpMFA'); - return grpcHandler( + return lastValueFrom( this.authService.AuthVerifyTotpMfa({ accessToken, totp }), ); } diff --git a/src/modules/permissions/permissions.service.ts b/src/modules/permissions/permissions.service.ts index 91fda6a..2c0ec54 100644 --- a/src/modules/permissions/permissions.service.ts +++ b/src/modules/permissions/permissions.service.ts @@ -5,15 +5,12 @@ import { Injectable, } from '@nestjs/common'; import { ClientGrpc } from '@nestjs/microservices'; +import { lastValueFrom } from 'rxjs'; import { ProtoServices } from 'protospack-v2/dist/lib/Duc'; import { PermissionsProtoService as PermissionsServiceInterface } from 'protospack-v2/dist/lib/Duc/interfaces/write-service'; -import { - Empty, - InjectPermissionsRequest, -} from 'protospack-v2/dist/lib/Duc/interfaces/messages'; +import { InjectPermissionsRequest } from 'protospack-v2/dist/lib/Duc/interfaces/messages'; import { DadosferaLogger } from 'dadosfera-logs'; -import grpcHandler from '../../utils/grpcHandler'; import { Permissions } from '../../authentication/permissions.enum'; import ErrorBuilder from '../../utils/ErrorBuilder'; @@ -66,7 +63,7 @@ export class PermissionsClientService async injectPermissions({ permissions }: InjectPermissionsRequest) { this.logger.info('InjectPermissions'); - return grpcHandler( + return lastValueFrom( this.permissionsService.InjectPermissions({ permissions }), ); } diff --git a/src/utils/grpcHandler.ts b/src/utils/grpcHandler.ts deleted file mode 100644 index 0e7d77b..0000000 --- a/src/utils/grpcHandler.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Logger } from '@nestjs/common'; -import { RpcException } from '@nestjs/microservices'; -import { from } from 'rxjs'; - -import ErrorBuilder from './ErrorBuilder'; - -const logger = new Logger(); - -export default async function grpcHandler(method: Promise) { - return new Promise((resolve, reject) => { - from(method).subscribe({ - next: resolve, - error: reject, - complete: () => logger.log('done'), - }); - }).catch((err: RpcException) => { - throw new ErrorBuilder(err); - }); -} From 9f009309cbb8bc8868e93446500e46e12677f3e8 Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Thu, 7 Jul 2022 17:51:28 -0300 Subject: [PATCH 2/5] FIX: conditionally importing apm --- src/main.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.ts b/src/main.ts index 4d80a22..c0505ac 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,3 @@ -import 'elastic-apm-node/start'; import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { writeFileSync } from 'fs'; @@ -10,11 +9,12 @@ import documentEmpty from '../swagger_empty.json'; import { AppModule } from './app.module'; async function bootstrap() { + if (process.env.ENV !== 'local') await import('elastic-apm-node/start'); + DadosferaLogger.setupLogger({ serviceName: 'maestro', serviceEnvironment: process.env.ENV, }); - const logger = new DadosferaLogger().logger; const orginalWinstonLog = logger.log.bind(logger); From d288a4f357bebfa49b0a1dc430f0cacb781ebbc2 Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Thu, 7 Jul 2022 18:18:53 -0300 Subject: [PATCH 3/5] FIX: conditionally importing apm --- src/apm.ts | 5 +++++ src/main.ts | 4 +--- 2 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 src/apm.ts diff --git a/src/apm.ts b/src/apm.ts new file mode 100644 index 0000000..8c20720 --- /dev/null +++ b/src/apm.ts @@ -0,0 +1,5 @@ +export const startAPm = async () => { + if (process.env.ENV !== 'local') + return await import('elastic-apm-node/start'); +}; +startAPm(); diff --git a/src/main.ts b/src/main.ts index c0505ac..33c5e54 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,6 @@ +import './apm'; import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; -import { writeFileSync } from 'fs'; import helmet from 'helmet'; import { DadosferaLogger } from 'dadosfera-logs'; @@ -9,8 +9,6 @@ import documentEmpty from '../swagger_empty.json'; import { AppModule } from './app.module'; async function bootstrap() { - if (process.env.ENV !== 'local') await import('elastic-apm-node/start'); - DadosferaLogger.setupLogger({ serviceName: 'maestro', serviceEnvironment: process.env.ENV, From f49c5ac1c1b171ad7bdd1320434cb75ec594e7f2 Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Thu, 7 Jul 2022 20:04:42 -0300 Subject: [PATCH 4/5] FIX: conditionally importing apm --- src/apm.ts | 5 ----- src/main.ts | 3 +-- 2 files changed, 1 insertion(+), 7 deletions(-) delete mode 100644 src/apm.ts diff --git a/src/apm.ts b/src/apm.ts deleted file mode 100644 index 8c20720..0000000 --- a/src/apm.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const startAPm = async () => { - if (process.env.ENV !== 'local') - return await import('elastic-apm-node/start'); -}; -startAPm(); diff --git a/src/main.ts b/src/main.ts index 33c5e54..788cf4c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,4 +1,4 @@ -import './apm'; +if (process.env.ENV !== 'local') require('elastic-apm-node/start'); import { NestFactory } from '@nestjs/core'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import helmet from 'helmet'; @@ -7,7 +7,6 @@ import { DadosferaLogger } from 'dadosfera-logs'; import documentEmpty from '../swagger_empty.json'; import { AppModule } from './app.module'; - async function bootstrap() { DadosferaLogger.setupLogger({ serviceName: 'maestro', From 88bc7fe625295f58fa0e6203d290b31d63ecb655 Mon Sep 17 00:00:00 2001 From: Arthur Simas Date: Thu, 7 Jul 2022 20:24:13 -0300 Subject: [PATCH 5/5] FIX: added exception filter to catch unhandled errors --- src/error/grpc-to-http-exception.filter.ts | 22 ++++++++++++++++++++++ src/modules/auth/auth.controller.ts | 3 +++ src/utils/ErrorBuilder.ts | 4 ++-- 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/error/grpc-to-http-exception.filter.ts diff --git a/src/error/grpc-to-http-exception.filter.ts b/src/error/grpc-to-http-exception.filter.ts new file mode 100644 index 0000000..3e187db --- /dev/null +++ b/src/error/grpc-to-http-exception.filter.ts @@ -0,0 +1,22 @@ +import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common'; +import { Response } from 'express'; + +import ErrorBuilder from '../utils/ErrorBuilder'; + +@Catch(Error) +export class GrpcToHttpExceptionFilter implements ExceptionFilter { + catch(exception: any, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const response = ctx.getResponse(); + + // return this exception directly if is already of type ErrorBuilder, + // else transform it using the ErrorBuilder + const err = + exception.constructor.name === ErrorBuilder.name + ? exception + : new ErrorBuilder(exception.details); + + const { statusCode } = err.response; + return response.status(statusCode).json(err.response); + } +} diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 0560249..6db6a51 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -6,6 +6,7 @@ import { HttpCode, HttpStatus, Inject, + UseFilters, } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { @@ -22,8 +23,10 @@ import { import { AuthClientService } from './auth.service'; import { DadosferaLogger } from 'dadosfera-logs'; +import { GrpcToHttpExceptionFilter } from '../../error/grpc-to-http-exception.filter'; @ApiTags('Auth') +@UseFilters(new GrpcToHttpExceptionFilter()) @Controller('auth') export class AuthController { logger: any; diff --git a/src/utils/ErrorBuilder.ts b/src/utils/ErrorBuilder.ts index fd7095d..2f2cfd9 100644 --- a/src/utils/ErrorBuilder.ts +++ b/src/utils/ErrorBuilder.ts @@ -3,7 +3,7 @@ import { RpcException } from '@nestjs/microservices'; import ErrorCodes from './errorCodes'; -function enrichErrorCode(code: string) { +export function EnrichErrorCode(code: string) { switch (code) { case ErrorCodes.AUTH.WRONG_CREDENTIALS: return { @@ -138,7 +138,7 @@ export default class ErrorBuilder extends HttpException { logger.log(code); } - const { statusCode, message, error, code: rCode } = enrichErrorCode(code); + const { statusCode, message, error, code: rCode } = EnrichErrorCode(code); super({ statusCode, message, error, code: rCode }, statusCode); this.code = code; }