/** * GDPR Controller * * Endpoints for GDPR compliance (data export, deletion, consent) */ import { Controller, Get, Post, Delete, Body, UseGuards, HttpCode, HttpStatus, Res, } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse } from '@nestjs/swagger'; import { Response } from 'express'; import { JwtAuthGuard } from '../guards/jwt-auth.guard'; import { CurrentUser } from '../decorators/current-user.decorator'; import { UserPayload } from '../decorators/current-user.decorator'; import { GDPRService, ConsentData } from '../services/gdpr.service'; @ApiTags('GDPR') @Controller('gdpr') @UseGuards(JwtAuthGuard) @ApiBearerAuth() export class GDPRController { constructor(private readonly gdprService: GDPRService) {} /** * Export user data (GDPR Right to Data Portability) */ @Get('export') @ApiOperation({ summary: 'Export all user data', description: 'Export all personal data in JSON format (GDPR Article 20)', }) @ApiResponse({ status: 200, description: 'Data export successful', }) async exportData( @CurrentUser() user: UserPayload, @Res() res: Response, ): Promise { const exportData = await this.gdprService.exportUserData(user.id); // Set headers for file download res.setHeader('Content-Type', 'application/json'); res.setHeader( 'Content-Disposition', `attachment; filename="xpeditis-data-export-${user.id}-${Date.now()}.json"`, ); res.json(exportData); } /** * Export user data as CSV */ @Get('export/csv') @ApiOperation({ summary: 'Export user data as CSV', description: 'Export personal data in CSV format for easy viewing', }) @ApiResponse({ status: 200, description: 'CSV export successful', }) async exportDataCSV( @CurrentUser() user: UserPayload, @Res() res: Response, ): Promise { const exportData = await this.gdprService.exportUserData(user.id); // Convert to CSV (simplified version) let csv = 'Category,Field,Value\n'; // User data Object.entries(exportData.userData).forEach(([key, value]) => { csv += `User Data,${key},"${value}"\n`; }); // Set headers res.setHeader('Content-Type', 'text/csv'); res.setHeader( 'Content-Disposition', `attachment; filename="xpeditis-data-export-${user.id}-${Date.now()}.csv"`, ); res.send(csv); } /** * Delete user data (GDPR Right to Erasure) */ @Delete('delete-account') @HttpCode(HttpStatus.NO_CONTENT) @ApiOperation({ summary: 'Delete user account and data', description: 'Permanently delete or anonymize user data (GDPR Article 17)', }) @ApiResponse({ status: 204, description: 'Account deletion initiated', }) async deleteAccount( @CurrentUser() user: UserPayload, @Body() body: { reason?: string; confirmEmail: string }, ): Promise { // Verify email confirmation (security measure) if (body.confirmEmail !== user.email) { throw new Error('Email confirmation does not match'); } await this.gdprService.deleteUserData(user.id, body.reason); } /** * Record consent */ @Post('consent') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Record user consent', description: 'Record consent for marketing, analytics, etc. (GDPR Article 7)', }) @ApiResponse({ status: 200, description: 'Consent recorded', }) async recordConsent( @CurrentUser() user: UserPayload, @Body() body: Omit, ): Promise<{ success: boolean }> { await this.gdprService.recordConsent({ ...body, userId: user.id, }); return { success: true }; } /** * Withdraw consent */ @Post('consent/withdraw') @HttpCode(HttpStatus.OK) @ApiOperation({ summary: 'Withdraw consent', description: 'Withdraw consent for marketing or analytics (GDPR Article 7.3)', }) @ApiResponse({ status: 200, description: 'Consent withdrawn', }) async withdrawConsent( @CurrentUser() user: UserPayload, @Body() body: { consentType: 'marketing' | 'analytics' }, ): Promise<{ success: boolean }> { await this.gdprService.withdrawConsent(user.id, body.consentType); return { success: true }; } /** * Get consent status */ @Get('consent') @ApiOperation({ summary: 'Get current consent status', description: 'Retrieve current consent preferences', }) @ApiResponse({ status: 200, description: 'Consent status retrieved', }) async getConsentStatus( @CurrentUser() user: UserPayload, ): Promise { return this.gdprService.getConsentStatus(user.id); } }