import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseUUIDPipe, Post, Put, Query, UseGuards, } from '@nestjs/common'; import { ApiOperation, ApiResponse, ApiTags } from '@nestjs/swagger'; import { archiveFilesSchema, filePathSchema, listFilesQuerySchema, readFileContentQuerySchema, unarchiveFileSchema, updateFileContentSchema, uploadFileSchema, } from '@hexahost/contracts'; import { CurrentUser } from '../../auth/decorators/current-user.decorator'; import { SessionGuard } from '../../auth/guards/session.guard'; import { ZodValidationPipe } from '../../common/pipes/zod-validation.pipe'; import { FilesService } from './files.service'; @ApiTags('servers') @Controller('servers/:serverId/files') @UseGuards(SessionGuard) export class FilesController { constructor(private readonly filesService: FilesService) {} @Get() @ApiOperation({ summary: 'List files in the server data directory' }) list( @CurrentUser() user: { id: string }, @Param('serverId', ParseUUIDPipe) serverId: string, @Query(new ZodValidationPipe(listFilesQuerySchema)) query: { path: string }, ) { return this.filesService.listFiles(user.id, serverId, query.path); } @Get('content') @ApiOperation({ summary: 'Read a text file from the server' }) read( @CurrentUser() user: { id: string }, @Param('serverId', ParseUUIDPipe) serverId: string, @Query(new ZodValidationPipe(readFileContentQuerySchema)) query: { path: string }, ) { return this.filesService.readFile(user.id, serverId, query.path); } @Put('content') @ApiOperation({ summary: 'Write a text file on the server' }) write( @CurrentUser() user: { id: string }, @Param('serverId', ParseUUIDPipe) serverId: string, @Body(new ZodValidationPipe(updateFileContentSchema)) body: unknown, ) { return this.filesService.writeFile( user.id, serverId, body as Parameters[2], ); } @Post('upload') @HttpCode(HttpStatus.CREATED) @ApiOperation({ summary: 'Upload a file (base64) to the server' }) upload( @CurrentUser() user: { id: string }, @Param('serverId', ParseUUIDPipe) serverId: string, @Body(new ZodValidationPipe(uploadFileSchema)) body: unknown, ) { return this.filesService.uploadFile( user.id, serverId, body as Parameters[2], ); } @Delete() @ApiOperation({ summary: 'Delete a file or directory' }) delete( @CurrentUser() user: { id: string }, @Param('serverId', ParseUUIDPipe) serverId: string, @Query(new ZodValidationPipe(filePathSchema)) query: { path: string }, ) { return this.filesService.deleteFile(user.id, serverId, query.path); } @Post('archive') @HttpCode(HttpStatus.CREATED) @ApiOperation({ summary: 'Create a tar.gz archive from selected paths' }) archive( @CurrentUser() user: { id: string }, @Param('serverId', ParseUUIDPipe) serverId: string, @Body(new ZodValidationPipe(archiveFilesSchema)) body: unknown, ) { return this.filesService.archiveFiles( user.id, serverId, body as Parameters[2], ); } @Post('unarchive') @HttpCode(HttpStatus.ACCEPTED) @ApiOperation({ summary: 'Extract a tar.gz archive on the server' }) unarchive( @CurrentUser() user: { id: string }, @Param('serverId', ParseUUIDPipe) serverId: string, @Body(new ZodValidationPipe(unarchiveFileSchema)) body: unknown, ) { return this.filesService.unarchiveFile( user.id, serverId, body as Parameters[2], ); } }