import { Controller, Get, Post, Patch, Param, Body, UseInterceptors, UploadedFile, Res, HttpStatus, BadRequestException, ParseUUIDPipe, StreamableFile, } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import type { Response } from 'express'; import { DocumentsLegauxService } from './documents-legaux.service'; import { UploadDocumentDto } from './dto/upload-document.dto'; import { DocumentsActifsResponseDto } from './dto/documents-actifs.dto'; import { DocumentVersionDto } from './dto/document-version.dto'; @Controller('documents-legaux') export class DocumentsLegauxController { constructor(private readonly documentsService: DocumentsLegauxService) {} /** * GET /api/v1/documents-legaux/actifs * Récupérer les documents actifs (CGU + Privacy) * PUBLIC */ @Get('actifs') async getDocumentsActifs(): Promise { const { cgu, privacy } = await this.documentsService.getDocumentsActifs(); return { cgu: { id: cgu.id, type: cgu.type, version: cgu.version, url: `/api/v1/documents-legaux/${cgu.id}/download`, activeLe: cgu.activeLe, }, privacy: { id: privacy.id, type: privacy.type, version: privacy.version, url: `/api/v1/documents-legaux/${privacy.id}/download`, activeLe: privacy.activeLe, }, }; } /** * GET /api/v1/documents-legaux/:type/versions * Lister toutes les versions d'un type de document * ADMIN ONLY */ @Get(':type/versions') // @UseGuards(JwtAuthGuard, RolesGuard) // @Roles('super_admin', 'administrateur') async listerVersions(@Param('type') type: string): Promise { if (type !== 'cgu' && type !== 'privacy') { throw new BadRequestException('Le type doit être "cgu" ou "privacy"'); } const documents = await this.documentsService.listerVersions(type as 'cgu' | 'privacy'); return documents.map((doc) => ({ id: doc.id, version: doc.version, fichier_nom: doc.fichier_nom, actif: doc.actif, televersePar: doc.televersePar ? { id: doc.televersePar.id, prenom: doc.televersePar.prenom, nom: doc.televersePar.nom, } : null, televerseLe: doc.televerseLe, activeLe: doc.activeLe, })); } /** * POST /api/v1/documents-legaux * Upload une nouvelle version d'un document * ADMIN ONLY */ @Post() @UseInterceptors(FileInterceptor('file')) // @UseGuards(JwtAuthGuard, RolesGuard) // @Roles('super_admin', 'administrateur') async uploadDocument( @Body() uploadDto: UploadDocumentDto, @UploadedFile() file: Express.Multer.File, // @CurrentUser() user: any, // TODO: Décommenter quand le guard sera implémenté ) { if (!file) { throw new BadRequestException('Aucun fichier fourni'); } // TODO: Récupérer l'ID utilisateur depuis le guard const userId = '00000000-0000-0000-0000-000000000000'; // Temporaire const document = await this.documentsService.uploadNouvelleVersion( uploadDto.type, file, userId, ); return { id: document.id, type: document.type, version: document.version, fichier_nom: document.fichier_nom, actif: document.actif, televerseLe: document.televerseLe, }; } /** * PATCH /api/v1/documents-legaux/:id/activer * Activer une version d'un document * ADMIN ONLY */ @Patch(':id/activer') // @UseGuards(JwtAuthGuard, RolesGuard) // @Roles('super_admin', 'administrateur') async activerVersion(@Param('id', ParseUUIDPipe) documentId: string) { await this.documentsService.activerVersion(documentId); // Récupérer le document pour retourner les infos const documents = await this.documentsService.listerVersions('cgu'); const document = documents.find((d) => d.id === documentId); if (!document) { const documentsPrivacy = await this.documentsService.listerVersions('privacy'); const docPrivacy = documentsPrivacy.find((d) => d.id === documentId); if (!docPrivacy) { throw new BadRequestException('Document non trouvé'); } return { message: 'Document activé avec succès', documentId: docPrivacy.id, type: docPrivacy.type, version: docPrivacy.version, }; } return { message: 'Document activé avec succès', documentId: document.id, type: document.type, version: document.version, }; } /** * GET /api/v1/documents-legaux/:id/download * Télécharger un document * PUBLIC */ @Get(':id/download') async telechargerDocument( @Param('id', ParseUUIDPipe) documentId: string, @Res() res: Response, ) { const { stream, filename } = await this.documentsService.telechargerDocument(documentId); res.set({ 'Content-Type': 'application/pdf', 'Content-Disposition': `attachment; filename="${filename}"`, }); res.status(HttpStatus.OK).send(stream); } /** * GET /api/v1/documents-legaux/:id/verifier-integrite * Vérifier l'intégrité d'un document (hash SHA-256) * ADMIN ONLY */ @Get(':id/verifier-integrite') // @UseGuards(JwtAuthGuard, RolesGuard) // @Roles('super_admin', 'administrateur') async verifierIntegrite(@Param('id', ParseUUIDPipe) documentId: string) { const integre = await this.documentsService.verifierIntegrite(documentId); return { documentId, integre, message: integre ? 'Le document est intègre (hash valide)' : 'ALERTE : Le document a été modifié (hash invalide)', }; } }