diff --git a/docsfera.json b/docsfera.json index 801658d..425263d 100644 --- a/docsfera.json +++ b/docsfera.json @@ -10100,6 +10100,21 @@ "entities" ] }, + "Column": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "name", + "type" + ] + }, "TableColumns": { "type": "object", "properties": { @@ -10115,17 +10130,25 @@ "references": { "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/Column" } }, "type": { "type": "string" + }, + "identifier_columns": { + "type": "array", + "items": { + "type": "string" + } + }, + "reference_column": { + "$ref": "#/components/schemas/Column" } }, "required": [ "name", "columns", - "references", "type" ] }, @@ -10405,6 +10428,114 @@ "engine" ] }, + "ValidationTableDTO": { + "type": "object", + "properties": { + "tables": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "tables" + ] + }, + "EnforceMfa": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled" + ] + }, + "CustomerLinkItem": { + "type": "object", + "properties": { + "href": { + "type": "string" + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "iconSrc": { + "type": "string" + } + }, + "required": [ + "href", + "name", + "description" + ] + }, + "CustomerSidebarSection": { + "type": "object", + "properties": { + "title": { + "type": "object" + }, + "items": { + "type": "array", + "items": { + "oneOf": [ + { + "$ref": "#/components/schemas/CustomerSidebarMenuItem" + }, + { + "$ref": "#/components/schemas/CustomerSidebarLinkItem" + } + ] + } + } + }, + "required": [ + "title", + "items" + ] + }, + "CustomerLinksConfig": { + "type": "object", + "properties": { + "home": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerLinkItem" + } + }, + "sidebar": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerSidebarSection" + } + } + } + }, + "CustomerLinksResponse": { + "type": "object", + "properties": { + "links": { + "$ref": "#/components/schemas/CustomerLinksConfig" + } + } + }, + "CustomerLinkRequest": { + "type": "object", + "properties": { + "links": { + "$ref": "#/components/schemas/CustomerLinksConfig" + } + }, + "required": [ + "links" + ] + }, "IRole": { "type": "object", "properties": { @@ -11005,7 +11136,7 @@ "enabled" ] }, - "CustomerLink": { + "CustomerLinkItem": { "type": "object", "properties": { "href": { @@ -11027,28 +11158,61 @@ "description" ] }, - "CustomerLinksResponse": { + "CustomerSidebarSection": { "type": "object", "properties": { - "links": { + "title": { + "type": "string" + }, + "items": { "type": "array", "items": { - "$ref": "#/components/schemas/CustomerLink" + "oneOf": [ + { + "$ref": "#/components/schemas/CustomerSidebarMenuItem" + }, + { + "$ref": "#/components/schemas/CustomerSidebarLinkItem" + } + ] } } }, "required": [ - "links" + "title", + "items" ] }, + "CustomerLinksConfig": { + "type": "object", + "properties": { + "home": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerLinkItem" + } + }, + "sidebar": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerSidebarSection" + } + } + } + }, + "CustomerLinksResponse": { + "type": "object", + "properties": { + "links": { + "$ref": "#/components/schemas/CustomerLinksConfig" + } + } + }, "CustomerLinkRequest": { "type": "object", "properties": { "links": { - "type": "array", - "items": { - "$ref": "#/components/schemas/CustomerLink" - } + "$ref": "#/components/schemas/CustomerLinksConfig" } }, "required": [ diff --git a/package-lock.json b/package-lock.json index 4d90eb7..592117e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@aws-sdk/signature-v4": "^3.370.0", "@dadosfera/dadosfera-logs": "^1.0.0-beta.4", "@dadosfera/protospack": "2.5.3", - "@dadosfera/protospack-v2": "^3.38.0-beta.26", + "@dadosfera/protospack-v2": "^3.39.0", "@grpc/grpc-js": "^1.9.3", "@grpc/proto-loader": "^0.7.9", "@nestjs/cli": "^9.5.0", @@ -47,6 +47,7 @@ "jwk-to-pem": "^2.0.5", "mixpanel": "^0.17.0", "ms": "^3.0.0-canary.1", + "multer": "^2.0.2", "openid-client": "^5.7.1", "passport": "^0.6.0", "passport-facebook": "^3.0.0", @@ -1744,9 +1745,9 @@ } }, "node_modules/@dadosfera/protospack-v2": { - "version": "3.38.0-beta.26", - "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.38.0-beta.26.tgz", - "integrity": "sha512-N8NS7+djLGy0wJXk00+4oupqd/wBIQ1f+YBBhK2y9x4guFXYK1KWIrPZhPj+gaU8g2KNkqKoT7SnE9PXNxlLSQ==", + "version": "3.39.0", + "resolved": "https://dadosfera-611330257153.d.codeartifact.us-east-1.amazonaws.com/npm/dadosfera-npm/@dadosfera/protospack-v2/-/protospack-v2-3.39.0.tgz", + "integrity": "sha512-z6q+ZRpbDT6apfmly1+X818DgAFUCilFO0ATP7xR5+SH+GAUAJLY1dJRQDEkq5vFIfXnC2Nmm9aODZAs+9/5vw==", "dependencies": { "@grpc/grpc-js": "^1.9.3", "rxjs": "^7.5.5" @@ -2927,6 +2928,20 @@ "node": ">= 0.6" } }, + "node_modules/@nestjs/platform-express/node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "node_modules/@nestjs/platform-express/node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -3096,6 +3111,24 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/@nestjs/platform-express/node_modules/multer": { + "version": "1.4.4-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", + "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", + "deprecated": "Multer 1.x is impacted by a number of vulnerabilities, which have been patched in 2.x. You should upgrade to the latest 2.x version.", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/@nestjs/platform-express/node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", @@ -3120,6 +3153,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/@nestjs/platform-express/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/@nestjs/platform-express/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/@nestjs/platform-express/node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -3194,6 +3246,19 @@ "node": ">= 0.8" } }, + "node_modules/@nestjs/platform-express/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/@nestjs/platform-express/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "node_modules/@nestjs/platform-express/node_modules/tslib": { "version": "2.5.3", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", @@ -6508,7 +6573,6 @@ "engines": [ "node >= 6.0" ], - "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -9127,6 +9191,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -10724,7 +10793,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz", "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==", - "license": "MIT", "dependencies": { "append-field": "^1.0.0", "busboy": "^1.6.0", @@ -11727,6 +11795,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/process-warning": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/process-warning/-/process-warning-1.0.0.tgz", diff --git a/package.json b/package.json index 4fd10bd..6afe185 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@aws-sdk/signature-v4": "^3.370.0", "@dadosfera/dadosfera-logs": "^1.0.0-beta.4", "@dadosfera/protospack": "2.5.3", - "@dadosfera/protospack-v2": "^3.38.0-beta.26", + "@dadosfera/protospack-v2": "^3.39.0", "@grpc/grpc-js": "^1.9.3", "@grpc/proto-loader": "^0.7.9", "@nestjs/cli": "^9.5.0", @@ -65,6 +65,7 @@ "jwk-to-pem": "^2.0.5", "mixpanel": "^0.17.0", "ms": "^3.0.0-canary.1", + "multer": "^2.0.2", "openid-client": "^5.7.1", "passport": "^0.6.0", "passport-facebook": "^3.0.0", @@ -80,7 +81,6 @@ "swagger-ui-express": "^4.6.3" }, "overrides": { - "multer": "2.0.2", "form-data": "^4.0.4", "body-parser": "^1.20.3", "cross-spawn": "^7.0.5", diff --git a/src/modules/customers/customers.service.ts b/src/modules/customers/customers.service.ts index 602943b..8915ab9 100644 --- a/src/modules/customers/customers.service.ts +++ b/src/modules/customers/customers.service.ts @@ -9,12 +9,12 @@ import { } from '@nestjs/common'; import { firstValueFrom, lastValueFrom } from 'rxjs'; -import { Link } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/entities'; import { DucClient } from '../duc/client.config'; import { ClientGrpc } from '@nestjs/microservices'; import { ProtoServices } from '@dadosfera/protospack-v2/dist/lib/Duc'; -import { CustomerUpdateRequest } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages'; +import { CustomerSetLinksRequest } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/messages'; import { CustomersProtoService } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/write-service'; +import { CustomerLinksConfig } from './dtos/customers'; import ErrorCodes from 'src/utils/errorCodes'; import jwt from 'jsonwebtoken'; import { @@ -67,12 +67,12 @@ export class CustomersService implements OnModuleInit { ) } - async getLinks(customerId: string) { + async getLinks(customerId: string): Promise { try { const result = await lastValueFrom( - this.customerService.CustomerFindOneById({ id: customerId }), + this.customerService.CustomerGetLinks({ customerId }), ); - return result.customer?.links || []; + return (result.links as CustomerLinksConfig) || null; } catch (err) { if (err.details === ErrorCodes.CUSTOMER.NOT_FOUND) throw new HttpException(err.details, HttpStatus.NOT_FOUND); @@ -80,17 +80,17 @@ export class CustomersService implements OnModuleInit { } } - async setLinks(customerId: string, links: Link[]) { + async setLinks(customerId: string, links: CustomerLinksConfig) { if (!customerId || !links) { throw new HttpException(null, HttpStatus.BAD_REQUEST); } try { return await firstValueFrom( - this.customerService.CustomerUpdate({ - id: customerId, - links, - } as CustomerUpdateRequest), + this.customerService.CustomerSetLinks({ + customerId, + links: links as CustomerSetLinksRequest['links'], + }), ); } catch (err) { if (err.details === ErrorCodes.CUSTOMER.NOT_FOUND) diff --git a/src/modules/customers/dtos/customers.ts b/src/modules/customers/dtos/customers.ts index db56ee3..d914f07 100644 --- a/src/modules/customers/dtos/customers.ts +++ b/src/modules/customers/dtos/customers.ts @@ -1,7 +1,6 @@ -import { Link } from '@dadosfera/protospack-v2/dist/lib/Duc/interfaces/entities'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; -export class CustomerLink implements Link { +export class CustomerLinkItem { @ApiProperty() href: string; @ApiProperty() @@ -9,15 +8,59 @@ export class CustomerLink implements Link { @ApiProperty() description: string; @ApiPropertyOptional() - iconSrc: string; + iconSrc?: string; } + +export class CustomerSidebarLinkItem { + @ApiProperty() + type: 'link'; + @ApiProperty({ type: Object }) + title: Record; + @ApiProperty() + link: string; + @ApiPropertyOptional() + icon?: string; +} + +export class CustomerSidebarMenuItem { + @ApiProperty() + type: 'menu'; + @ApiProperty({ type: Object }) + title: Record; + @ApiPropertyOptional() + icon?: string; + @ApiProperty({ type: [CustomerSidebarLinkItem] }) + items: CustomerSidebarLinkItem[]; +} + +export class CustomerSidebarSection { + @ApiProperty({ type: Object }) + title: Record; + @ApiProperty({ + type: 'array', + items: { + oneOf: [ + { $ref: '#/components/schemas/CustomerSidebarMenuItem' }, + { $ref: '#/components/schemas/CustomerSidebarLinkItem' }, + ], + }, + }) + items: (CustomerSidebarMenuItem | CustomerSidebarLinkItem)[]; +} + +export class CustomerLinksConfig { + @ApiPropertyOptional({ type: [CustomerLinkItem] }) + home?: CustomerLinkItem[]; + @ApiPropertyOptional({ type: [CustomerSidebarSection] }) + sidebar?: CustomerSidebarSection[]; +} + export class CustomerLinkRequest { - @ApiProperty({ type: [CustomerLink] }) - links: CustomerLink[]; + @ApiProperty({ type: CustomerLinksConfig }) + links: CustomerLinksConfig; } export class CustomerLinksResponse { - @ApiProperty({ type: [CustomerLink] }) - links: CustomerLink[]; -} - + @ApiPropertyOptional({ type: CustomerLinksConfig }) + links?: CustomerLinksConfig; +} \ No newline at end of file diff --git a/src/modules/inputs/dtos/input.model.ts b/src/modules/inputs/dtos/input.model.ts index 7b40d1e..c026f8d 100644 --- a/src/modules/inputs/dtos/input.model.ts +++ b/src/modules/inputs/dtos/input.model.ts @@ -11,10 +11,19 @@ export class TableColumns { name: string; @ApiProperty() columns: string[]; - @ApiProperty() + @ApiPropertyOptional({ type: [Column] }) references: Column[]; @ApiProperty() + destination: Record<'raw' | 'qualify', { + table_name: string; + table_schema: string; + }> | null; + @ApiProperty() type: string; + @ApiPropertyOptional({ type: [String] }) + identifier_columns?: string[]; + @ApiPropertyOptional({ type: Column }) + reference_column?: Column; } export class AvailableEntity { @ApiProperty() diff --git a/src/modules/inputs/inputs.service.ts b/src/modules/inputs/inputs.service.ts index 94dd27a..d258215 100644 --- a/src/modules/inputs/inputs.service.ts +++ b/src/modules/inputs/inputs.service.ts @@ -164,6 +164,11 @@ export class InputsService { const inputCreateGenericRequest: InputCreateGenericRequest = { input: { ...body, + tables: (body.tables || []).map((table) => ({ + ...table, + identifier_columns: table.identifier_columns || [], + reference_column: table.reference_column || table.references?.[0], + })), }, info, };