87 lines
3.0 KiB
TypeScript
87 lines
3.0 KiB
TypeScript
import { Controller, Get, Post, Param, Delete, UseGuards, UploadedFile, UseInterceptors, Body, ForbiddenException, NotFoundException, Req, Res, ParseIntPipe } from '@nestjs/common';
|
|
import { FilesService } from './files.service';
|
|
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
|
|
import { FileInterceptor } from '@nestjs/platform-express';
|
|
import { diskStorage } from 'multer';
|
|
import { extname } from 'path';
|
|
import type { Response } from 'express';
|
|
import { PrismaService } from '../prisma/prisma.service';
|
|
import * as fs from 'fs';
|
|
|
|
@Controller('files')
|
|
@UseGuards(JwtAuthGuard)
|
|
export class FilesController {
|
|
constructor(
|
|
private readonly filesService: FilesService,
|
|
private readonly prisma: PrismaService
|
|
) {}
|
|
|
|
@Post('upload')
|
|
@UseInterceptors(FileInterceptor('file', {
|
|
storage: diskStorage({
|
|
destination: './uploads',
|
|
filename: (req, file, callback) => {
|
|
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
|
|
const ext = extname(file.originalname);
|
|
callback(null, `${uniqueSuffix}${ext}`);
|
|
},
|
|
}),
|
|
}))
|
|
async uploadFile(@UploadedFile() file: Express.Multer.File, @Body('timetableEntryId') timetableEntryId: string, @Req() req: any) {
|
|
const user = req.user;
|
|
const entryId = timetableEntryId ? parseInt(timetableEntryId) : undefined;
|
|
|
|
if (!file) {
|
|
throw new NotFoundException('No file uploaded');
|
|
}
|
|
|
|
try {
|
|
if (entryId) {
|
|
// Lesson Upload
|
|
const lesson = await this.prisma.timetableEntry.findUnique({ where: { id: entryId } });
|
|
if (!lesson) throw new NotFoundException('Lesson not found');
|
|
|
|
if (user.role !== 'Lehrer') {
|
|
// Student uploading to lesson
|
|
if (!lesson.allowStudentUploads) {
|
|
throw new ForbiddenException('Uploads not allowed for this lesson');
|
|
}
|
|
}
|
|
} else {
|
|
// General Upload
|
|
if (user.role !== 'Lehrer') {
|
|
throw new ForbiddenException('Only teachers can upload general files');
|
|
}
|
|
}
|
|
|
|
return await this.filesService.saveFile(file, user.id, entryId);
|
|
} catch (error) {
|
|
// Cleanup file if error
|
|
if (file.path && fs.existsSync(file.path)) {
|
|
fs.unlinkSync(file.path);
|
|
}
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
@Get()
|
|
async findAllGeneral() {
|
|
return this.filesService.findAllGeneral();
|
|
}
|
|
|
|
@Get('lesson/:id')
|
|
async findByLesson(@Param('id', ParseIntPipe) id: number, @Req() req: any) {
|
|
return this.filesService.findByLesson(id, req.user.id, req.user.role);
|
|
}
|
|
|
|
@Get('download/:id')
|
|
async downloadFile(@Param('id', ParseIntPipe) id: number, @Res() res: Response) {
|
|
const fileEntity = await this.filesService.getFileEntity(id);
|
|
res.download(fileEntity.path, fileEntity.filename);
|
|
}
|
|
|
|
@Delete(':id')
|
|
async deleteFile(@Param('id', ParseIntPipe) id: number, @Req() req: any) {
|
|
return this.filesService.deleteFile(id, req.user.id, req.user.role);
|
|
}
|
|
} |