|
1 | | -# Learning Management System (LMS) |
2 | | - |
3 | | -## 📌 Project Overview |
4 | | -A comprehensive Learning Management System designed to bridge the gap between teachers and students. This platform features a scalable backend for managing data and a responsive frontend for a seamless user experience. It supports role-based access, course management, assignment tracking, and secure authentication. |
5 | | - |
6 | | -## 🚀 Tech Stack |
7 | | - |
8 | | -### Frontend |
9 | | -- **Framework:** React (Vite) |
10 | | -- **State Management:** Redux Toolkit |
11 | | -- **Styling:** CSS Modules & Global Variables |
12 | | -- **Routing:** React Router v6 |
13 | | -- **HTTP Client:** Axios |
| 1 | +# Mini LMS (Learning Management System) Backend |
| 2 | + |
| 3 | +An advanced, resilient, and secure RESTful API for a Learning Management System designed to handle core educational workflows: course creation, student enrollment, assignment distribution, and grade-less submission tracking. |
| 4 | + |
| 5 | +## Overview |
| 6 | +This backend powers a multi-tenant learning environment where Teachers manage courses and assignments, and Students enroll in those courses and submit their work. It heavily emphasizes security boundaries, rate-limiting resilience, and strict data consistency logic utilizing modern Node.js backend practices. |
| 7 | + |
| 8 | +## Tech Stack |
| 9 | +* **Language & Runtime:** Node.js (v20), ES Modules |
| 10 | +* **Framework:** Express.js (v5) |
| 11 | +* **Database & ORM:** PostgreSQL (v15), Prisma ORM |
| 12 | +* **Security & Hardening:** Helmet, express-rate-limit, CORS, bcrypt, Joi |
| 13 | +* **Observability:** Winston (Structured logging, Recursive redaction) |
| 14 | +* **Testing:** Jest, Supertest |
| 15 | +* **CI/CD:** GitHub Actions (Clean-clone DB migration tests) |
| 16 | + |
| 17 | +## Architecture |
| 18 | + |
| 19 | +```mermaid |
| 20 | +graph TD |
| 21 | + Client[Client App / Postman] --> |HTTP / JSON| API[Express API Gateway] |
| 22 | + |
| 23 | + subgraph Express Backend |
| 24 | + API --> RateLimit[Rate Limiter] |
| 25 | + RateLimit --> Auth[Auth Middleware] |
| 26 | + Auth --> Validation[Joi Boundary Validation] |
| 27 | + Validation --> Controllers[Controllers] |
| 28 | + Controllers --> CoreAuth[Core Authorization] |
| 29 | + CoreAuth --> Services[Domain Services] |
| 30 | + end |
| 31 | + |
| 32 | + Services --> |Prisma Client| DB[(PostgreSQL)] |
| 33 | + |
| 34 | + subgraph Observability |
| 35 | + Controllers -.-> Logger[Winston Logger] |
| 36 | + Services -.-> Logger |
| 37 | + Logger -.-> |Redacts PII/Tokens| LogOutput[Stdout/JSON] |
| 38 | + end |
| 39 | +``` |
14 | 40 |
|
15 | | -### Backend |
16 | | -- **Runtime:** Node.js |
17 | | -- **Framework:** Express.js |
18 | | -- **Database:** PostgreSQL (via Prisma ORM) |
19 | | -- **Authentication:** JWT (JSON Web Tokens) |
20 | | -- **Validation:** Joi |
21 | | -- **Security:** Helmet, CORS, bcrypt |
| 41 | +## Project Structure |
| 42 | +```text |
| 43 | +backend/ |
| 44 | +├── src/ |
| 45 | +│ ├── app.js # Express app configuration & hardening |
| 46 | +│ ├── server.js # Entry point & Graceful shutdown |
| 47 | +│ ├── config/ # Centralized environment variable parsing |
| 48 | +│ ├── controllers/ # HTTP request/response handlers |
| 49 | +│ ├── core/ # Core domain logic (e.g., authorization.js) |
| 50 | +│ ├── middlewares/ # Joi validation, error handling, logging, JWT auth |
| 51 | +│ ├── routes/ # Route definitions |
| 52 | +│ ├── services/ # Business logic and Prisma DB interactions |
| 53 | +│ ├── utils/ # Helpers (e.g., JWT signing/verification) |
| 54 | +│ └── validations/ # Joi schema definitions |
| 55 | +├── tests/ # Jest integration test suite & fixtures |
| 56 | +├── database/ # Prisma schema, migrations, config |
| 57 | +├── .github/workflows/ # CI/CD pipelines |
| 58 | +├── package.json # NPM dependencies & scripts |
| 59 | +└── eslint.config.js # Linter configuration |
| 60 | +``` |
22 | 61 |
|
23 | | -## ✨ Features |
| 62 | +## Getting Started |
24 | 63 |
|
25 | | -### Core |
26 | | -- **User Authentication:** Secure signup/login with JWT. |
27 | | -- **Role-Based Access Control (RBAC):** Strict separation between Teacher and Student roles. |
| 64 | +### Prerequisites |
| 65 | +* Node.js (v20+) |
| 66 | +* Docker & Docker Compose (for the local test database) |
| 67 | +* PostgreSQL (if running locally without Docker) |
| 68 | + |
| 69 | +### Environment Setup |
| 70 | +Create a `.env` file in the `backend/` directory: |
| 71 | + |
| 72 | +```env |
| 73 | +NODE_ENV=development |
| 74 | +PORT=3000 |
| 75 | +DATABASE_URL=postgresql://lmsuser:lmspassword@localhost:5432/lmsdb |
| 76 | +JWT_SECRET=super_secret_jwt_key_that_is_at_least_32_bytes_long |
| 77 | +JWT_EXPIRES_IN=1d |
| 78 | +CORS_ORIGIN=http://localhost:3000 |
| 79 | +RATE_LIMIT_LOGIN_MAX=5 |
| 80 | +RATE_LIMIT_REGISTER_MAX=10 |
| 81 | +``` |
28 | 82 |
|
29 | | -### 👩🏫 Teacher Portal |
30 | | -- **Dashboard:** Overview of created courses. |
31 | | -- **Course Management:** Create and update courses. |
32 | | -- **Assignments:** Create assignments and review student submissions. |
| 83 | +### Installation & Execution |
| 84 | +```bash |
| 85 | +cd backend/ |
| 86 | +npm install |
33 | 87 |
|
34 | | -### 👨🎓 Student Portal |
35 | | -- **Dashboard:** View enrolled courses. |
36 | | -- **Enrollment:** Browse and enroll in available courses. |
37 | | -- **Assignments:** Submit work and track progress. |
| 88 | +# Apply database migrations |
| 89 | +npx prisma migrate dev |
38 | 90 |
|
39 | | -## 📂 Project Structure |
40 | | -``` |
41 | | -Learning_management_system/ |
42 | | -├── frontend/ # React application |
43 | | -│ ├── src/ # Components, Pages, Redux Store |
44 | | -│ └── ... |
45 | | -├── backend/ # Node.js Express API |
46 | | -│ ├── src/ # Controllers, Routes, Services, Prisma |
47 | | -│ └── ... |
48 | | -└── README.md # Project documentation (this file) |
| 91 | +# Start the server (Development) |
| 92 | +npm run dev |
49 | 93 | ``` |
50 | 94 |
|
51 | | -## 🛠️ Setup & Installation |
| 95 | +## API Reference |
52 | 96 |
|
53 | | -### Prerequisites |
54 | | -- Node.js (v18+) |
55 | | -- PostgreSQL (installed and running) |
| 97 | +### Authentication |
| 98 | +| Method | Endpoint | Description | Auth Required | |
| 99 | +| :--- | :--- | :--- | :--- | |
| 100 | +| `POST` | `/auth/register` | Register a new user (Teacher/Student) | No | |
| 101 | +| `POST` | `/auth/login` | Authenticate and receive a JWT | No | |
56 | 102 |
|
57 | | -### 1. Backend Setup |
58 | | -Navigate to the backend directory and set up the API and database. |
| 103 | +### Courses & Enrollments |
| 104 | +| Method | Endpoint | Description | Auth Required (Role) | |
| 105 | +| :--- | :--- | :--- | :--- | |
| 106 | +| `GET` | `/courses` | List all available courses | No | |
| 107 | +| `POST` | `/courses` | Create a new course | Yes (TEACHER) | |
| 108 | +| `GET` | `/courses/enrolled` | List courses the student is enrolled in | Yes (STUDENT) | |
| 109 | +| `POST` | `/courses/:id/enroll` | Enroll the current student into a course | Yes (STUDENT) | |
| 110 | +| `GET` | `/courses/:id/assignments` | List assignments for a course | Yes (Enrolled STUDENT / Owning TEACHER) | |
| 111 | +| `POST` | `/courses/:id/assignments` | Create a new assignment for a course | Yes (Owning TEACHER) | |
59 | 112 |
|
60 | | -```bash |
61 | | -cd backend |
62 | | -``` |
| 113 | +### Assignments & Submissions |
| 114 | +| Method | Endpoint | Description | Auth Required (Role) | |
| 115 | +| :--- | :--- | :--- | :--- | |
| 116 | +| `POST` | `/assignments/:id/submit` | Submit work for an assignment | Yes (Enrolled STUDENT) | |
| 117 | +| `GET` | `/assignments/:id/submissions` | List all submissions for an assignment | Yes (Owning TEACHER) | |
63 | 118 |
|
64 | | -**Install Dependencies & Setup Environment:** |
65 | | -You can use the provided setup script or configure manually. |
| 119 | +## Security |
66 | 120 |
|
67 | | -```bash |
68 | | -# Option A: Automatic Setup |
69 | | -./setup.sh |
70 | | - |
71 | | -# Option B: Manual Setup |
72 | | -npm install |
73 | | -cp .env.example .env |
74 | | -# Edit .env with your DATABASE_URL and JWT_SECRET |
75 | | -npx prisma migrate dev --name init |
76 | | -``` |
| 121 | +This system implements a defense-in-depth security architecture: |
77 | 122 |
|
78 | | -**Start the Server:** |
79 | | -```bash |
80 | | -npm run dev |
81 | | -``` |
82 | | -> The backend runs on `http://localhost:3000`. |
| 123 | +1. **Strict Boundary Validation**: All incoming requests pass through a global `validateBody` middleware using strict Joi schemas (`stripUnknown: false`, `allowUnknown: false`), dropping malformed payloads before they reach business logic. |
| 124 | +2. **Rate Limiting**: Authentication endpoints are heavily protected against brute-force attacks via memory-stored rate limiters (`trust proxy` enabled). |
| 125 | +3. **Recursive Log Redaction**: The Winston logger utilizes a recursive object traversal function to guarantee `password`, `token`, and `authorization` keys are redacted (`[REDACTED]`), regardless of how deeply nested they are within request payloads or error stacks. |
| 126 | +4. **Isolated Authorization (`core/authorization.js`)**: Authorization is strictly split from authentication. Role checks are handled via the JWT middleware, but **ownership** (`assertOwnsCourse`) and **enrollment** (`assertEnrolled`) domain checks are abstracted into an isolated `core/authorization.js` module. This guarantees that standard Prisma queries always wrap the required database lookups to verify a Teacher actually owns the course they are modifying, or a Student is genuinely enrolled in the course they are interacting with. |
83 | 127 |
|
84 | | -### 2. Frontend Setup |
85 | | -Open a new terminal and navigate to the frontend directory. |
| 128 | +## Testing |
| 129 | +The repository maintains strict integration test coverage spanning the full API boundary, database constraint validation, rate limiting, and log redaction. |
86 | 130 |
|
87 | 131 | ```bash |
88 | | -cd frontend |
| 132 | +# Run the full test suite (automatically spins up a clean Postgres container) |
| 133 | +npm test |
89 | 134 | ``` |
90 | 135 |
|
91 | | -**Install Dependencies:** |
92 | | -```bash |
93 | | -npm install |
94 | | -``` |
| 136 | +## Design Decisions |
| 137 | +- **Hard Delete cascades**: `onDelete: Cascade` rules were implemented strictly across the schema. A course serves as a container; deleting a course destroys its assignments and submissions. However, deleting a user is restricted if they have graded submissions, preserving historical academic integrity. |
| 138 | +- **UUIDs and API Coercion**: A dedicated integer coercion middleware shields the database from Prisma's `NaN` panics. |
| 139 | +- **Graceful Shutdown & Resilience**: The application leverages `SIGTERM`/`SIGINT` traps and explicitly delays startup until the database emits a successful connection ping. |
95 | 140 |
|
96 | | -**Start the Application:** |
97 | | -```bash |
98 | | -npm run dev |
99 | | -``` |
100 | | -> The frontend runs on `http://localhost:5173`. |
101 | | -
|
102 | | -## 🧪 Verification & Usage |
103 | | -1. **Register as a Teacher** to create a test course and assignment. |
104 | | -2. **Register as a Student** (incognito window recommended) to enroll in the course. |
105 | | -3. **Submit an Assignment** as a student and view it as a teacher. |
106 | | - |
107 | | -## ✅ Requirements Fulfillment |
108 | | -This project satisfies the core requirements for a scalable LMS platform: |
109 | | -- **Architecture:** Decoupled Frontend and Backend. |
110 | | -- **Security:** Password hashing, JWT auth, and RBAC middleware. |
111 | | -- **Database:** Relational schema with Prisma ORM. |
112 | | -- **Code Quality:** Modular structure, centralized error handling, and input validation. |
| 141 | +## Limitations |
| 142 | +- **No Frontend**: This repository is strictly a backend API. The GitHub Actions CI pipeline verifies backend linting, database migrations from scratch, and integration tests, but intentionally does not build or assert UI artifacts. |
| 143 | +- **In-Memory Rate Limiting**: The `express-rate-limit` configuration uses the default memory store. In a multi-node production deployment, this should be migrated to a Redis store. |
0 commit comments