import { Controller, Get, Post, Put, Param, Body, Query, Inject, UseInterceptors, UploadedFiles, Headers, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiConsumes } from '@nestjs/swagger'; import { FilesInterceptor } from '@nestjs/platform-express'; import { DadosferaLogger } from '@dadosfera/dadosfera-logs'; import FormData from 'form-data'; import { Authenticated, RequireAllPermissions, } from '../../decorators/authentication.decorator'; import { User, RequestUser } from '../../decorators/user.decorator'; import { StorageExplorerService } from './storage-explorer.service'; import { PERMISSIONS_GROUPS } from '../../authentication/permissions.enum'; @ApiTags('Storage Explorer') @Controller('storage-explorer') @Authenticated() export class StorageExplorerController { private logger: any; constructor( private readonly storageExplorerService: StorageExplorerService, @Inject(DadosferaLogger) dadosferaLogger: DadosferaLogger, ) { this.logger = dadosferaLogger.logger; } // ============================================ // TABLE OPERATIONS // ============================================ @ApiOperation({ summary: 'Validate table name in PostgreSQL and Snowflake' }) @Post('tables/validate-name') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.WRITE) async validateTableName( @Body() body: any, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'POST', '/tables/validate-name', user, body, ); } @ApiOperation({ summary: 'Create a new table' }) @Post('tables') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.WRITE) async createTable( @Body() body: any, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'POST', '/tables/', user, body, ); } @ApiOperation({ summary: 'List all tables with pagination' }) @Get('tables') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async listTables( @Query('page') page: number, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', '/tables/', user, undefined, { page }, ); } @ApiOperation({ summary: 'Get table details by ID' }) @Get('tables/:tableId') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async getTable( @Param('tableId') tableId: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', `/tables/${tableId}`, user, ); } @ApiOperation({ summary: 'Link a dataset to a table' }) @Post('tables/:tableId/datasets/:datasetId') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.WRITE) async linkDatasetToTable( @Param('tableId') tableId: string, @Param('datasetId') datasetId: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'POST', `/tables/${tableId}/datasets/${datasetId}`, user, ); } @ApiOperation({ summary: 'Get all datasets linked to a table' }) @Get('tables/:tableId/datasets') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async getTableDatasets( @Param('tableId') tableId: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', `/tables/${tableId}/datasets`, user, ); } @ApiOperation({ summary: 'Get table schema' }) @Get('tables/:tableId/schema') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async getTableSchema( @Param('tableId') tableId: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', `/tables/${tableId}/schema`, user, ); } @ApiOperation({ summary: 'Validate schema compatibility between table and dataset' }) @Post('tables/:tableId/validate-compatibility/:datasetId') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async validateSchemaCompatibility( @Param('tableId') tableId: string, @Param('datasetId') datasetId: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'POST', `/tables/${tableId}/validate-compatibility/${datasetId}`, user, ); } // ============================================ // DATASET OPERATIONS // ============================================ @ApiOperation({ summary: 'Get dataset preview data' }) @Get('datasets/:datasetId/preview') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async getDatasetPreview( @Param('datasetId') datasetId: string, @Query('limit') limit: number, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', `/datasets/${datasetId}/preview`, user, undefined, { limit }, ); } @ApiOperation({ summary: 'Get dataset schema information' }) @Get('datasets/:datasetId/schema') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async getDatasetSchema( @Param('datasetId') datasetId: string, @Query('force_refresh') forceRefresh: boolean, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', `/datasets/${datasetId}/schema`, user, undefined, { force_refresh: forceRefresh }, ); } @ApiOperation({ summary: 'List all datasets for a specific upload' }) @Get('datasets/upload/:uploadId') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async listDatasetsByUpload( @Param('uploadId') uploadId: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', `/datasets/upload/${uploadId}`, user, ); } @ApiOperation({ summary: 'Refresh dataset schema with new parsing options (Excel)' }) @Put('datasets/:datasetId/refresh-schema') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.WRITE) async refreshDatasetSchema( @Param('datasetId') datasetId: string, @Body() body: any, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'PUT', `/datasets/${datasetId}/refresh-schema`, user, body, ); } // ============================================ // STORAGE OPERATIONS // ============================================ @ApiOperation({ summary: 'List file explorer uploads with pagination' }) @Get('storage/uploads/history') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async listFileExplorerUploads( @Query('page') page: number, @Query('limit') limit: number, @Query('folder_path') folderPath: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', '/storage/uploads/history', user, undefined, { page, limit, folder_path: folderPath }, ); } @ApiOperation({ summary: 'Browse folders and files in storage' }) @Get('storage/browse') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async browseStorage( @Query('path') path: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', '/storage/browse', user, undefined, { path }, ); } @ApiOperation({ summary: 'Upload multiple files to storage' }) @Post('storage/upload/batch') @ApiConsumes('multipart/form-data') @UseInterceptors(FilesInterceptor('files')) @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.WRITE) async batchUpload( @UploadedFiles() files: Array, @Body('folder_path') folderPath: string, @User() user: RequestUser, ) { // Create FormData to forward files to storage-explorer API const formData = new FormData(); // Add files if (files && files.length > 0) { files.forEach((file) => { formData.append('files', file.buffer, { filename: file.originalname, contentType: file.mimetype, }); }); } // Add folder_path if (folderPath) { formData.append('folder_path', folderPath); } return this.storageExplorerService.proxyFormData( 'POST', '/storage/upload/batch', user, formData, ); } @ApiOperation({ summary: 'Create a new folder in storage' }) @Post('storage/folder/create') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.WRITE) async createFolder( @Body() body: any, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'POST', '/storage/folder/create', user, body, ); } @ApiOperation({ summary: 'Download a file from storage' }) @Get('storage/download') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async downloadFile( @Query('file_path') filePath: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', '/storage/download', user, undefined, { file_path: filePath }, ); } @ApiOperation({ summary: 'Get detailed file metadata' }) @Get('storage/metadata') @RequireAllPermissions(PERMISSIONS_GROUPS.STORAGE_EXPLORER.permissions.READ) async getFileMetadata( @Query('file_path') filePath: string, @User() user: RequestUser, ) { return this.storageExplorerService.proxy( 'GET', '/storage/metadata', user, undefined, { file_path: filePath }, ); } }