diff --git a/README.md b/README.md index c3eeebb..028ca81 100644 --- a/README.md +++ b/README.md @@ -82,10 +82,12 @@ Atualmente, estamos gerando **2 documentações diferentes**: Interna e Externa. Todas as rotas que têm o decorador `@ApiInternalOnly()` não serão visíveis no swagger da API **Externa**. -- Quando você inicia a aplicação com `npm run start`, ela servirá e gerará o JSON do swagger da API **Externa** -- Quando você inicia a aplicação com `npm run start:internal`, ela servirá e gerará o JSON do swagger da API **Interna** +- Quando você inicia a aplicação com `npm run start:dev`, ela servirá e gerará o JSON do swagger da API **Interna** + - Quando você executa `npm run docs`, ele gerará o JSON do swagger de ambas as APIs **Interna** e **Externa** e os salvará em `docsfera.json` e `docsfera.external.json`, respectivamente; +> Link para documentação interna: https://dadosfera.github.io/docsfera + É importante executar `npm run docs` antes de cada implantação para que sempre tenhamos as documentações mais atualizadas publicadas. ## Decoradores de autenticação diff --git a/docsfera.json b/docsfera.json index ffa7a1d..1df2238 100644 --- a/docsfera.json +++ b/docsfera.json @@ -4513,6 +4513,280 @@ ] } }, + "/catalog/rls-rule": { + "post": { + "operationId": "CatalogController_addRlsRule", + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Catalog" + ], + "security": [ + { + "access-token": [] + }, + { + "access-token": [] + } + ] + }, + "get": { + "operationId": "CatalogController_getRlsRules", + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "object" + } + } + } + } + } + }, + "tags": [ + "Catalog" + ], + "security": [ + { + "access-token": [] + }, + { + "access-token": [] + } + ] + }, + "delete": { + "operationId": "CatalogController_batchRemoveRlsRules", + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, + { + "name": "nimbus_dashboard_id", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "id_rls", + "required": false, + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "Catalog" + ], + "security": [ + { + "access-token": [] + }, + { + "access-token": [] + } + ] + } + }, + "/catalog/rls-rule/{id}": { + "get": { + "operationId": "CatalogController_getOneRlsRule", + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Catalog" + ], + "security": [ + { + "access-token": [] + }, + { + "access-token": [] + } + ] + }, + "delete": { + "operationId": "CatalogController_removeRlsRule", + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + }, + { + "name": "id", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Catalog" + ], + "security": [ + { + "access-token": [] + }, + { + "access-token": [] + } + ] + } + }, + "/catalog/nimbus-dashboards": { + "get": { + "operationId": "CatalogController_getNimbusDashboards", + "parameters": [ + { + "name": "dadosfera-lang", + "in": "header", + "required": false, + "schema": { + "enum": [ + "pt-br", + "en-us" + ], + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Catalog" + ], + "security": [ + { + "access-token": [] + }, + { + "access-token": [] + } + ] + } + }, "/terms-of-use/token": { "get": { "operationId": "TermsOfUseController_getToken", @@ -5173,7 +5447,7 @@ } }, "info": { - "title": "Maestro - main", + "title": "Maestro - feat/rls", "description": "This is the Maestro API", "version": "1.0.0", "contact": {} diff --git a/package-lock.json b/package-lock.json index 4af5cd5..61e212a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@aws-sdk/client-secrets-manager": "^3.414.0", "@dadosfera/dadosfera-logs": "^1.0.0-beta.4", "@dadosfera/protospack": "2.5.3", - "@dadosfera/protospack-v2": "3.33.1-beta.2", + "@dadosfera/protospack-v2": "3.34.0", "@grpc/grpc-js": "^1.9.3", "@grpc/proto-loader": "^0.7.9", "@nestjs/cli": "^9.5.0", @@ -1404,9 +1404,9 @@ } }, "node_modules/@dadosfera/protospack-v2": { - "version": "3.33.1-beta.2", - "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.33.1-beta.2.tgz", - "integrity": "sha512-iXvJWacU8HcueIArw7iI5TLeHb6/ZSEUcDwPUjhiSddTGnq3+kHTDkon8UEzgmhyEDmUp3BT4hHuufQmzE46sA==", + "version": "3.34.0", + "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.34.0.tgz", + "integrity": "sha512-VUjpoHg5/uNNkg1cTxWbUv+20t5CTAf1tB4dhBmGSYjgb+Efo5gi3aO/p3ajYuzOOMOxF+EhjQVouU6BD3E+Xg==", "dependencies": { "@grpc/grpc-js": "^1.9.3", "rxjs": "^7.5.5" diff --git a/package.json b/package.json index 8feaa04..b750615 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "@aws-sdk/client-secrets-manager": "^3.414.0", "@dadosfera/dadosfera-logs": "^1.0.0-beta.4", "@dadosfera/protospack": "2.5.3", - "@dadosfera/protospack-v2": "3.33.1-beta.2", + "@dadosfera/protospack-v2": "3.34.0", "@grpc/grpc-js": "^1.9.3", "@grpc/proto-loader": "^0.7.9", "@nestjs/cli": "^9.5.0", diff --git a/src/modules/catalog/catalog.controller.ts b/src/modules/catalog/catalog.controller.ts index 4f86deb..0a594d3 100644 --- a/src/modules/catalog/catalog.controller.ts +++ b/src/modules/catalog/catalog.controller.ts @@ -31,6 +31,7 @@ import { DadosferaLogger } from '@dadosfera/dadosfera-logs'; import { PackTheMetadata } from 'src/utils/ PackTheMetadata'; import { RequestUser, User } from 'src/decorators/user.decorator'; import { + BatchRemoveRlsRulesRequest, GetDatasetCatalogTaskRes, ICatalogAllRequest, ICatalogAllResponse, @@ -49,6 +50,11 @@ import { GrpcToHttpExceptionFilter } from 'src/error/grpc-to-http-exception.filt import { Language } from 'src/decorators/language.decorator'; import { LanguageEnum } from 'src/utils/languages.enum'; import { ApiInternalOnlyEndpoint } from 'src/decorators/swagger.decorator'; +import { + AddRlsRuleRequest, + GetNimbusDashboardsRequest, + GetRlsRulesRequest, +} from '@dadosfera/protospack-v2/dist/lib/Catalog/interfaces/messages'; @ApiTags('Catalog') @ApiHeaders([{ name: 'dadosfera-lang', enum: LanguageEnum, required: false }]) @@ -633,4 +639,108 @@ export class CatalogController { return response; } + + @Post('rls-rule') + @RequireAllPermissions(PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER) + async addRlsRule(@User() user: RequestUser, @Body() body: AddRlsRuleRequest) { + const { customer_id, customer_name, user_id, username } = user; + const metadata = PackTheMetadata({ + customer_id, + customer_name, + user_id, + username, + }); + const response = await this.catalogService.addRlsRule(body, metadata); + + return response; + } + + @Get('rls-rule/:id') + @RequireAllPermissions(PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER) + async getOneRlsRule(@Param('id') id: string, @User() user: RequestUser) { + const { customer_id, customer_name, user_id, username } = user; + const metadata = PackTheMetadata({ + customer_id, + customer_name, + user_id, + username, + }); + const idInt = parseInt(id); + const response = await this.catalogService.getOneRlsRule(idInt, metadata); + + return response; + } + + @Get('rls-rule') + @RequireAllPermissions(PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER) + async getRlsRules( + @User() user: RequestUser, + @Query() query: GetRlsRulesRequest, + ) { + const { customer_id, customer_name, user_id, username } = user; + const metadata = PackTheMetadata({ + customer_id, + customer_name, + user_id, + username, + }); + const response = await this.catalogService.getRlsRules(query, metadata); + + return response; + } + + @Delete('rls-rule/:id') + @RequireAllPermissions(PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER) + async removeRlsRule(@Param('id') id: string, @User() user: RequestUser) { + const { customer_id, customer_name, user_id, username } = user; + const metadata = PackTheMetadata({ + customer_id, + customer_name, + user_id, + username, + }); + const idInt = parseInt(id); + const response = await this.catalogService.removeRlsRule(idInt, metadata); + + return response; + } + + @Delete('rls-rule') + @RequireAllPermissions(PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER) + async batchRemoveRlsRules( + @Query() query: BatchRemoveRlsRulesRequest, + @User() user: RequestUser, + ) { + const { customer_id, customer_name, user_id, username } = user; + const metadata = PackTheMetadata({ + customer_id, + customer_name, + user_id, + username, + }); + await this.catalogService.batchRemoveRlsRule(query, metadata); + + return { message: 'OK' }; + } + + @Get('nimbus-dashboards') + @RequireAllPermissions(PERMISSIONS_GROUPS.CATALOG.permissions.DATA_MANAGER) + async getNimbusDashboards( + @User() user: RequestUser, + @Body() body: GetNimbusDashboardsRequest, + ) { + const { customer_id, customer_name, user_id, username } = user; + const metadata = PackTheMetadata({ + customer_id, + customer_name, + user_id, + username, + }); + const dashboards = await this.catalogService.getNimbusDashboards( + body, + metadata, + ); + + return JSON.parse(dashboards); + } } diff --git a/src/modules/catalog/catalog.service.ts b/src/modules/catalog/catalog.service.ts index 6f743c1..00d188e 100644 --- a/src/modules/catalog/catalog.service.ts +++ b/src/modules/catalog/catalog.service.ts @@ -6,6 +6,7 @@ import { Messages, } from '@dadosfera/protospack-v2/dist/lib/Catalog'; import { + BadRequestException, HttpException, HttpStatus, Inject, @@ -18,7 +19,16 @@ import { CatalogClientConfiguration } from './catalog-client'; import { UsersService } from '../users/users.service'; import { RolesService } from '../roles/roles.service'; import { Metadata } from '@grpc/grpc-js'; -import { IUpdateDataRequest, TriggerCatalogReq } from './dtos'; +import { + BatchRemoveRlsRulesRequest, + IUpdateDataRequest, + TriggerCatalogReq, +} from './dtos'; +import { + AddRlsRuleRequest, + GetNimbusDashboardsRequest, + GetRlsRulesRequest, +} from '@dadosfera/protospack-v2/dist/lib/Catalog/interfaces/messages'; class CatalogService implements OnModuleInit { catalogReadService: ReadService.CatalogReadServices; @@ -333,6 +343,7 @@ class CatalogService implements OnModuleInit { } as typeof data_asset; }); } + async triggerCatalog(data: TriggerCatalogReq, metadata: Metadata) { const { session } = await lastValueFrom( this.catalogWriteService.TriggerDatasetCataloging(data, metadata), @@ -345,6 +356,70 @@ class CatalogService implements OnModuleInit { ); return res; } + + async addRlsRule(data: AddRlsRuleRequest, metadata: Metadata) { + const res = await lastValueFrom( + this.catalogWriteService.AddRlsRule(data, metadata), + ); + return res; + } + + async removeRlsRule(id: number, metadata: Metadata) { + const res = await lastValueFrom( + this.catalogWriteService.RemoveRlsRule({ id }, metadata), + ); + return res; + } + + async batchRemoveRlsRule( + query: BatchRemoveRlsRulesRequest, + metadata: Metadata, + ) { + const { id_rls, nimbus_dashboard_id } = query; + + if (id_rls && nimbus_dashboard_id) { + throw new BadRequestException( + "You can't delete using both parameters. Choose either 'id_rls' or 'nimbus_dashboard_id'", + ); + } + if (id_rls) { + await lastValueFrom( + this.catalogWriteService.RemoveRlsRulesByRlsId({ id_rls }, metadata), + ); + } else if (nimbus_dashboard_id) { + await lastValueFrom( + this.catalogWriteService.RemoveRlsRulesByDashboardId( + { nimbus_dashboard_id: parseInt(nimbus_dashboard_id) }, + metadata, + ), + ); + } + return 'OK'; + } + + async getRlsRules(data: GetRlsRulesRequest, metadata: Metadata) { + const res = await lastValueFrom( + this.catalogReadService.GetRlsRules(data, metadata), + ); + return res.rls_rules; + } + + async getOneRlsRule(id: number, metadata: Metadata) { + const res = await lastValueFrom( + this.catalogReadService.GetOneRlsRule({ id }, metadata), + ); + return res.rls_rule; + } + + async getNimbusDashboards( + data: GetNimbusDashboardsRequest, + metadata: Metadata, + ) { + const res = await lastValueFrom( + this.catalogReadService.GetNimbusDashboards(data, metadata), + ); + return res.dashboards; + } } export { CatalogService }; diff --git a/src/modules/catalog/dtos/index.ts b/src/modules/catalog/dtos/index.ts index d7d135f..b869e5e 100644 --- a/src/modules/catalog/dtos/index.ts +++ b/src/modules/catalog/dtos/index.ts @@ -312,3 +312,11 @@ export class GetDatasetCatalogTaskRes { @ApiProperty() updated_by: string; } + +export class BatchRemoveRlsRulesRequest { + @ApiPropertyOptional() + nimbus_dashboard_id?: string; + + @ApiPropertyOptional() + id_rls?: string; +}