A complete backend system for managing college timetables using Node.js, Express.js, and AWS DynamoDB.
-
Dual Authentication System
- Admin authentication using email + password
- Student authentication using USN + password
- JWT token-based authentication
- Separate middleware for admin and student routes
-
Timetable Management
- Add single slot or batch slots
- Update and delete timetable entries
- View weekly or daily timetables
- Automatic duplicate slot validation
- Some filter methods for both faculty and students
- Checks for the faculty or section clash in timetable
-
Database
- AWS DynamoDB with optimized table structure
- AWS SDK v3 implementation
- Node.js (v14 or higher)
- AWS Account with DynamoDB access
- AWS Access Key ID and Secret Access Key
-
Clone the repository and install dependencies:
npm install
-
Set up environment variables:
- Copy
.env.exampleto.env - Fill in your AWS credentials and JWT secret:
PORT=3000 NODE_ENV=development JWT_SECRET=your_super_secret_jwt_key AWS_REGION=us-east-1 AWS_ACCESS_KEY_ID=your_access_key AWS_SECRET_ACCESS_KEY=your_secret_key
- Copy
-
Create DynamoDB Tables:
π For detailed step-by-step instructions, see DYNAMODB_SETUP.md
Quick summary:
- Create IAM user with DynamoDB permissions
- Get Access Key ID and Secret Access Key
- Create two tables in AWS DynamoDB:
Table 1: Users
- Table name:
Users(exact, case-sensitive) - Partition key:
PK(String) - No sort key required
Table 2: TimeTable
- Table name:
TimeTable(exact, case-sensitive) - Partition key:
PK(String) - Sort key:
SK(String)
npm startThe server will start on http://localhost:3000 (or the port specified in .env).
POST /admin/register
Content-Type: application/json
{
"email": "admin@college.edu",
"password": "admin123",
"name": "Admin Name"
}
POST /admin/login
Content-Type: application/json
{
"email": "admin@college.edu",
"password": "admin123"
}
Response:
{
"success": true,
"message": "Login successful",
"user": {
"email": "admin@college.edu",
"name": "Admin Name",
"userType": "ADMIN"
}
}
Note: JWT token is automatically set as HTTP-only cookie (adminToken)
POST /admin/logout
Response:
{
"success": true,
"message": "Admin logged out successfully"
}
Note: Clears the adminToken cookie
POST /student/register
Content-Type: application/json
{
"usn": "1RI23IS050",
"password": "student123",
"name": "Student Name"
}
POST /student/login
Content-Type: application/json
{
"usn": "1RI23IS050",
"password": "student123"
}
Response:
{
"success": true,
"message": "Login successful",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": {
"usn": "1RI23IS050",
"name": "Student Name",
"userType": "STUDENT"
}
}
Note: All admin endpoints require authentication. Authentication is handled via:
- Cookies (Preferred): JWT token is automatically sent via HTTP-only cookie (
adminToken) after login - Headers (Fallback): You can still use Bearer token in Authorization header:
Authorization: Bearer <your_jwt_token>
POST /admin/timetable/addSingleSlot
Authorization: Bearer <token>
Content-Type: application/json
{
"year_section": "5A",
"day": "MONDAY",
"slot": 2,
"subject": "DBMS",
"faculty": "RSH",
"room": "LHC-315",
"type": "Theory"
}
POST /admin/timetable/addBatchForDay
Authorization: Bearer <token>
Content-Type: application/json
{
"year_section": "5A",
"day": "MONDAY",
"slots": [
{
"slot": 1,
"subject": "OS",
"faculty": "JDS",
"room": "LHC-315",
"type": "Theory"
},
{
"slot": 2,
"subject": "DBMS",
"faculty": "RSH",
"room": "LHC-315",
"type": "Theory"
}
]
}
PUT /admin/timetable/updateSlot
Authorization: Bearer <token>
Content-Type: application/json
{
"year_section": "5A",
"day": "MONDAY",
"slot": 2,
"subject": "Advanced DBMS",
"faculty": "RSH",
"room": "LHC-320",
"type": "Theory"
}
DELETE /admin/timetable/deleteSlot?year_section=5A&day=MONDAY&slot=2
Authorization: Bearer <token>
GET /admin/timetable/faculty/RSH
Authorization: Bearer <token>
Query parameters alternative:
GET /admin/timetable/faculty/RSH
GET /admin/timetable/faculty?faculty=RSH
Authorization: Bearer <token>
Business rule: A teacher can teach a maximum of 5 slots per day.
GET /admin/timetable/faculty/daily-load?faculty=RSH&day=MONDAY
Authorization: Bearer <token>
Response:
{
"success": true,
"message": "Daily load for faculty 'RSH' on MONDAY calculated successfully",
"faculty": "RSH",
"day": "MONDAY",
"assignedSlots": 3,
"remainingSlots": 2,
"maxSlotsPerDay": 5
}
Note: All student endpoints require authentication. Authentication is handled via:
- Cookies (Preferred): JWT token is automatically sent via HTTP-only cookie (
studentToken) after login - Headers (Fallback): You can still use Bearer token in Authorization header:
Authorization: Bearer <your_jwt_token>
GET /student/timetable/weekly/5A
Authorization: Bearer <token>
GET /student/timetable/day/5A/MONDAY
Authorization: Bearer <token>
Returns the next upcoming class (day and slot) for a given subject in a year/section, based on the current server day and time.
- Past classes in the current week are ignored.
- If there is no remaining class this week, the first occurrence in the next week is returned.
GET /student/timetable/next-class/5A/DBMS
Authorization: Bearer <token>
Response example:
{
"success": true,
"message": "Next class for subject 'DBMS' in yearSection '5A' retrieved successfully",
"yearSection": "5A",
"subject": "DBMS",
"nextClass": {
"day": "TUESDAY",
"slot": 3,
"subject": "DBMS",
"faculty": "RSH",
"room": "LHC-315",
"type": "Theory",
"isNextWeek": false
}
}
- Create a new Postman Environment (e.g., "Timetable Management")
- Add variables:
base_url:http://localhost:3000admin_token: (will be set after login)student_token: (will be set after login)
-
Register Admin:
- Method:
POST - URL:
{{base_url}}/admin/register - Body (raw JSON):
{ "email": "admin@college.edu", "password": "admin123", "name": "Admin User" }
- Method:
-
Login Admin:
- Method:
POST - URL:
{{base_url}}/admin/login - Body (raw JSON):
{ "email": "admin@college.edu", "password": "admin123" } - Note: Cookie is automatically set by the server. No need to manually extract token.
- For Postman: Enable "Send cookies" in request settings (Settings β Send cookies)
- Optional: In Tests tab (if you want to use header-based auth as fallback):
if (pm.response.code === 200) { var jsonData = pm.response.json(); // Cookie is automatically sent, but you can also set header token if needed // pm.environment.set("admin_token", jsonData.token); }
- Method:
-
Register Student:
- Method:
POST - URL:
{{base_url}}/student/register - Body (raw JSON):
{ "usn": "1RI23IS050", "password": "student123", "name": "John Doe" }
- Method:
-
Login Student:
- Method:
POST - URL:
{{base_url}}/student/login - Body (raw JSON):
{ "usn": "1RI23IS050", "password": "student123" } - Note: Cookie is automatically set by the server. No need to manually extract token.
- For Postman: Enable "Send cookies" in request settings (Settings β Send cookies)
- Optional: In Tests tab (if you want to use header-based auth as fallback):
if (pm.response.code === 200) { var jsonData = pm.response.json(); // Cookie is automatically sent, but you can also set header token if needed // pm.environment.set("student_token", jsonData.token); }
- Method:
-
Add Single Slot:
- Method:
POST - URL:
{{base_url}}/admin/timetable/addSingleSlot - Headers:
Authorization:Bearer {{admin_token}}
- Body (raw JSON):
{ "year_section": "5A", "day": "MONDAY", "slot": 1, "subject": "Operating Systems", "faculty": "JDS", "room": "LHC-315", "type": "Theory" }
- Method:
-
Add Batch Slots:
- Method:
POST - URL:
{{base_url}}/admin/timetable/addBatchForDay - Headers:
Authorization:Bearer {{admin_token}}
- Body (raw JSON):
{ "year_section": "5A", "day": "MONDAY", "slots": [ { "slot": 2, "subject": "DBMS", "faculty": "RSH", "room": "LHC-315", "type": "Theory" }, { "slot": 3, "subject": "Computer Networks", "faculty": "ABC", "room": "LHC-320", "type": "Theory" } ] }
- Method:
-
Update Slot:
- Method:
PUT - URL:
{{base_url}}/admin/timetable/updateSlot - Headers:
Authorization:Bearer {{admin_token}}
- Body (raw JSON):
{ "year_section": "5A", "day": "MONDAY", "slot": 2, "subject": "Advanced DBMS", "faculty": "RSH", "room": "LHC-320" }
- Method:
-
Delete Slot:
- Method:
DELETE - URL:
{{base_url}}/admin/timetable/deleteSlot?year_section=5A&day=MONDAY&slot=3 - Note: Cookie is automatically sent. No headers needed if using cookies.
- Optional Headers (if using Bearer token instead):
Authorization:Bearer {{admin_token}}
- Method:
-
Get All Slots for a Faculty (Admin):
- Method:
GET - URL:
{{base_url}}/admin/timetable/faculty/RSH - Headers:
Authorization:Bearer {{admin_token}}
- Method:
-
Get Faculty Daily Teaching Load (Admin):
- Method:
GET - URL:
{{base_url}}/admin/timetable/faculty/daily-load?faculty=RSH&day=MONDAY - Headers:
Authorization:Bearer {{admin_token}}
- Method:
-
Get Weekly Timetable:
- Method:
GET - URL:
{{base_url}}/student/timetable/weekly/5A - Headers:
Authorization:Bearer {{student_token}}
- Method:
-
Get Day Timetable:
- Method:
GET - URL:
{{base_url}}/student/timetable/day/5A/MONDAY - Headers:
Authorization:Bearer {{student_token}}
- Method:
-
Get Next Upcoming Class for a Subject (Student):
- Method:
GET - URL:
{{base_url}}/student/timetable/next-class/5A/DBMS - Headers:
Authorization:Bearer {{student_token}}
- Method:
- Slot 1: 9:00 β 9:55
- Slot 2: 9:55 β 10:50
- Slot 3: 11:05 β 12:00
- Slot 4: 12:00 β 12:55
- Slot 5: 1:45 β 2:40
- Slot 6: 2:40 β 3:35
- Slot 7: 3:35 β 4:30
src/
βββ config/
β βββ dynamoClient.js # DynamoDB client configuration
βββ controllers/
β βββ adminAuthController.js
β βββ studentAuthController.js
β βββ timetableController.js
βββ middleware/
β βββ adminAuth.js # Admin authentication middleware
β βββ studentAuth.js # Student authentication middleware
βββ services/
β βββ userService.js # User authentication logic
β βββ timetableService.js # Timetable CRUD operations
βββ routes/
β βββ adminRoutes.js
β βββ studentRoutes.js
βββ app.js # Express app configuration
βββ server.js # Server entry point
- Password hashing using bcrypt (10 rounds)
- JWT token authentication with expiration (24 hours)
- HTTP-only cookies for secure token storage (prevents XSS attacks)
- SameSite: strict cookie policy (prevents CSRF attacks)
- Secure flag in production (HTTPS only)
- Role-based access control (Admin/Student)
- Input validation on all endpoints
- Duplicate slot prevention
- Fallback support for Bearer token in Authorization header
All endpoints return consistent JSON error responses:
{
"success": false,
"message": "Error message description"
}- All day names must be in uppercase (MONDAY, TUESDAY, etc.)
- Year sections are case-insensitive (will be converted to uppercase)
- Slot numbers must be between 1 and 7
- Type must be either "Theory" or "LAB"
- JWT tokens expire after 24 hours
- Cookie-based authentication: Tokens are stored in HTTP-only cookies (
adminTokenfor admin,studentTokenfor students) - Postman Setup: Enable "Send cookies" in Postman settings (Settings β Send cookies) to use cookie-based auth
- Dual Auth Support: System supports both cookie-based (preferred) and header-based (Bearer token) authentication
-
DynamoDB Connection Issues:
- Verify AWS credentials in
.env - Check AWS region configuration
- Ensure tables are created with correct names
- Verify AWS credentials in
-
Authentication Errors:
- Verify JWT_SECRET is set in
.env - Check token format:
Bearer <token> - Ensure token hasn't expired
- Verify JWT_SECRET is set in
-
Validation Errors:
- Check all required fields are provided
- Verify day names are uppercase
- Ensure slot numbers are 1-7
ISC
Backend System for College Timetable Management using using Node.js, Express.js, and AWS DynamoDB