imkFinal/backend/src/documents/documents.controller.ts
2025-02-25 20:41:23 +01:00

127 lines
3.5 KiB
TypeScript

import { Controller, Get, Param, Req, Res, UseGuards, Logger, Request, Post, UseInterceptors, UploadedFile, Body } from '@nestjs/common';
import { Response } from 'express';
import { DocumentsService } from './documents.service';
import { JwtAuthGuard } from '../auth/jwt-auth.guard';
import { S3Service } from '../s3/s3.service';
import { FileInterceptor } from '@nestjs/platform-express';
interface S3File {
buffer: Buffer;
contentType: string;
contentLength: number;
fileName: string;
}
@Controller('documents')
export class DocumentsController {
private readonly logger = new Logger(DocumentsController.name);
constructor(
private readonly documentsService: DocumentsService,
private readonly s3Service: S3Service
) {
this.logger.log('DocumentsController initialized');
}
@Post('upload')
@UseGuards(JwtAuthGuard)
@UseInterceptors(FileInterceptor('file'))
async uploadDocument(
@UploadedFile() file: Express.Multer.File,
@Body('title') title: string,
@Body('sharedWithId') sharedWithId: string,
@Request() req,
) {
this.logger.log('=== Document upload endpoint hit ===');
this.logger.debug('Upload request received:', {
fileName: file?.originalname,
fileSize: file?.size,
title,
sharedWithId,
uploadedById: req.user.id,
});
try {
const result = await this.documentsService.uploadDocument(
file,
title,
Number(sharedWithId),
req.user.id,
);
this.logger.debug('Document upload successful:', {
documentId: result.id,
title: result.title,
s3Key: result.s3Key,
});
return result;
} catch (error) {
this.logger.error('Document upload failed:', {
error: error.message,
stack: error.stack,
});
throw error;
}
}
@Get('shared/:userId')
@UseGuards(JwtAuthGuard)
async getSharedDocuments(@Param('userId') userId: string) {
return this.documentsService.getClientDocuments(Number(userId));
}
@Get('download/:key')
@UseGuards(JwtAuthGuard)
async downloadDocument(
@Param('key') key: string,
@Request() req,
@Res() res: Response
) {
try {
this.logger.debug(`Download request for key: ${key}`);
const decodedKey = decodeURIComponent(key);
this.logger.debug(`Decoded key: ${decodedKey}`);
// Get document from database first to verify access
const document = await this.documentsService.findDocumentByS3Key(decodedKey);
if (!document) {
return res.status(404).json({ message: 'Document not found' });
}
// Verify user has access to this document
const hasAccess = await this.documentsService.verifyDocumentAccess(
document.id,
req.user.id
);
if (!hasAccess) {
return res.status(403).json({ message: 'Access denied' });
}
// Get the file from S3
const file = await this.s3Service.getFile(decodedKey);
if (!file || !file.buffer) {
return res.status(404).json({ message: 'File not found in storage' });
}
res.set({
'Content-Type': file.contentType || 'application/octet-stream',
'Content-Length': file.contentLength,
'Content-Disposition': `attachment; filename="${encodeURIComponent(file.fileName)}"`,
});
return res.send(file.buffer);
} catch (error) {
this.logger.error('Download error:', error);
return res.status(500).json({
message: 'Failed to download file',
error: error.message
});
}
}
}