DEV Community

Cover image for Day 11 - Building the Document Management System
Nader Fkih Hassen
Nader Fkih Hassen

Posted on

Day 11 - Building the Document Management System

I focused on implementing one of the key features for any legal platform: document management. Since Lura is a case-centric system, each legal case can hold multiple documents. These need to be uploaded, listed, downloaded, and (by authorized users) deleted.

๐Ÿ“ Goals

  • Allow users to upload documents to specific cases
  • Store document metadata in the database
  • Link each file to a workspace and case
  • Allow admins to delete files
  • Prevent unauthorized access to documents

๐Ÿ”จ Stack & Tools Used

  • Frontend: Next.js + FormData for file uploads
  • Backend: NestJS + Multer (file middleware)
  • ORM: Prisma
  • Database: PostgreSQL
  • File Storage: Local for now (to be moved to cloud storage later)

๐Ÿ“ฆ Backend โ€“ File Upload API
Using NestJS, I created an endpoint to handle uploads. We used the Multer middleware to manage multipart/form-data.

@Post('upload/:caseId')
@UseInterceptors(FileInterceptor('file'))
uploadDoc(@UploadedFile() file, @Param('caseId') caseId: string) {
  return this.docService.storeFile(file, caseId);
}
Enter fullscreen mode Exit fullscreen mode

Files are saved locally in /uploads and registered in the Document table with their name, caseId, and uploadedAt timestamp.

๐Ÿ’ป Frontend โ€“ Upload Interface
On the frontend, I created a basic upload component using
<input type="file" /> with a button to trigger submission via fetch:

const formData = new FormData();
formData.append("file", selectedFile);
await fetch(`/api/upload/${caseId}`, {
  method: "POST",
  body: formData
});
Enter fullscreen mode Exit fullscreen mode

Once uploaded, the new document appears in a list with its name and an option to delete (visible only to Admins).

๐Ÿงน Delete Function with Permissions
Admins can delete documents via a secure DELETE endpoint. We used role checking middleware to ensure that only authorized roles (Admin, Super Admin) can delete.

@Delete(':docId')
@UseGuards(AuthGuard, RoleGuard)
deleteDoc(@Param('docId') id: string) {
  return this.docService.delete(id);
}
Enter fullscreen mode Exit fullscreen mode

โœ… Key Lessons & Takeaways

  • NestJS makes handling file uploads smooth with built-in interceptors
  • RBAC is essential โ€” users shouldnโ€™t even see buttons they canโ€™t use
  • File metadata (not just the file) is important for traceability
  • Uploading should feel seamless, especially in a legal tool where reliability matters

โ“Question for You
How do you handle secure file uploads in your apps โ€” and do you prefer local or cloud storage?

Top comments (0)