A comprehensive NestJS backend system for managing thesis projects, advisor assignments, submissions, and inspections in academic institutions.
- JWT-based Authentication with OTP verification and password reset
- Role-Based Access Control (Admin, Instructor, Student) with fine-grained permissions
- Thesis Group Management - Formation, tracking, and approval workflows
- Submission System - PDF file uploads with verification rounds (max 50MB)
- Inspection Rounds - Time-windowed submission periods by academic year/term
- Advisor Assignment - Automatic assignment and tracking
- Dashboard & Analytics - Real-time progress tracking and statistics
- Real-time Notifications - WebSocket-based instant updates (Socket.io)
- Async Job Processing - RabbitMQ queue for PDF verification
- Secure File Storage - S3-compatible storage (MinIO, AWS S3, etc.)
- Email Service - OTP and notifications via Nodemailer + Handlebars templates
- Audit Logging - Complete activity trail with IP tracking
- Document Configuration - Dynamic document settings with Redis caching
Before you begin, ensure you have the following installed:
- Node.js v18 or higher
- npm or yarn package manager
- PostgreSQL v15 (or use Docker Compose)
- Redis v7 (or use Docker Compose)
- RabbitMQ v3 (or use Docker Compose)
- S3-compatible Storage (MinIO, AWS S3, etc., or use Docker Compose)
- Docker & Docker Compose (recommended for quick setup)
git clone <repository-url>
cd vutf-api
npm installCreate a .env file in the root directory:
cp .env.example .envThen edit .env with your configuration (see Configuration section).
docker-compose up -dThis will start:
- PostgreSQL (port 5434)
- Redis (port 6379)
- RabbitMQ (port 5672 + 15672 for UI)
- MinIO/Storage (port 9000 + 9001 for console)
- Adminer (port 8080) for database GUI
npm run migration:runnpm run seed# Development mode (with hot reload)
npm run start:dev
# Production build
npm run build
npm run start:prodThe API will be available at http://localhost:3000/api/v1
| Category | Technology | Purpose |
|---|---|---|
| Framework | NestJS v11.0.1 | Progressive Node.js framework |
| Language | TypeScript | Type-safe development |
| Database | PostgreSQL 15 + TypeORM | Relational data storage & ORM |
| Authentication | Passport.js + JWT + bcrypt | Secure user authentication |
| Real-time | Socket.io (@nestjs/websockets) | WebSocket-based notifications |
| Caching | Redis + ioredis | In-memory cache for tokens & OTP |
| Message Queue | RabbitMQ + @golevelup/nestjs-rabbitmq | Async job processing |
| File Storage | S3-compatible (MinIO, AWS S3, etc.) | Object storage |
| Nodemailer + Handlebars | Email/OTP delivery | |
| File Processing | ExcelJS, PDFMake, Archiver | Document generation |
| HTTP Client | Axios | External API calls |
| Validation | class-validator | DTO validation |
| Scheduling | @nestjs/schedule | Task scheduling |
| Testing | Jest + Supertest | Unit & E2E testing |
| Linting | ESLint + Prettier | Code quality |
Create a .env file in the root with the following variables:
| Variable | Default | Description |
|---|---|---|
| PORT | 3000 | Application port |
| NODE_ENV | development | Environment (development/production) |
| FRONTEND_URL | http://localhost:5173 | Frontend URL for CORS |
| DB_HOST | localhost | PostgreSQL host |
| DB_PORT | 5432 | PostgreSQL port |
| DB_USERNAME | postgres | Database username |
| DB_PASSWORD | postgres | Database password |
| DB_DATABASE | vutf_db | Database name |
| REDIS_HOST | localhost | Redis host |
| REDIS_PORT | 6379 | Redis port |
| REDIS_PASSWORD | (empty) | Redis password (if auth required) |
| JWT_ACCESS_SECRET | (required) | Secret key for access tokens |
| JWT_REFRESH_SECRET | (required) | Secret key for refresh tokens |
| JWT_ACCESS_EXPIRE | 15m | Access token expiration |
| JWT_REFRESH_EXPIRE | 7d | Refresh token expiration |
| MAIL_HOST | smtp.gmail.com | SMTP server host |
| MAIL_PORT | 587 | SMTP port |
| MAIL_USER | (required) | Email address for sending |
| MAIL_PASSWORD | (required) | Email password/app-password |
| MAIL_FROM | "No Reply" noreply@example.com | From email address |
| STORAGE_ENDPOINT | localhost | Storage endpoint (S3, MinIO, etc.) |
| STORAGE_PORT | 9000 | Storage port |
| STORAGE_USE_SSL | false | Use SSL/TLS |
| STORAGE_ROOT_USER | minioadmin | Storage root user |
| STORAGE_ROOT_PASSWORD | minioadmin | Storage root password |
| STORAGE_ACCESS_KEY | (required) | Storage access key |
| STORAGE_SECRET_KEY | (required) | Storage secret key |
| STORAGE_BUCKET | submissions | Default bucket name |
| STORAGE_REGION | us-east-1 | Storage region |
| RABBITMQ_HOST | localhost | RabbitMQ host |
| RABBITMQ_PORT | 5672 | RabbitMQ port |
| RABBITMQ_USER | guest | RabbitMQ username |
| RABBITMQ_PASSWORD | guest | RabbitMQ password |
| RABBITMQ_JOB_QUEUE | pdf_verification_jobs | PDF job queue name |
| RABBITMQ_RESULT_QUEUE | pdf_verification_results | Result queue name |
| UPLOAD_MAX_FILE_SIZE | 52428800 | Max file size in bytes (50MB) |
| Entity | Purpose |
|---|---|
user_account |
User authentication with roles (admin, instructor, student) |
student |
Student profile linked to user account |
instructor |
Instructor profile linked to user account |
thesis_group |
Student thesis group (statuses: incomplete → pending → approved/rejected) |
group_member |
Group membership tracking with member status |
thesis |
Core thesis/capstone project entity |
thesis_topic |
Pre-defined thesis topics for selection |
advisor_assignment |
Advisor-to-group assignments |
submissions |
File submissions (statuses: pending → verified/rejected) |
inspection_round |
Submission deadline periods (year/term/round based) |
report_file |
Generated reports and outputs |
notifications |
User notifications |
audit_log |
Complete audit trail of user actions |
permissions |
Fine-grained access control permissions |
user_permissions |
Many-to-many: user to permissions mapping |
# Generate new migration
npm run migration:generate
# Run pending migrations
npm run migration:run
# Revert last migration
npm run migration:revertAll endpoints are prefixed with /api/v1
POST /auth/login- User login with email/passwordPOST /auth/logout- User logoutPOST /auth/refresh- Refresh JWT tokensPOST /auth/request-otp- Request OTP for registrationPOST /auth/verify-otp- Verify registration OTPPOST /auth/register- User registrationPOST /auth/forgot-password- Initiate password resetPOST /auth/reset-password- Complete password resetGET /auth/me- Get current user profile
GET /users- List all users (admin only)GET /users/:id- Get user by IDPUT /users/:id- Update user profileDELETE /users/:id- Deactivate user account
POST /thesis-group- Create thesis groupGET /thesis-group- List thesis groupsGET /thesis-group/:id- Get group detailsPUT /thesis-group/:id- Update groupPOST /thesis-group/:id/submit-for-approval- Submit for approvalPOST /thesis-group/:id/approve- Approve group (advisor)POST /thesis-group/:id/reject- Reject group (advisor)
POST /submissions- Submit file (student, max 50MB PDF)GET /submissions- List submissionsGET /submissions/:id- Get submission detailsGET /submissions/:id/file- Download submission fileGET /submissions/group/:groupId- Get group submissionsPOST /submissions/:id/verify- Verify submission (instructor)POST /submissions/:id/reject- Reject submission (instructor)
GET /inspection-rounds- List inspection roundsPOST /inspection-rounds- Create inspection round (admin)PUT /inspection-rounds/:id- Update roundDELETE /inspection-rounds/:id- Delete round
GET /dashboard- Get dashboard analyticsGET /dashboard/statistics- Get system statistics
/student- Student profile management/instructor- Instructor profile management/advisor-assignment- Advisor assignments/announcements- System announcements/audit-logs- Activity audit trail/notifications- Real-time notifications
Group Creation → Add Members → Select Topic →
Submit for Approval → Pending Status →
Approved/Rejected by Advisor
Active Inspection Round → Student Uploads PDF →
Pending Verification → Async PDF Processing via RabbitMQ →
Verified/Rejected Result → Notification Sent
- WebSocket (Socket.io) connection for instant updates
- Events: new submission, verification result, approval status
- Automatic reconnection with exponential backoff
- RabbitMQ job queue (
pdf_verification_jobs) - Background workers verify PDF integrity
- Results sent to
pdf_verification_resultsqueue - User notified via WebSocket upon completion
- Files stored securely in S3-compatible storage
- Pre-signed URLs for download links (time-limited)
- Access control: only group members and advisors can download
- 50MB file size limit enforced
- Registration OTP valid for 5 minutes
- Password reset OTP valid for 5 minutes
- Rate limiting: max 3 OTP requests per 15 minutes
- Handlebars templates for professional emails
- Max 5 failed login attempts
- Account locked for 15 minutes after max attempts
- Unlock via admin action or time-based auto-unlock
- Complete audit trail with IP tracking
Quick reference for local services:
# Start all services
docker-compose up -d
# Stop all services
docker-compose down
# View logs
docker-compose logs -f
# Rebuild containers
docker-compose build --no-cache| Service | Port | URL | Notes |
|---|---|---|---|
| API | 3000 | http://localhost:3000 | NestJS backend |
| PostgreSQL | 5434 | - | Database (vutf_db) |
| Redis | 6379 | - | Cache store |
| RabbitMQ | 5672 | - | Message broker (AMQP) |
| RabbitMQ UI | 15672 | http://localhost:15672 | Management console (guest/guest) |
| Storage | 9000 | - | S3-compatible object storage API |
| Storage Console | 9001 | http://localhost:9001 | File browser UI (minioadmin/minioadmin) |
| Adminer | 8080 | http://localhost:8080 | Database GUI |
# Unit tests
npm run test
# Unit tests with coverage
npm run test:cov
# E2E tests
npm run test:e2e
# Watch mode for tests
npm run test:watch# Lint code
npm run lint
# Format code
npm run format
# Check formatting
npm run format:check# Compile TypeScript
npm run build
# Run production server
npm run start:prod# Seed sample data
npm run seed
# Generate migrations after model changes
npm run migration:generateThe API follows RESTful conventions with structured responses.
Success Response:
{
"statusCode": 200,
"message": "Success",
"data": {
"id": "uuid",
"email": "user@example.com"
}
}Error Response:
{
"statusCode": 400,
"message": "Bad Request",
"error": "Invalid email format"
}Include JWT token in request header:
Authorization: Bearer <your-jwt-token>
Login:
curl -X POST http://localhost:3000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "password123"
}'Submit File:
curl -X POST http://localhost:3000/api/v1/submissions \
-H "Authorization: Bearer <token>" \
-F "file=@thesis.pdf" \
-F "groupId=<group-id>" \
-F "inspectionRoundId=<round-id>"Get Dashboard:
curl -X GET http://localhost:3000/api/v1/dashboard \
-H "Authorization: Bearer <token>"For more detailed API documentation, refer to the source code comments or enable Swagger/OpenAPI if configured.
# Development
npm run start:dev # Start with hot reload
npm run start # Start normally
npm run build # Build for production
npm run start:prod # Production server
# Testing
npm run test # Run unit tests
npm run test:e2e # Run E2E tests
npm run test:cov # Coverage report
# Database
npm run migration:run # Run pending migrations
npm run migration:generate # Generate new migration
npm run migration:revert # Revert last migration
npm run seed # Seed database
# Code Quality
npm run lint # Run ESLint
npm run format # Format with Prettier
# Docker
docker-compose up -d # Start services
docker-compose down # Stop services
docker-compose logs -f # View logs