mirror of
https://github.com/dadosfera/maestro.git
synced 2026-09-15 15:14:48 +00:00
384 lines
9.8 KiB
TypeScript
384 lines
9.8 KiB
TypeScript
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<Express.Multer.File>,
|
|
@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 },
|
|
);
|
|
}
|
|
}
|