From de065122490eee90d4bc929a2c69f722bf167183 Mon Sep 17 00:00:00 2001 From: Gabriel Rosa Date: Tue, 14 Feb 2023 08:56:23 -0300 Subject: [PATCH] FIX: changed language strategy to use new custom decorator --- docsfera.json | 647 ++++++++++++++++-- src/decorators/language.decorator.ts | 25 + src/main.ts | 3 +- src/modules/auth/auth.controller.ts | 17 +- src/modules/auth/dtos/login.ts | 5 +- src/modules/catalog/catalog.controller.ts | 13 +- .../connection/connection.controller.ts | 12 +- src/modules/connector/connector.controller.ts | 13 +- .../network-config.controller.ts | 12 +- src/modules/oauth/oauth.controller.ts | 1 - .../passport-strategies/google-strategy.ts | 1 - .../permissions/permissions.controller.ts | 7 +- .../pipelinesV2/pipelines.controller.ts | 43 +- src/modules/roles/roles.controller.ts | 29 +- .../termsOfUse/termsOfUse.controller.ts | 7 +- src/modules/users/users.controller.ts | 37 +- 16 files changed, 717 insertions(+), 155 deletions(-) create mode 100644 src/decorators/language.decorator.ts diff --git a/docsfera.json b/docsfera.json index ac32457..e067c21 100644 --- a/docsfera.json +++ b/docsfera.json @@ -10,10 +10,14 @@ "operationId": "AuthController_signIn", "parameters": [ { - "name": "Dadosfera-Lang", - "required": true, + "name": "dadosfera-lang", "in": "header", + "required": false, "schema": { + "enum": [ + "pt-br", + "en-us" + ], "type": "string" } } @@ -48,7 +52,20 @@ "/auth/sso/snowflake": { "post": { "operationId": "AuthController_snowflakeSignIn", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -76,10 +93,14 @@ "operationId": "AuthController_refreshAccessToken", "parameters": [ { - "name": "Dadosfera-Lang", - "required": true, + "name": "dadosfera-lang", "in": "header", + "required": false, "schema": { + "enum": [ + "pt-br", + "en-us" + ], "type": "string" } } @@ -114,7 +135,20 @@ "/auth/change-password": { "post": { "operationId": "AuthController_changePassword", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -135,7 +169,20 @@ "/auth/reset-password": { "post": { "operationId": "AuthController_resetPassword", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -156,7 +203,20 @@ "/auth/verify-reset-password-code": { "post": { "operationId": "AuthController_verifyResetPasswordCode", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -177,7 +237,20 @@ "/auth/confirm-reset-password": { "post": { "operationId": "AuthController_confirmResetPassword", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -198,7 +271,20 @@ "/auth/enable-totp": { "post": { "operationId": "AuthController_enableTotpMFA", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -219,7 +305,20 @@ "/auth/disable-totp": { "post": { "operationId": "AuthController_disableTotpMFA", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -240,7 +339,20 @@ "/auth/dismiss-totp": { "post": { "operationId": "AuthController_dismissTotpMFA", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -261,7 +373,20 @@ "/auth/verify-totp": { "post": { "operationId": "AuthController_verifyTotp", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -282,7 +407,20 @@ "/auth/verify-access-token": { "get": { "operationId": "AuthController_verifyAccessToken", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "" @@ -305,6 +443,18 @@ "get": { "operationId": "AuthController_getSession", "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, { "name": "session", "required": true, @@ -334,7 +484,20 @@ "/auth/oauth/google": { "get": { "operationId": "AuthController_googleOauth", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -355,7 +518,20 @@ "/auth/oauth/google/callback": { "get": { "operationId": "AuthController_googleOauthCallback", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "" @@ -935,14 +1111,6 @@ "put": { "operationId": "ConnectionController_updateConnection", "parameters": [ - { - "name": "Dadosfera-Lang", - "required": true, - "in": "header", - "schema": { - "type": "string" - } - }, { "name": "id", "required": true, @@ -2633,7 +2801,20 @@ "/pipelinesV2": { "post": { "operationId": "PipelinesController_create", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "requestBody": { "required": true, "content": { @@ -2667,7 +2848,20 @@ }, "get": { "operationId": "PipelinesController_findAll", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "" @@ -2687,6 +2881,18 @@ "get": { "operationId": "PipelinesController_downloadLogs", "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, { "name": "pipeline_run_id", "required": true, @@ -2714,7 +2920,20 @@ "/pipelinesV2/{id}/config": { "get": { "operationId": "PipelinesController_getPipelineproperties", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "" @@ -2733,7 +2952,20 @@ "/pipelinesV2/{id}/objects": { "get": { "operationId": "PipelinesController_getPipelineObjects", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "" @@ -2752,7 +2984,20 @@ "/pipelinesV2/{id}/status": { "get": { "operationId": "PipelinesController_getPipelineStatus", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -2778,7 +3023,20 @@ "/pipelinesV2/{id}": { "get": { "operationId": "PipelinesController_findOne", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -2802,7 +3060,20 @@ }, "patch": { "operationId": "PipelinesController_update", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -2829,7 +3100,20 @@ "summary": "", "deprecated": true, "description": "This method is deprecated. Please use PATCH instead", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -2853,7 +3137,20 @@ }, "delete": { "operationId": "PipelinesController_delete", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "204": { "description": "" @@ -2872,7 +3169,20 @@ "/pipelinesV2/init-upload": { "post": { "operationId": "PipelinesController_initUploadFile", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "requestBody": { "required": true, "content": { @@ -2904,7 +3214,20 @@ "/pipelinesV2/complete-upload": { "post": { "operationId": "PipelinesController_completeUploadFile", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "requestBody": { "required": true, "content": { @@ -2943,7 +3266,20 @@ "/pipelinesV2/file": { "post": { "operationId": "PipelinesController_uploadedFile", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "requestBody": { "required": true, "content": { @@ -2982,7 +3318,20 @@ "/pipelinesV2/start/{id}": { "post": { "operationId": "PipelinesController_activate", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "201": { "description": "", @@ -3321,7 +3670,20 @@ "/catalog": { "get": { "operationId": "CatalogController_searchCatalog", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -3348,7 +3710,20 @@ }, "post": { "operationId": "CatalogController_createDataAsset", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "requestBody": { "required": true, "content": { @@ -3380,7 +3755,20 @@ "/catalog/data-asset": { "get": { "operationId": "CatalogController_findByPipelineAndObject", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "" @@ -3399,7 +3787,20 @@ "/catalog/tags": { "get": { "operationId": "CatalogController_findAllTags", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -3429,6 +3830,18 @@ "get": { "operationId": "CatalogController_getDataAsset", "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, { "name": "shared", "required": true, @@ -3457,7 +3870,20 @@ }, "put": { "operationId": "CatalogController_updateDataAsset", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "requestBody": { "required": true, "content": { @@ -3495,6 +3921,18 @@ "delete": { "operationId": "CatalogController_deleteDataAsset", "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, { "name": "id", "required": true, @@ -3532,7 +3970,20 @@ "/catalog/data-asset/rls/{id}": { "get": { "operationId": "CatalogController_getDataAssetRls", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "" @@ -3554,7 +4005,20 @@ "/catalog/data-asset/{id}/columns-metadata": { "get": { "operationId": "CatalogController_getDataAssetColumnsMetadata", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -3583,7 +4047,20 @@ "/catalog/data-asset/{id}/preview": { "get": { "operationId": "CatalogController_getDataAssetPreview", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -3612,7 +4089,20 @@ "/catalog/data-asset/{id}/docs": { "get": { "operationId": "CatalogController_getDataAssetDocs", - "parameters": [], + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], "responses": { "200": { "description": "", @@ -3640,6 +4130,18 @@ "post": { "operationId": "CatalogController_manageDataAssetDocs", "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, { "name": "id", "required": true, @@ -3678,6 +4180,18 @@ "put": { "operationId": "CatalogController_manageDataAssetPermissions", "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, { "name": "id", "required": true, @@ -3706,6 +4220,18 @@ "put": { "operationId": "CatalogController_revokeDataAssetPermissions", "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, { "name": "id", "required": true, @@ -3734,6 +4260,18 @@ "post": { "operationId": "CatalogController_commentOnDataAsset", "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, { "name": "id", "required": true, @@ -3780,6 +4318,18 @@ "delete": { "operationId": "CatalogController_deleteComment", "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, { "name": "id", "required": true, @@ -4089,7 +4639,7 @@ }, "info": { "title": "Maestro - feat/docs-refactor", - "description": "Documentation for Maestro gateway", + "description": "This is the Maestro API", "version": "1.0.0", "contact": {} }, @@ -4114,7 +4664,8 @@ "type": "string" }, "totp": { - "type": "string" + "type": "string", + "description": "TOTP code used to login when Multi-Factor Authentication is enabled" } }, "required": [ diff --git a/src/decorators/language.decorator.ts b/src/decorators/language.decorator.ts new file mode 100644 index 0000000..f455200 --- /dev/null +++ b/src/decorators/language.decorator.ts @@ -0,0 +1,25 @@ +import { createParamDecorator, type ExecutionContext } from '@nestjs/common'; +import { LanguageEnum } from 'src/utils/languages.enum'; + +export const Language: () => ParameterDecorator = createParamDecorator( + (options: any, ctx: ExecutionContext): LanguageEnum => { + const headers = ctx.switchToHttp()?.getRequest()?.headers; + + if (!headers) return LanguageEnum.ptbr; + + let language: LanguageEnum = + headers['dadosfera-lang'] ?? headers['accept-language']; + language = language?.toLowerCase().trim() as LanguageEnum; + + if (!language) return LanguageEnum.ptbr; + + Object.values(LanguageEnum).some((l) => { + if (language === l || l.includes(language)) { + language = l; + return true; + } + language = LanguageEnum.enus; + }); + return language; + }, +); diff --git a/src/main.ts b/src/main.ts index c3bf5da..1fe7ee5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -39,7 +39,7 @@ function configureSwagger(app: INestApplication) { .replace('\n', '') .trim(); } catch (error) { - console.log("Can't get branch name", error); + console.warn("Can't get branch name", error); } const swaggerTitle = branchName ? `Maestro - ${branchName}` : 'Maestro'; @@ -51,6 +51,7 @@ function configureSwagger(app: INestApplication) { name: 'Authorization', in: 'header', }) + .setDescription('This is the Maestro API') .build(); const document = SwaggerModule.createDocument(app, config); diff --git a/src/modules/auth/auth.controller.ts b/src/modules/auth/auth.controller.ts index 01868c1..2932216 100644 --- a/src/modules/auth/auth.controller.ts +++ b/src/modules/auth/auth.controller.ts @@ -13,7 +13,7 @@ import { Req, Param, } from '@nestjs/common'; -import { ApiSecurity, ApiTags } from '@nestjs/swagger'; +import { ApiHeaders, ApiSecurity, ApiTags } from '@nestjs/swagger'; import { AuthChangePasswordRequest, AuthResetPasswordRequest, @@ -43,8 +43,11 @@ import { AuthGuard } from '@nestjs/passport'; import { Request } from 'express'; import ErrorCodes, { OauthErrors } from 'src/utils/errorCodes'; import jwt from 'jsonwebtoken'; +import { LanguageEnum } from 'src/utils/languages.enum'; +import { Language } from 'src/decorators/language.decorator'; @ApiTags('Auth') +@ApiHeaders([{ name: 'dadosfera-lang', enum: LanguageEnum, required: false }]) @UseFilters(new GrpcToHttpExceptionFilter()) @Controller('auth') export class AuthController { @@ -74,10 +77,10 @@ export class AuthController { @HttpCode(HttpStatus.OK) async signIn( @Body() { username, password, totp }: AuthSignInReq, - @Headers('Dadosfera-Lang') language: string, + @Language() language: LanguageEnum, ): Promise { this.logger.info('/auth - SignIn'); - const metadata = PackTheMetadata({ language: language || 'pt-br' }); + const metadata = PackTheMetadata({ language }); return this.authClient.signIn({ username, password, totp }, metadata); } @@ -99,11 +102,11 @@ export class AuthController { @Post('refresh-access-token') @HttpCode(HttpStatus.OK) async refreshAccessToken( - @Body() - { refreshToken, customerName: customer_name }: AuthRefreshAccessTokenReq, - @Headers('Dadosfera-Lang') language: string, + @Body() body: AuthRefreshAccessTokenReq, + @Language() language: LanguageEnum, ) { this.logger.info('/auth - RefreshAccessToken'); + const { refreshToken, customerName: customer_name } = body; const metadata = PackTheMetadata({ customer_name, @@ -135,7 +138,7 @@ export class AuthController { @HttpCode(HttpStatus.OK) async resetPassword( @Body() body: AuthResetPasswordRequest, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('/auth - reset-password'); const metadata = PackTheMetadata({ diff --git a/src/modules/auth/dtos/login.ts b/src/modules/auth/dtos/login.ts index a41d8f3..981ac6c 100644 --- a/src/modules/auth/dtos/login.ts +++ b/src/modules/auth/dtos/login.ts @@ -81,7 +81,10 @@ export class AuthSignInReq implements AuthSignInRequest { username: string; @ApiProperty() password: string; - @ApiPropertyOptional() + @ApiPropertyOptional({ + description: + 'TOTP code used to login when Multi-Factor Authentication is enabled', + }) totp: string; } diff --git a/src/modules/catalog/catalog.controller.ts b/src/modules/catalog/catalog.controller.ts index 1dc4b55..e7a2657 100644 --- a/src/modules/catalog/catalog.controller.ts +++ b/src/modules/catalog/catalog.controller.ts @@ -14,7 +14,7 @@ import { Query, UseFilters, } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; +import { ApiHeaders, ApiTags } from '@nestjs/swagger'; import { Authenticated, RequireSomePermission, @@ -36,8 +36,11 @@ import { IUpdateDataRequest, } from './dtos'; import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter'; +import { Language } from 'src/decorators/language.decorator'; +import { LanguageEnum } from 'src/utils/languages.enum'; @ApiTags('Catalog') +@ApiHeaders([{ name: 'dadosfera-lang', enum: LanguageEnum, required: false }]) @Controller('catalog') @UseFilters(new GrpcToHttpExceptionFilter()) @Authenticated() @@ -283,7 +286,7 @@ export class CatalogController { ) async getDataAssetColumnsMetadata( @User() user: RequestUser, - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Param('id') id, ): Promise { const { customer_name, customer_id, user_id, username } = user; @@ -314,7 +317,7 @@ export class CatalogController { ) async getDataAssetPreview( @User() user: RequestUser, - @Headers('Dadosfera-lang') language, + @Language() language: LanguageEnum, @Param('id') id, ): Promise { const { customer_name, customer_id, user_id, username } = user; @@ -344,7 +347,7 @@ export class CatalogController { ) async getDataAssetDocs( @User() user: RequestUser, - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Param('id') id, ): Promise { const { customer_name, customer_id, user_id, username } = user; @@ -374,7 +377,7 @@ export class CatalogController { ) async updateDataAsset( @User() user: RequestUser, - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Param('id') data_asset_id, @Body() body: IUpdateDataRequest, ): Promise { diff --git a/src/modules/connection/connection.controller.ts b/src/modules/connection/connection.controller.ts index c986617..a2245c1 100644 --- a/src/modules/connection/connection.controller.ts +++ b/src/modules/connection/connection.controller.ts @@ -7,7 +7,6 @@ import { Param, Delete, Get, - Headers, Query, UseFilters, } from '@nestjs/common'; @@ -30,6 +29,8 @@ import { import { CreateConnectionDto } from './dtos/connection'; import { PackTheMetadata } from 'src/utils/ PackTheMetadata'; import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter'; +import { Language } from 'src/decorators/language.decorator'; +import { LanguageEnum } from 'src/utils/languages.enum'; const connectionPermissions = PERMISSIONS_GROUPS.CONNECTION.permissions; @UseFilters(new GrpcToHttpExceptionFilter()) @@ -83,12 +84,11 @@ export class ConnectionController { @RequireAllPermissions(connectionPermissions.CREATE) async updateConnection( @User() user: RequestUser, - @Headers('Dadosfera-Lang') language: string, + @Language() language: LanguageEnum, @Param('id') id: string, @Body(new ValidationPipe()) body: UpdateConnectionDto, ): Promise { this.logger.info('/connections - Update Connection'); - if (!language) language = 'en-us'; const { user_id, customer_id, customer_name, username } = user; const metadata = PackTheMetadata({ @@ -135,11 +135,10 @@ export class ConnectionController { @Get() async getAllConnections( @User() user: RequestUser, - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Query() queries, ): Promise { this.logger.info('/connections - Get All Connection'); - if (!language) language = 'en-us'; const { user_id, customer_id, customer_name, username } = user; const { search, size, page, ...filters } = queries; @@ -161,13 +160,12 @@ export class ConnectionController { @Get('/:id') async getConnectionDetails( - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @User() user: RequestUser, @Param('id') id, @Query() queries, ): Promise { this.logger.info('/connections - Get Connection Details'); - if (!language) language = 'en-us'; console.log(queries); diff --git a/src/modules/connector/connector.controller.ts b/src/modules/connector/connector.controller.ts index badf102..a786912 100644 --- a/src/modules/connector/connector.controller.ts +++ b/src/modules/connector/connector.controller.ts @@ -11,7 +11,6 @@ import { UploadedFile, UseInterceptors, Inject, - Headers, UploadedFiles, } from '@nestjs/common'; import { FileInterceptor, FilesInterceptor } from '@nestjs/platform-express'; @@ -29,6 +28,8 @@ import { RequireSomePermission, } from 'src/decorators/authentication.decorator'; import { PERMISSIONS_GROUPS } from 'src/authentication/permissions.enum'; +import { Language } from 'src/decorators/language.decorator'; +import { LanguageEnum } from 'src/utils/languages.enum'; @ApiTags('connectors') @Authenticated() @@ -97,11 +98,10 @@ export class ConnectorController { PERMISSIONS_GROUPS.PIPELINE.permissions.DELETE, ) async getAllConnectors( - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, @Query() queries: GetAllDto, ) { this.logger.info('/GET - getAllConnectors Route'); - if (!language) language = 'en-us'; const { search, size, page, ...filters } = queries; @@ -142,12 +142,11 @@ export class ConnectorController { PERMISSIONS_GROUPS.PIPELINE.permissions.DELETE, ) async getConnector( - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, @Param('plugin') plugin: string, @Query('version') version: string, ) { this.logger.info('/GET/:plugin - getConnector Route'); - if (!language) language = 'en-us'; const pluginId = `${plugin}-${version}`; @@ -171,13 +170,11 @@ export class ConnectorController { PERMISSIONS_GROUPS.PIPELINE.permissions.DELETE, ) async getConnectorDetails( - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, @Param('plugin') plugin: string, @Query('version') version: string, ) { this.logger.info('/upload - Upload Connector Route'); - if (!language) language = 'en-us'; - const pluginId = `${plugin}-${version}`; const response: any = await this.connectorClientService.getConnectorDetails( diff --git a/src/modules/network-config/network-config.controller.ts b/src/modules/network-config/network-config.controller.ts index 3e1291c..26c0df7 100644 --- a/src/modules/network-config/network-config.controller.ts +++ b/src/modules/network-config/network-config.controller.ts @@ -1,12 +1,9 @@ import { Body, Controller, - Delete, Get, - Headers, Inject, Param, - Patch, Post, Query, UploadedFile, @@ -27,6 +24,8 @@ import { Authenticated, RequireAllPermissions, } from 'src/decorators/authentication.decorator'; +import { Language } from 'src/decorators/language.decorator'; +import { LanguageEnum } from 'src/utils/languages.enum'; const networkConfigPermissions = PERMISSIONS_GROUPS.NETWORK_CONFIG.permissions; @ApiTags('Network Config') @@ -44,14 +43,13 @@ export class NetworkConfigController { @ApiOkResponse({ type: FindAllNetworkConfigsRes }) async findAllNetworkConfigs( @User() user: RequestUser, - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Query() queries, ) { this.logger.info('GET /network-config', { user: user.user_id, customer: user.customer_name, }); - if (!language) language = 'en-us'; const { user_id, customer_id, customer_name } = user; const { search, size, page, ...filters } = queries; @@ -79,14 +77,14 @@ export class NetworkConfigController { @ApiOkResponse({ type: FindAllNetworkConfigsRes }) async findNetworkConfigByIdDetails( @User() user: RequestUser, - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Param('id') id: string, ) { this.logger.info('GET /network-config/:id', { user: user.user_id, customer: user.customer_name, }); - if (!language) language = 'en-us'; + return this.networkConfigService.findNetworkConfigByIdDetails(id, { customer_name: user.customer_name, customer_id: user.customer_id, diff --git a/src/modules/oauth/oauth.controller.ts b/src/modules/oauth/oauth.controller.ts index 518dd24..2feb441 100644 --- a/src/modules/oauth/oauth.controller.ts +++ b/src/modules/oauth/oauth.controller.ts @@ -15,7 +15,6 @@ export class OauthController { private logger: DadosferaLogger, ) { switch (process.env.ENV) { - case 'dev': case 'stg': this.redirectUrl = `https://app.${process.env.ENV}.dadosfera.ai/collect/auth-callback`; break; diff --git a/src/modules/oauth/passport-strategies/google-strategy.ts b/src/modules/oauth/passport-strategies/google-strategy.ts index 1bd6ffc..972ebc4 100644 --- a/src/modules/oauth/passport-strategies/google-strategy.ts +++ b/src/modules/oauth/passport-strategies/google-strategy.ts @@ -29,7 +29,6 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { super(options, verify); switch (process.env.ENV) { - case 'dev': case 'stg': this.redirect_uri = `https://maestro.${process.env.ENV}.dadosfera.ai/oauth`; break; diff --git a/src/modules/permissions/permissions.controller.ts b/src/modules/permissions/permissions.controller.ts index ad51354..45b46d0 100644 --- a/src/modules/permissions/permissions.controller.ts +++ b/src/modules/permissions/permissions.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Headers, Inject } from '@nestjs/common'; +import { Controller, Get, Inject } from '@nestjs/common'; import { ApiHeader, ApiOkResponse, ApiTags } from '@nestjs/swagger'; import { DadosferaLogger } from '@dadosfera/dadosfera-logs'; import { Authenticated } from 'src/decorators/authentication.decorator'; @@ -7,6 +7,7 @@ import { RequestUser, User } from 'src/decorators/user.decorator'; import { LanguageEnum } from 'src/utils/languages.enum'; import { GetPublicPermissionsRes } from './dto/entities'; import { PermissionsService } from './permissions.service'; +import { Language } from 'src/decorators/language.decorator'; @ApiTags('Permissions') @Authenticated() @@ -32,10 +33,10 @@ export class PermissionsController { @ApiOkResponse({ type: GetPublicPermissionsRes }) getPublicPermissions( @User() user: RequestUser, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('getPublicPermissions', { user }); - if (!language) language = 'en-us'; + const permissionGroups = this.permissionsService.getPermissionsGrouped( PermissionUsages.PUBLIC, language, diff --git a/src/modules/pipelinesV2/pipelines.controller.ts b/src/modules/pipelinesV2/pipelines.controller.ts index ab3093e..66d5e1e 100644 --- a/src/modules/pipelinesV2/pipelines.controller.ts +++ b/src/modules/pipelinesV2/pipelines.controller.ts @@ -7,7 +7,6 @@ import { Param, Post, Put, - Headers, Query, UseFilters, HttpCode, @@ -18,6 +17,7 @@ import { } from '@nestjs/common'; import { ApiCreatedResponse, + ApiHeaders, ApiNoContentResponse, ApiOperation, ApiTags, @@ -42,8 +42,12 @@ import { IInitUploadCSVFile, } from './interfaces'; import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter'; -@UseFilters(new GrpcToHttpExceptionFilter()) +import { LanguageEnum } from 'src/utils/languages.enum'; +import { Language } from 'src/decorators/language.decorator'; + @ApiTags('PipelinesV2') +@ApiHeaders([{ name: 'dadosfera-lang', enum: LanguageEnum, required: false }]) +@UseFilters(new GrpcToHttpExceptionFilter()) @Controller('pipelinesV2') @AuthenticateCondition((req, user) => { let action; @@ -83,12 +87,12 @@ export class PipelinesController { @Post() @ApiCreatedResponse({ type: IPipelineV2 }) async create( - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @User() user: RequestUser, @Body() createPipelineDto: ICreatePipelineV2Req, ) { this.logger.info('PipelinesController - create', { user }); - if (!language) language = 'en-us'; + const { customer_id, customer_name, username, user_id } = user; const metadata = PackTheMetadata({ customer_id, @@ -109,13 +113,11 @@ export class PipelinesController { @Get() async findAll( @User() user: RequestUser, - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Query() data, ) { this.logger.info('PipelinesController - findAll', { user }); - if (!language) language = 'en-us'; - const { customer_id, customer_name, user_id, username } = user; const metadata = PackTheMetadata({ customer_id, @@ -135,13 +137,11 @@ export class PipelinesController { @Get('/download-logs') async downloadLogs( @User() user: RequestUser, - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Query('pipeline_run_id') pipeline_run_id: string, ) { this.logger.info('PipelinesController - downloadLogs', { user }); - if (!language) language = 'en-us'; - if (!pipeline_run_id) throw new BadRequestException('Missing pipeline_run_id'); @@ -166,29 +166,23 @@ export class PipelinesController { @Get(':id/config') async getPipelineproperties( - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @User() user: RequestUser, @Param('id') id, ) { this.logger.info('PipelinesController - getPipelineproperties', { user }); - const metadata = PackTheMetadata({ - ...user, - language: language || 'pt-br', - }); + const metadata = PackTheMetadata({ ...user, language: language }); return this.pipelinesClientService.findOneProperties(id, metadata); } @Get(':id/objects') async getPipelineObjects( - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @User() user: RequestUser, @Param('id') id, ) { this.logger.info('PipelinesController - getPipelineObjects', { user }); - const metadata = PackTheMetadata({ - ...user, - language: language || 'pt-br', - }); + const metadata = PackTheMetadata({ ...user, language: language }); return this.pipelinesClientService.findOneObjects(id, metadata); } @@ -212,14 +206,12 @@ export class PipelinesController { @Get('/:id') async findOne( - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @User() user: RequestUser, @Param('id') id, ): Promise { this.logger.info('PipelinesController - findOne', { user }); - if (!language) language = 'en-us'; - const { customer_id, customer_name, user_id, username } = user; const metadata = PackTheMetadata({ @@ -255,7 +247,7 @@ export class PipelinesController { @Patch('/:id') async update( - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Body() updatePipelineDto, @Param('id') id, @User() user: RequestUser, @@ -265,7 +257,6 @@ export class PipelinesController { delete updatePipelineDto.info; const { customer_id, customer_name, user_id, username } = user; - if (!language) language = 'en-us'; const metadata = PackTheMetadata({ customer_id, @@ -294,7 +285,7 @@ export class PipelinesController { description: 'This method is deprecated. Please use PATCH instead', }) async updateDeprecated( - @Headers('Dadosfera-Lang') language, + @Language() language: LanguageEnum, @Body() updatePipelineDto, @Param('id') id, @User() user: RequestUser, diff --git a/src/modules/roles/roles.controller.ts b/src/modules/roles/roles.controller.ts index 038245c..f3fa0bb 100644 --- a/src/modules/roles/roles.controller.ts +++ b/src/modules/roles/roles.controller.ts @@ -3,7 +3,6 @@ import { Controller, Delete, Get, - Headers, Inject, Param, Patch, @@ -14,7 +13,7 @@ import { } from '@nestjs/common'; import { ApiCreatedResponse, - ApiHeader, + ApiHeaders, ApiOkResponse, ApiTags, } from '@nestjs/swagger'; @@ -45,14 +44,10 @@ import { RequireAllPermissions, } from 'src/decorators/authentication.decorator'; import { LanguageEnum } from 'src/utils/languages.enum'; +import { Language } from 'src/decorators/language.decorator'; @ApiTags('Roles') -@ApiHeader({ - name: 'dadosfera-lang', - enum: LanguageEnum, - required: false, - description: 'Defaults to pt-br', -}) +@ApiHeaders([{ name: 'dadosfera-lang', enum: LanguageEnum, required: false }]) @Authenticated() @UseFilters(new GrpcToHttpExceptionFilter()) @Controller('roles') @@ -72,7 +67,7 @@ export class RolesController { async searchRoles( @User() user: RequestUser, @Query() params: GetRolesByCustomerReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('searchRoles', { user }); this.rolesService.setLanguage(language); @@ -85,7 +80,7 @@ export class RolesController { async createRole( @User() user: RequestUser, @Body() body: CreateRoleReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('createRole', { user }); this.rolesService.setLanguage(language); @@ -98,7 +93,7 @@ export class RolesController { async grantPermissionsToRole( @User() user: RequestUser, @Body() body: GrantPermissionsToRoleReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('grantPermissionsToRole', { user }); this.rolesService.setLanguage(language); @@ -111,7 +106,7 @@ export class RolesController { async revokePermissionsFromRole( @User() user: RequestUser, @Body() body: RevokePermissionsFromRoleReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('revokePermissionsToRole', { user }); this.rolesService.setLanguage(language); @@ -124,7 +119,7 @@ export class RolesController { async setRolePermissions( @User() user: RequestUser, @Body() body: SetRolePermissionsReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('setRolePermissions', { user }); this.rolesService.setLanguage(language); @@ -137,7 +132,7 @@ export class RolesController { async setRoleUsers( @User() user: RequestUser, @Body() body: SetRoleUsersReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('setRoleUsers', { user }); this.rolesService.setLanguage(language); @@ -150,7 +145,7 @@ export class RolesController { async getRoleById( @User() user: RequestUser, @Param('id') id: string, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('getRoleById', { user }); this.rolesService.setLanguage(language); @@ -162,7 +157,7 @@ export class RolesController { async deleteRole( @User() user: RequestUser, @Param('id') id: string, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('deleteRole', { user }); this.rolesService.setLanguage(language); @@ -176,7 +171,7 @@ export class RolesController { @User() user: RequestUser, @Param('id') id: string, @Body() body: UpdateRoleReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('updateRole', { user }); this.rolesService.setLanguage(language); diff --git a/src/modules/termsOfUse/termsOfUse.controller.ts b/src/modules/termsOfUse/termsOfUse.controller.ts index 55279ff..7d23139 100644 --- a/src/modules/termsOfUse/termsOfUse.controller.ts +++ b/src/modules/termsOfUse/termsOfUse.controller.ts @@ -9,7 +9,7 @@ import { Headers, UseFilters, } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; +import { ApiHeaders, ApiTags } from '@nestjs/swagger'; import { TermsOfUseAcceptRequest } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages'; import { TermsOfUseClientService } from './termsOfUse.service'; @@ -18,8 +18,11 @@ import { DadosferaLogger } from '@dadosfera/dadosfera-logs'; import { GrpcToHttpExceptionFilter } from '../../error/grpc-to-http-exception.filter'; import { RequestUser, User } from '../../decorators/user.decorator'; import { Metadata } from '@grpc/grpc-js'; +import { Language } from 'src/decorators/language.decorator'; +import { LanguageEnum } from 'src/utils/languages.enum'; @ApiTags('TermsOfUse') +@ApiHeaders([{ name: 'dadosfera-lang', enum: LanguageEnum, required: false }]) @UseFilters(new GrpcToHttpExceptionFilter()) @Controller('terms-of-use') export class TermsOfUseController { @@ -36,7 +39,7 @@ export class TermsOfUseController { @Get('token') async getToken( @User({ required: true }) user: RequestUser, - @Headers('Dadosfera-Lang') language: string, + @Language() language: LanguageEnum, ) { this.logger.info('/terms-of-use - get token'); const metadata = new Metadata(); diff --git a/src/modules/users/users.controller.ts b/src/modules/users/users.controller.ts index c05fb27..308d4fd 100644 --- a/src/modules/users/users.controller.ts +++ b/src/modules/users/users.controller.ts @@ -4,7 +4,6 @@ import { Controller, Delete, Get, - Headers, HttpCode, HttpStatus, Inject, @@ -17,7 +16,7 @@ import { } from '@nestjs/common'; import { ApiCreatedResponse, - ApiHeader, + ApiHeaders, ApiOkResponse, ApiTags, } from '@nestjs/swagger'; @@ -26,6 +25,7 @@ import { Authenticated, RequireAllPermissions, } from 'src/decorators/authentication.decorator'; +import { Language } from 'src/decorators/language.decorator'; import { RequestUser, User } from 'src/decorators/user.decorator'; import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filter'; import { PackTheMetadata } from 'src/utils/ PackTheMetadata'; @@ -54,12 +54,7 @@ import { UsersService } from './users.service'; @ApiTags('Users') @Controller('users') -@ApiHeader({ - name: 'dadosfera-lang', - enum: LanguageEnum, - required: false, - description: 'Defaults to pt-br', -}) +@ApiHeaders([{ name: 'dadosfera-lang', enum: LanguageEnum, required: false }]) @Authenticated() @UseFilters(GrpcToHttpExceptionFilter) export class UsersController { @@ -76,7 +71,7 @@ export class UsersController { @Get() async getAllUsersByCustomerId( @User() user: RequestUser, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ): Promise { this.logger.info('getAllUsersByCustomerId', { user }); this.userService.setLanguage(language); @@ -88,7 +83,7 @@ export class UsersController { @ApiOkResponse({ type: GetAllHierarchiesRes }) async getAllHierarchies( @User() user: RequestUser, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ): Promise { this.logger.info('getAllHierarchies', { user }); this.userService.setLanguage(language); @@ -100,7 +95,7 @@ export class UsersController { @ApiOkResponse({ type: GetAllDepartmentsRes }) async getAllDepartments( @User() user: RequestUser, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ): Promise { this.logger.info('getAllHierarchies', { user }); this.userService.setLanguage(language); @@ -112,7 +107,7 @@ export class UsersController { @ApiOkResponse({ type: GetAllDepartmentsRes }) async getAllJobTitles( @User() user: RequestUser, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ): Promise { this.logger.info('getAllHierarchies', { user }); this.userService.setLanguage(language); @@ -126,7 +121,7 @@ export class UsersController { async findOneById( @User() user: RequestUser, @Param('id') id: string, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('findOneById', { user }); this.userService.setLanguage(language); @@ -147,7 +142,7 @@ export class UsersController { async createUser( @User() user: RequestUser, @Body() body: CreateUserReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { const metadata = PackTheMetadata({ access_token: user.access_token, @@ -165,7 +160,7 @@ export class UsersController { async batchCreateUser( @User() user: RequestUser, @Body() body: BatchCreateUserReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('batchCreateUser', { user }); this.userService.setLanguage(language); @@ -184,7 +179,7 @@ export class UsersController { async resendInvite( @User() user: RequestUser, @Param('id') id: string, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('resendInvite', { user }); this.userService.setLanguage(language); @@ -200,7 +195,7 @@ export class UsersController { async unassignRoleToUser( @User() user: RequestUser, @Query() request: UnassignRoleToUserReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('unassignRoleToUser', { user }); this.userService.setLanguage(language); @@ -213,7 +208,7 @@ export class UsersController { async deleteUser( @User() user: RequestUser, @Param('id') id: string, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('deleteUser', { user }); this.userService.setLanguage(language); @@ -226,7 +221,7 @@ export class UsersController { async setUserRoles( @User() user: RequestUser, @Body() body: SetUserRolesReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('createUser', { user }); this.userService.setLanguage(language); @@ -238,7 +233,7 @@ export class UsersController { async assignRoleToUser( @User() user: RequestUser, @Body() body: AssignRoleToUserReq, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('assignRoleToUser', { user }); this.userService.setLanguage(language); @@ -252,7 +247,7 @@ export class UsersController { @User() user: RequestUser, @Body() body: UpdateUserReq, @Param('id') id: string, - @Headers('dadosfera-lang') language, + @Language() language: LanguageEnum, ) { this.logger.info('updateUser', { user }); this.userService.setLanguage(language);