From b736cddf07f89a7bca6d04e3477b655b38576414 Mon Sep 17 00:00:00 2001 From: Rafael Date: Mon, 12 Jan 2026 16:22:25 -0300 Subject: [PATCH 1/6] FIX: Update ValidationPipe for class-validator 0.14.0+ compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fix addresses a breaking change introduced in class-validator 0.14.0 where the default for forbidUnknownValues changed from false to true. Issue: - POST /connections was returning 400 "an unknown value was passed to the validate function" errors - This occurred because CreateConnectionDto and UpdateConnectionDto have no validation decorators, causing class-validator 0.14.0+ to treat them as "unknown values" - Extra fields (like connector_version) in request payloads would fail validation Solution: - Set forbidUnknownValues: false to allow DTOs without validation decorators - Set whitelist: true to automatically strip extra properties not defined in DTOs - This maintains backward compatibility while adding security by removing unexpected fields 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/pipes/object-validation.pipe.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/pipes/object-validation.pipe.ts b/src/pipes/object-validation.pipe.ts index 1014581..1315083 100644 --- a/src/pipes/object-validation.pipe.ts +++ b/src/pipes/object-validation.pipe.ts @@ -14,7 +14,10 @@ export class ValidationPipe implements PipeTransform { return value; } const object = plainToInstance(metatype, value); - const errors = await validate(object); + const errors = await validate(object, { + forbidUnknownValues: false, + whitelist: true, + }); if (errors.length > 0) { const errorMessages = errors.map((err) => err.constraints); throw new BadRequestException(errorMessages); From 878ec977b81f1288f7826d950f2772687137f9fa Mon Sep 17 00:00:00 2001 From: marcos-silva-rodrigues Date: Mon, 2 Feb 2026 14:25:13 -0300 Subject: [PATCH 2/6] FIX: maestro proxy urls --- deploy/helm-chart/values-stg.yaml | 1 + deploy/helm-chart/values.yaml | 2 +- docsfera.json | 124 +++++++++++++----- .../platform-api/platform-api.controller.ts | 59 +++++++++ .../storage-explorer.config.ts | 4 +- .../storage-explorer.service.ts | 2 +- 6 files changed, 158 insertions(+), 34 deletions(-) diff --git a/deploy/helm-chart/values-stg.yaml b/deploy/helm-chart/values-stg.yaml index 360aafe..ed83c67 100644 --- a/deploy/helm-chart/values-stg.yaml +++ b/deploy/helm-chart/values-stg.yaml @@ -9,6 +9,7 @@ maestro: cookie_secret: "ff7bc13823edb2ae50d248e5780bddc9d4b31c36" redis_database: "1" platform_api_url: https://xs2hkhq07k.execute-api.us-east-1.amazonaws.com + storage_explorer_api_url: "https://storage-explorer-{customer}.stg.dadosfera.ai/" hostname: maestro.stg.dadosfera.ai diff --git a/deploy/helm-chart/values.yaml b/deploy/helm-chart/values.yaml index 3c8ebcc..6420616 100644 --- a/deploy/helm-chart/values.yaml +++ b/deploy/helm-chart/values.yaml @@ -47,7 +47,7 @@ maestro: open_customer_id: f239718a-a271-4ef9-ae7e-02a2f0f3aa6e open_group_id: 401573bb-334f-44b2-b30e-88d4cea31ae9 platform_api_url: https://oz8v2zid1e.execute-api.us-east-1.amazonaws.com - storage_explorer_api_url: "https://storage-explorer-{customer_id}.prd.dadosfera.ai/api" + storage_explorer_api_url: "https://storage-explorer-{customer}.dadosfera.ai/" dedicated_proxy: "" restricted_ip: "" redis_host: "aaapzppmlyamkocqwstpo7zvopczyyiyuy6xzm2g6c5k4mq3a66be4a-0.redis.sa-saopaulo-1.oci.oraclecloud.com" diff --git a/docsfera.json b/docsfera.json index d13bcd6..801658d 100644 --- a/docsfera.json +++ b/docsfera.json @@ -7275,6 +7275,100 @@ ] } }, + "/platform/pipelines/catalog/tables": { + "get": { + "operationId": "PlatformApiController_getAvailableTables", + "summary": "Get all tables available", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Platform API" + ], + "security": [ + { + "access-token": [] + } + ] + } + }, + "/platform/pipelines/catalog/schemas": { + "get": { + "operationId": "PlatformApiController_getAvailableSchemas", + "summary": "Get all schemas available", + "parameters": [], + "responses": { + "200": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Platform API" + ], + "security": [ + { + "access-token": [] + } + ] + } + }, + "/platform/pipelines/catalog/tables/validate": { + "post": { + "operationId": "PlatformApiController_validateTableAndSchema", + "summary": "Validate tables and schemas", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "responses": { + "201": { + "description": "", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + }, + "tags": [ + "Platform API" + ], + "security": [ + { + "access-token": [] + } + ] + } + }, "/platform/pipeline/{pipelineId}/pipeline_run": { "get": { "operationId": "PlatformApiController_getPipelineRuns", @@ -8440,36 +8534,6 @@ ] } }, - "/storage-explorer/storage/link-to-table": { - "post": { - "operationId": "StorageExplorerController_linkFileToTable", - "summary": "Link an existing file in storage to a table", - "parameters": [], - "responses": { - "201": { - "description": "", - "content": { - "application/json": { - "schema": { - "type": "object" - } - } - } - } - }, - "tags": [ - "Storage Explorer" - ], - "security": [ - { - "access-token": [] - }, - { - "access-token": [] - } - ] - } - }, "/storage-explorer/storage/metadata": { "get": { "operationId": "StorageExplorerController_getFileMetadata", diff --git a/src/modules/platform-api/platform-api.controller.ts b/src/modules/platform-api/platform-api.controller.ts index e0d59f2..978f464 100644 --- a/src/modules/platform-api/platform-api.controller.ts +++ b/src/modules/platform-api/platform-api.controller.ts @@ -26,6 +26,14 @@ import { DynamoDBService, ReferenceColumn } from '../../services/dynamodb'; import { CustomersService } from '../customers/customers.service'; import { validateCronAgainstScheduleLimit } from '../../utils/cron-validation'; + +type ValidateTablesDTO = { + tables: Array<{ + table_schema: string, + table_name: string + }> +} + @ApiTags('Platform API') @Controller('platform') export class PlatformApiController { @@ -720,6 +728,57 @@ export class PlatformApiController { ); } + // ==================== Catalog ROUTES ==================== + + @Get('pipelines/catalog/tables') + @ApiOperation({ summary: 'Get all tables available' }) + @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET) + async getAvailableTables( + @User() user: RequestUser, + @Query() query: Record, + ) { + return this.platformApiService.proxy( + 'GET', + '/catalog/tables', + user, + undefined, + query, + ); + } + + @Get('pipelines/catalog/schemas') + @ApiOperation({ summary: 'Get all schemas available' }) + @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.GET) + async getAvailableSchemas( + @User() user: RequestUser, + @Query() query: Record, + ) { + return this.platformApiService.proxy( + 'GET', + '/catalog/schemas', + user, + undefined, + query, + ); + } + + @Post('pipelines/catalog/tables/validate') + @ApiOperation({ summary: 'Validate tables and schemas' }) + @RequireAllPermissions(PERMISSIONS_GROUPS.PIPELINE.permissions.UPDATE) + async validateTableAndSchema( + @User() user: RequestUser, + @Query() query: Record, + @Body() validateTablesDto: ValidateTablesDTO[] + ) { + return this.platformApiService.proxy( + 'POST', + '/catalog/tables/validate', + user, + validateTablesDto, + query, + ); + } + // ==================== PIPELINE RUN ROUTES ==================== @Get('pipeline/:pipelineId/pipeline_run') diff --git a/src/modules/storage-explorer/storage-explorer.config.ts b/src/modules/storage-explorer/storage-explorer.config.ts index 417eb15..4a9ff43 100644 --- a/src/modules/storage-explorer/storage-explorer.config.ts +++ b/src/modules/storage-explorer/storage-explorer.config.ts @@ -1,5 +1,5 @@ export const STORAGE_EXPLORER_CONFIG = { - getUrl: (customerId: string): string => { + getUrl: (customerName: string): string => { const urlTemplate = process.env.STORAGE_EXPLORER_API_URL; if (!urlTemplate) { throw new Error('STORAGE_EXPLORER_API_URL environment variable is not set'); @@ -7,7 +7,7 @@ export const STORAGE_EXPLORER_CONFIG = { // Replace {customer_id} placeholder with actual customer ID // For local: http://172.17.0.1:8000/api (no placeholder) // For prod: https://storage-explorer-{customer_id}.stg.dadosfera.ai/api - return urlTemplate.replace('{customer_id}', customerId); + return urlTemplate.replace('{customer}', customerName); }, timeout: parseInt(process.env.STORAGE_EXPLORER_TIMEOUT || '30000', 10), }; diff --git a/src/modules/storage-explorer/storage-explorer.service.ts b/src/modules/storage-explorer/storage-explorer.service.ts index ba149c0..5ff3bf7 100644 --- a/src/modules/storage-explorer/storage-explorer.service.ts +++ b/src/modules/storage-explorer/storage-explorer.service.ts @@ -28,7 +28,7 @@ export class StorageExplorerService { } // Get customer-specific storage-explorer URL - const baseUrl = STORAGE_EXPLORER_CONFIG.getUrl(user.customer_id); + const baseUrl = STORAGE_EXPLORER_CONFIG.getUrl(user.customer_name); const url = new URL(`${baseUrl}${path}`); // Add query params From c97a02cb17b1b7bea6eb7e658ead451d8f5c30fe Mon Sep 17 00:00:00 2001 From: marcos-silva-rodrigues Date: Mon, 2 Feb 2026 14:27:08 -0300 Subject: [PATCH 3/6] FIX: remove / --- deploy/helm-chart/values-stg.yaml | 2 +- deploy/helm-chart/values.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/helm-chart/values-stg.yaml b/deploy/helm-chart/values-stg.yaml index ed83c67..f86d9ff 100644 --- a/deploy/helm-chart/values-stg.yaml +++ b/deploy/helm-chart/values-stg.yaml @@ -9,7 +9,7 @@ maestro: cookie_secret: "ff7bc13823edb2ae50d248e5780bddc9d4b31c36" redis_database: "1" platform_api_url: https://xs2hkhq07k.execute-api.us-east-1.amazonaws.com - storage_explorer_api_url: "https://storage-explorer-{customer}.stg.dadosfera.ai/" + storage_explorer_api_url: "https://storage-explorer-{customer}.stg.dadosfera.ai" hostname: maestro.stg.dadosfera.ai diff --git a/deploy/helm-chart/values.yaml b/deploy/helm-chart/values.yaml index 6420616..e94a576 100644 --- a/deploy/helm-chart/values.yaml +++ b/deploy/helm-chart/values.yaml @@ -47,7 +47,7 @@ maestro: open_customer_id: f239718a-a271-4ef9-ae7e-02a2f0f3aa6e open_group_id: 401573bb-334f-44b2-b30e-88d4cea31ae9 platform_api_url: https://oz8v2zid1e.execute-api.us-east-1.amazonaws.com - storage_explorer_api_url: "https://storage-explorer-{customer}.dadosfera.ai/" + storage_explorer_api_url: "https://storage-explorer-{customer}.dadosfera.ai" dedicated_proxy: "" restricted_ip: "" redis_host: "aaapzppmlyamkocqwstpo7zvopczyyiyuy6xzm2g6c5k4mq3a66be4a-0.redis.sa-saopaulo-1.oci.oraclecloud.com" From 0e038d0b121ef7f4dc3bd62c0653eb7fc2bca34b Mon Sep 17 00:00:00 2001 From: marcos-silva-rodrigues Date: Mon, 2 Feb 2026 14:41:53 -0300 Subject: [PATCH 4/6] FIX: storage api --- deploy/helm-chart/values-stg.yaml | 2 +- deploy/helm-chart/values.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/helm-chart/values-stg.yaml b/deploy/helm-chart/values-stg.yaml index f86d9ff..924dcd6 100644 --- a/deploy/helm-chart/values-stg.yaml +++ b/deploy/helm-chart/values-stg.yaml @@ -9,7 +9,7 @@ maestro: cookie_secret: "ff7bc13823edb2ae50d248e5780bddc9d4b31c36" redis_database: "1" platform_api_url: https://xs2hkhq07k.execute-api.us-east-1.amazonaws.com - storage_explorer_api_url: "https://storage-explorer-{customer}.stg.dadosfera.ai" + storage_explorer_api_url: "https://storage-explorer-{customer}.stg.dadosfera.ai/api" hostname: maestro.stg.dadosfera.ai diff --git a/deploy/helm-chart/values.yaml b/deploy/helm-chart/values.yaml index e94a576..4e431f5 100644 --- a/deploy/helm-chart/values.yaml +++ b/deploy/helm-chart/values.yaml @@ -47,7 +47,7 @@ maestro: open_customer_id: f239718a-a271-4ef9-ae7e-02a2f0f3aa6e open_group_id: 401573bb-334f-44b2-b30e-88d4cea31ae9 platform_api_url: https://oz8v2zid1e.execute-api.us-east-1.amazonaws.com - storage_explorer_api_url: "https://storage-explorer-{customer}.dadosfera.ai" + storage_explorer_api_url: "https://storage-explorer-{customer}.dadosfera.ai/api" dedicated_proxy: "" restricted_ip: "" redis_host: "aaapzppmlyamkocqwstpo7zvopczyyiyuy6xzm2g6c5k4mq3a66be4a-0.redis.sa-saopaulo-1.oci.oraclecloud.com" From cd4382c1ffe63f138be4e17bdda6b11245e88cee Mon Sep 17 00:00:00 2001 From: marcos-silva-rodrigues Date: Mon, 2 Feb 2026 15:37:13 -0300 Subject: [PATCH 5/6] FIX: send token by storage --- docsfera.json | 156 +++++++++++++++++- .../storage-explorer.controller.ts | 38 ++++- .../storage-explorer.service.ts | 4 +- 3 files changed, 192 insertions(+), 6 deletions(-) diff --git a/docsfera.json b/docsfera.json index 801658d..04853e7 100644 --- a/docsfera.json +++ b/docsfera.json @@ -7865,7 +7865,16 @@ "post": { "operationId": "StorageExplorerController_validateTableName", "summary": "Validate table name in PostgreSQL and Snowflake", - "parameters": [], + "parameters": [ + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } + } + ], "responses": { "201": { "description": "", @@ -7895,7 +7904,16 @@ "post": { "operationId": "StorageExplorerController_createTable", "summary": "Create a new table", - "parameters": [], + "parameters": [ + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } + } + ], "responses": { "201": { "description": "", @@ -7931,6 +7949,14 @@ "schema": { "type": "number" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -7970,6 +7996,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8017,6 +8051,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8056,6 +8098,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8095,6 +8145,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8142,6 +8200,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8189,6 +8255,14 @@ "schema": { "type": "number" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8236,6 +8310,14 @@ "schema": { "type": "boolean" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8275,6 +8357,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8314,6 +8404,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8369,6 +8467,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8408,6 +8514,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8439,7 +8553,16 @@ "post": { "operationId": "StorageExplorerController_batchUpload", "summary": "Upload multiple files to storage", - "parameters": [], + "parameters": [ + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } + } + ], "responses": { "201": { "description": "", @@ -8469,7 +8592,16 @@ "post": { "operationId": "StorageExplorerController_createFolder", "summary": "Create a new folder in storage", - "parameters": [], + "parameters": [ + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } + } + ], "responses": { "201": { "description": "", @@ -8507,6 +8639,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { @@ -8546,6 +8686,14 @@ "schema": { "type": "string" } + }, + { + "name": "Authorization", + "required": true, + "in": "header", + "schema": { + "type": "string" + } } ], "responses": { diff --git a/src/modules/storage-explorer/storage-explorer.controller.ts b/src/modules/storage-explorer/storage-explorer.controller.ts index ef6a071..50dcc96 100644 --- a/src/modules/storage-explorer/storage-explorer.controller.ts +++ b/src/modules/storage-explorer/storage-explorer.controller.ts @@ -3,13 +3,13 @@ import { Get, Post, Put, - Delete, Param, Body, Query, Inject, UseInterceptors, UploadedFiles, + Headers, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiConsumes } from '@nestjs/swagger'; import { FilesInterceptor } from '@nestjs/platform-express'; @@ -47,11 +47,13 @@ export class StorageExplorerController { async validateTableName( @Body() body: any, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'POST', '/tables/validate-name', user, + token, body, ); } @@ -62,11 +64,13 @@ export class StorageExplorerController { async createTable( @Body() body: any, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'POST', '/tables/', user, + token, body, ); } @@ -77,11 +81,13 @@ export class StorageExplorerController { async listTables( @Query('page') page: number, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', '/tables/', user, + token, undefined, { page }, ); @@ -93,11 +99,13 @@ export class StorageExplorerController { async getTable( @Param('tableId') tableId: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', `/tables/${tableId}`, user, + token ); } @@ -108,11 +116,13 @@ export class StorageExplorerController { @Param('tableId') tableId: string, @Param('datasetId') datasetId: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'POST', `/tables/${tableId}/datasets/${datasetId}`, user, + token ); } @@ -122,11 +132,13 @@ export class StorageExplorerController { async getTableDatasets( @Param('tableId') tableId: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', `/tables/${tableId}/datasets`, user, + token ); } @@ -136,11 +148,13 @@ export class StorageExplorerController { async getTableSchema( @Param('tableId') tableId: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', `/tables/${tableId}/schema`, user, + token ); } @@ -151,11 +165,13 @@ export class StorageExplorerController { @Param('tableId') tableId: string, @Param('datasetId') datasetId: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'POST', `/tables/${tableId}/validate-compatibility/${datasetId}`, user, + token ); } @@ -170,11 +186,13 @@ export class StorageExplorerController { @Param('datasetId') datasetId: string, @Query('limit') limit: number, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', `/datasets/${datasetId}/preview`, user, + token, undefined, { limit }, ); @@ -187,11 +205,13 @@ export class StorageExplorerController { @Param('datasetId') datasetId: string, @Query('force_refresh') forceRefresh: boolean, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', `/datasets/${datasetId}/schema`, user, + token, undefined, { force_refresh: forceRefresh }, ); @@ -203,11 +223,13 @@ export class StorageExplorerController { async listDatasetsByUpload( @Param('uploadId') uploadId: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', `/datasets/upload/${uploadId}`, user, + token ); } @@ -218,11 +240,13 @@ export class StorageExplorerController { @Param('datasetId') datasetId: string, @Body() body: any, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'PUT', `/datasets/${datasetId}/refresh-schema`, user, + token, body, ); } @@ -239,11 +263,13 @@ export class StorageExplorerController { @Query('limit') limit: number, @Query('folder_path') folderPath: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', '/storage/uploads/history', user, + token, undefined, { page, limit, folder_path: folderPath }, ); @@ -255,11 +281,13 @@ export class StorageExplorerController { async browseStorage( @Query('path') path: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', '/storage/browse', user, + token, undefined, { path }, ); @@ -274,6 +302,7 @@ export class StorageExplorerController { @UploadedFiles() files: Array, @Body('folder_path') folderPath: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { // Create FormData to forward files to storage-explorer API const formData = new FormData(); @@ -297,6 +326,7 @@ export class StorageExplorerController { 'POST', '/storage/upload/batch', user, + token, formData, ); } @@ -307,11 +337,13 @@ export class StorageExplorerController { async createFolder( @Body() body: any, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'POST', '/storage/folder/create', user, + token, body, ); } @@ -322,11 +354,13 @@ export class StorageExplorerController { async downloadFile( @Query('file_path') filePath: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', '/storage/download', user, + token, undefined, { file_path: filePath }, ); @@ -338,11 +372,13 @@ export class StorageExplorerController { async getFileMetadata( @Query('file_path') filePath: string, @User() user: RequestUser, + @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'GET', '/storage/metadata', user, + token, undefined, { file_path: filePath }, ); diff --git a/src/modules/storage-explorer/storage-explorer.service.ts b/src/modules/storage-explorer/storage-explorer.service.ts index 5ff3bf7..c7de628 100644 --- a/src/modules/storage-explorer/storage-explorer.service.ts +++ b/src/modules/storage-explorer/storage-explorer.service.ts @@ -19,8 +19,9 @@ export class StorageExplorerService { method: string, path: string, user: RequestUser, + token: string, body?: any, - query?: Record, + query?: Record ): Promise { // Validate customer_id is present for multi-tenant isolation if (!user.customer_id) { @@ -41,6 +42,7 @@ export class StorageExplorerService { } const headers: Record = { + 'Authorization': token, 'content-type': 'application/json', }; From 9a217dff57bf454b28ee0de6eee206737050135b Mon Sep 17 00:00:00 2001 From: marcos-silva-rodrigues Date: Mon, 2 Feb 2026 16:37:01 -0300 Subject: [PATCH 6/6] FIX: storage service dns --- deploy/helm-chart/values-stg.yaml | 2 +- docsfera.json | 156 +----------------- .../storage-explorer.config.ts | 2 +- .../storage-explorer.controller.ts | 69 ++++---- .../storage-explorer.service.ts | 2 - 5 files changed, 39 insertions(+), 192 deletions(-) diff --git a/deploy/helm-chart/values-stg.yaml b/deploy/helm-chart/values-stg.yaml index 924dcd6..a9aa543 100644 --- a/deploy/helm-chart/values-stg.yaml +++ b/deploy/helm-chart/values-stg.yaml @@ -9,7 +9,7 @@ maestro: cookie_secret: "ff7bc13823edb2ae50d248e5780bddc9d4b31c36" redis_database: "1" platform_api_url: https://xs2hkhq07k.execute-api.us-east-1.amazonaws.com - storage_explorer_api_url: "https://storage-explorer-{customer}.stg.dadosfera.ai/api" + storage_explorer_api_url: "http://storage-explorer-{customer}.data-apps.svc.cluster.local/api" hostname: maestro.stg.dadosfera.ai diff --git a/docsfera.json b/docsfera.json index 04853e7..801658d 100644 --- a/docsfera.json +++ b/docsfera.json @@ -7865,16 +7865,7 @@ "post": { "operationId": "StorageExplorerController_validateTableName", "summary": "Validate table name in PostgreSQL and Snowflake", - "parameters": [ - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } - } - ], + "parameters": [], "responses": { "201": { "description": "", @@ -7904,16 +7895,7 @@ "post": { "operationId": "StorageExplorerController_createTable", "summary": "Create a new table", - "parameters": [ - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } - } - ], + "parameters": [], "responses": { "201": { "description": "", @@ -7949,14 +7931,6 @@ "schema": { "type": "number" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -7996,14 +7970,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8051,14 +8017,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8098,14 +8056,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8145,14 +8095,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8200,14 +8142,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8255,14 +8189,6 @@ "schema": { "type": "number" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8310,14 +8236,6 @@ "schema": { "type": "boolean" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8357,14 +8275,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8404,14 +8314,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8467,14 +8369,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8514,14 +8408,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8553,16 +8439,7 @@ "post": { "operationId": "StorageExplorerController_batchUpload", "summary": "Upload multiple files to storage", - "parameters": [ - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } - } - ], + "parameters": [], "responses": { "201": { "description": "", @@ -8592,16 +8469,7 @@ "post": { "operationId": "StorageExplorerController_createFolder", "summary": "Create a new folder in storage", - "parameters": [ - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } - } - ], + "parameters": [], "responses": { "201": { "description": "", @@ -8639,14 +8507,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { @@ -8686,14 +8546,6 @@ "schema": { "type": "string" } - }, - { - "name": "Authorization", - "required": true, - "in": "header", - "schema": { - "type": "string" - } } ], "responses": { diff --git a/src/modules/storage-explorer/storage-explorer.config.ts b/src/modules/storage-explorer/storage-explorer.config.ts index 4a9ff43..aa1a46e 100644 --- a/src/modules/storage-explorer/storage-explorer.config.ts +++ b/src/modules/storage-explorer/storage-explorer.config.ts @@ -6,7 +6,7 @@ export const STORAGE_EXPLORER_CONFIG = { } // Replace {customer_id} placeholder with actual customer ID // For local: http://172.17.0.1:8000/api (no placeholder) - // For prod: https://storage-explorer-{customer_id}.stg.dadosfera.ai/api + // For prod: https://storage-explorer-{customer_id}.dadosfera.ai/api return urlTemplate.replace('{customer}', customerName); }, timeout: parseInt(process.env.STORAGE_EXPLORER_TIMEOUT || '30000', 10), diff --git a/src/modules/storage-explorer/storage-explorer.controller.ts b/src/modules/storage-explorer/storage-explorer.controller.ts index 50dcc96..34e94fc 100644 --- a/src/modules/storage-explorer/storage-explorer.controller.ts +++ b/src/modules/storage-explorer/storage-explorer.controller.ts @@ -47,13 +47,13 @@ export class StorageExplorerController { async validateTableName( @Body() body: any, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'POST', '/tables/validate-name', user, - token, + body, ); } @@ -64,13 +64,13 @@ export class StorageExplorerController { async createTable( @Body() body: any, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'POST', '/tables/', user, - token, + body, ); } @@ -81,13 +81,13 @@ export class StorageExplorerController { async listTables( @Query('page') page: number, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', '/tables/', user, - token, + undefined, { page }, ); @@ -99,13 +99,12 @@ export class StorageExplorerController { async getTable( @Param('tableId') tableId: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', `/tables/${tableId}`, user, - token ); } @@ -116,13 +115,13 @@ export class StorageExplorerController { @Param('tableId') tableId: string, @Param('datasetId') datasetId: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'POST', `/tables/${tableId}/datasets/${datasetId}`, user, - token + ); } @@ -132,13 +131,13 @@ export class StorageExplorerController { async getTableDatasets( @Param('tableId') tableId: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', `/tables/${tableId}/datasets`, user, - token + ); } @@ -148,13 +147,13 @@ export class StorageExplorerController { async getTableSchema( @Param('tableId') tableId: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', `/tables/${tableId}/schema`, user, - token + ); } @@ -165,13 +164,12 @@ export class StorageExplorerController { @Param('tableId') tableId: string, @Param('datasetId') datasetId: string, @User() user: RequestUser, - @Headers('Authorization') token: string ) { return this.storageExplorerService.proxy( 'POST', `/tables/${tableId}/validate-compatibility/${datasetId}`, user, - token + ); } @@ -186,13 +184,13 @@ export class StorageExplorerController { @Param('datasetId') datasetId: string, @Query('limit') limit: number, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', `/datasets/${datasetId}/preview`, user, - token, + undefined, { limit }, ); @@ -205,13 +203,13 @@ export class StorageExplorerController { @Param('datasetId') datasetId: string, @Query('force_refresh') forceRefresh: boolean, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', `/datasets/${datasetId}/schema`, user, - token, + undefined, { force_refresh: forceRefresh }, ); @@ -223,13 +221,13 @@ export class StorageExplorerController { async listDatasetsByUpload( @Param('uploadId') uploadId: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', `/datasets/upload/${uploadId}`, user, - token + ); } @@ -240,13 +238,13 @@ export class StorageExplorerController { @Param('datasetId') datasetId: string, @Body() body: any, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'PUT', `/datasets/${datasetId}/refresh-schema`, user, - token, + body, ); } @@ -263,13 +261,13 @@ export class StorageExplorerController { @Query('limit') limit: number, @Query('folder_path') folderPath: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', '/storage/uploads/history', user, - token, + undefined, { page, limit, folder_path: folderPath }, ); @@ -281,13 +279,13 @@ export class StorageExplorerController { async browseStorage( @Query('path') path: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', '/storage/browse', user, - token, + undefined, { path }, ); @@ -302,7 +300,7 @@ export class StorageExplorerController { @UploadedFiles() files: Array, @Body('folder_path') folderPath: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { // Create FormData to forward files to storage-explorer API const formData = new FormData(); @@ -326,7 +324,7 @@ export class StorageExplorerController { 'POST', '/storage/upload/batch', user, - token, + formData, ); } @@ -337,13 +335,13 @@ export class StorageExplorerController { async createFolder( @Body() body: any, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'POST', '/storage/folder/create', user, - token, + body, ); } @@ -354,13 +352,13 @@ export class StorageExplorerController { async downloadFile( @Query('file_path') filePath: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', '/storage/download', user, - token, + undefined, { file_path: filePath }, ); @@ -372,13 +370,12 @@ export class StorageExplorerController { async getFileMetadata( @Query('file_path') filePath: string, @User() user: RequestUser, - @Headers('Authorization') token: string + ) { return this.storageExplorerService.proxy( 'GET', '/storage/metadata', user, - token, undefined, { file_path: filePath }, ); diff --git a/src/modules/storage-explorer/storage-explorer.service.ts b/src/modules/storage-explorer/storage-explorer.service.ts index c7de628..02d919f 100644 --- a/src/modules/storage-explorer/storage-explorer.service.ts +++ b/src/modules/storage-explorer/storage-explorer.service.ts @@ -19,7 +19,6 @@ export class StorageExplorerService { method: string, path: string, user: RequestUser, - token: string, body?: any, query?: Record ): Promise { @@ -42,7 +41,6 @@ export class StorageExplorerService { } const headers: Record = { - 'Authorization': token, 'content-type': 'application/json', };