A production-ready REST API with JWT Authentication, Role-Based Access Control, and a React frontend β built for the PrimeTrade Backend Developer Intern assignment.
- Features
- Tech Stack
- Project Structure
- Quick Start
- API Documentation
- Environment Variables
- Database Schema
- Security Practices
- Scalability Notes
- Docker Deployment
- π JWT Authentication β Access + Refresh token pair
- π₯ Role-Based Access Control β
userandadminroles - β Full CRUD β Tasks with filters, search, pagination, sorting
- π‘οΈ Security β bcrypt hashing, helmet, rate limiting, NoSQL injection prevention, input sanitization
- π Swagger Docs β Auto-generated interactive API docs at
/api-docs - π Admin Dashboard β Manage users, view system stats
- π Account Locking β Auto-lock after 5 failed login attempts
- π Logging β Winston logger with file + console output
- β‘ API Versioning β
/api/v1/...
- βοΈ React 18 + Vite β Fast modern frontend
- π¨ Tailwind CSS β Dark theme, responsive design
- π Auto token refresh β Axios interceptor silently refreshes expired tokens
- π Dashboard β Task stats, priority breakdown, recent tasks
- π Task Manager β Full CRUD with modal forms, filters, search, pagination
- π‘οΈ Admin Panel β User management, role toggle, activate/deactivate
- β Client-side validation β Real-time form feedback
| Layer | Technology |
|---|---|
| Runtime | Node.js 20 |
| Framework | Express 4 |
| Database | MongoDB + Mongoose |
| Auth | JWT (jsonwebtoken) + bcryptjs |
| Validation | express-validator |
| Security | helmet, express-rate-limit, mongo-sanitize |
| Logging | Winston |
| API Docs | Swagger (swagger-jsdoc + swagger-ui-express) |
| Frontend | React 18 + Vite + Tailwind CSS |
| HTTP Client | Axios (with interceptors) |
| Deployment | Docker + Docker Compose |
taskflow-api/
βββ backend/
β βββ src/
β β βββ app.js # Express entry point
β β βββ seed.js # Demo data seeder
β β βββ config/
β β β βββ database.js # MongoDB connection
β β β βββ swagger.js # Swagger spec config
β β βββ controllers/
β β β βββ auth.controller.js # Register, login, refresh, logout
β β β βββ task.controller.js # CRUD + stats for tasks
β β β βββ admin.controller.js # User management, dashboard
β β βββ middleware/
β β β βββ auth.js # JWT protect + restrictTo
β β β βββ errorHandler.js # Global error handler
β β β βββ validate.js # express-validator runner
β β βββ models/
β β β βββ User.js # User schema + methods
β β β βββ Task.js # Task schema + hooks
β β βββ routes/v1/
β β β βββ auth.routes.js # /api/v1/auth/*
β β β βββ task.routes.js # /api/v1/tasks/*
β β β βββ user.routes.js # /api/v1/users/*
β β β βββ admin.routes.js # /api/v1/admin/*
β β βββ utils/
β β β βββ jwt.js # Token generation/verification
β β β βββ logger.js # Winston logger
β β β βββ apiResponse.js # Standardized response helpers
β β βββ validators/
β β βββ auth.validator.js # Auth input rules
β β βββ task.validator.js # Task input rules
β βββ logs/ # Log files (gitignored)
β βββ Dockerfile
β βββ package.json
β βββ .env.example
β
βββ frontend/
β βββ src/
β β βββ App.jsx # Router + protected routes
β β βββ main.jsx
β β βββ index.css # Tailwind + custom classes
β β βββ context/
β β β βββ AuthContext.jsx # Global auth state
β β βββ services/
β β β βββ api.js # Axios instance + all API calls
β β βββ components/
β β β βββ Layout.jsx # Sidebar navigation
β β βββ pages/
β β βββ LoginPage.jsx
β β βββ RegisterPage.jsx
β β βββ DashboardPage.jsx
β β βββ TasksPage.jsx # Full CRUD UI
β β βββ AdminPage.jsx # Admin user management
β βββ Dockerfile
β βββ nginx.conf
β βββ package.json
β
βββ docker-compose.yml
βββ README.md
- Node.js v18+
- MongoDB (local or MongoDB Atlas)
- npm or yarn
git clone https://github.com/YOUR_USERNAME/taskflow-api.git
cd taskflow-apicd backend
# Install dependencies
npm install
# Configure environment
cp .env.example .env
# Edit .env and set your MONGODB_URI and JWT secrets
# Seed demo data (optional)
node src/seed.js
# Start development server
npm run devBackend runs at: http://localhost:5000
API Docs at: http://localhost:5000/api-docs
cd ../frontend
# Install dependencies
npm install
# Start development server
npm run devFrontend runs at: http://localhost:3000
| Role | Password | |
|---|---|---|
| Admin | admin@demo.com | Admin@1234 |
| User | user@demo.com | Demo@1234 |
| User | jane@demo.com | Demo@1234 |
Interactive Swagger docs are available at: http://localhost:5000/api-docs
| Method | Endpoint | Access | Description |
|---|---|---|---|
| POST | /api/v1/auth/register |
Public | Register new user |
| POST | /api/v1/auth/login |
Public | Login & get tokens |
| POST | /api/v1/auth/refresh |
Public | Refresh access token |
| POST | /api/v1/auth/logout |
Private | Invalidate refresh token |
| GET | /api/v1/auth/me |
Private | Get current user |
| PUT | /api/v1/auth/change-password |
Private | Change password |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/v1/tasks |
Private | Get tasks (filter/page) |
| POST | /api/v1/tasks |
Private | Create task |
| GET | /api/v1/tasks/stats |
Private | Task statistics |
| GET | /api/v1/tasks/:id |
Private | Get single task |
| PUT | /api/v1/tasks/:id |
Private | Update task |
| DELETE | /api/v1/tasks/:id |
Private | Delete task |
| Method | Endpoint | Access | Description |
|---|---|---|---|
| GET | /api/v1/admin/dashboard |
Admin | System stats |
| GET | /api/v1/admin/users |
Admin | All users (paginated) |
| GET | /api/v1/admin/users/:id |
Admin | User by ID |
| PATCH | /api/v1/admin/users/:id/role |
Admin | Change user role |
| PATCH | /api/v1/admin/users/:id/toggle-status |
Admin | Activate/deactivate |
| DELETE | /api/v1/admin/users/:id |
Admin | Delete user + tasks |
| GET | /api/v1/admin/tasks |
Admin | All tasks in system |
| Param | Type | Values | Description |
|---|---|---|---|
| page | number | 1+ | Page number |
| limit | number | 1β50 | Items per page |
| status | string | todo, in-progress, completed | Filter status |
| priority | string | low, medium, high | Filter priority |
| sortBy | string | createdAt, dueDate, priority, title | Sort field |
| order | string | asc, desc | Sort direction |
| search | string | any | Search title/description |
All responses follow this standard shape:
{
"success": true,
"message": "Human readable message",
"data": { ... },
"meta": {
"total": 42,
"page": 1,
"limit": 10,
"totalPages": 5,
"hasNextPage": true,
"hasPrevPage": false
}
}Error responses:
{
"success": false,
"message": "Validation failed",
"errors": [
{ "field": "email", "message": "Valid email is required" }
]
}# Server
PORT=5000
NODE_ENV=development
# MongoDB
MONGODB_URI=mongodb://localhost:27017/taskflow
# JWT (use long random strings in production)
JWT_SECRET=your_jwt_secret_min_32_characters
JWT_EXPIRES_IN=7d
JWT_REFRESH_SECRET=your_refresh_secret_min_32_characters
JWT_REFRESH_EXPIRES_IN=30d
# Rate Limiting
RATE_LIMIT_WINDOW_MS=900000 # 15 minutes
RATE_LIMIT_MAX=100 # max requests per window
# CORS
FRONTEND_URL=http://localhost:3000{
name: String, // 2β50 chars
email: String, // unique, indexed
password: String, // bcrypt hashed, hidden from output
role: String, // 'user' | 'admin'
isActive: Boolean, // default: true
refreshToken: String, // stored for refresh validation
lastLogin: Date,
loginAttempts: Number, // for brute-force protection
lockUntil: Date, // account lock expiry
createdAt: Date,
updatedAt: Date
}Indexes: { email: 1 }, { role: 1 }
{
title: String, // 3β100 chars, required
description: String, // max 1000 chars
status: String, // 'todo' | 'in-progress' | 'completed'
priority: String, // 'low' | 'medium' | 'high'
dueDate: Date, // must be future date
tags: [String], // max 10 tags
owner: ObjectId, // ref: User
completedAt: Date, // auto-set when status β completed
createdAt: Date,
updatedAt: Date
}Indexes: { owner: 1, status: 1 }, { owner: 1, priority: 1 }, { owner: 1, createdAt: -1 }
| Practice | Implementation |
|---|---|
| Password hashing | bcrypt with salt rounds = 12 |
| JWT security | Short-lived access tokens (7d) + long-lived refresh (30d) |
| Refresh token storage | Server-side validation + rotation on each refresh |
| Account locking | Auto-lock after 5 failed login attempts (2 hours) |
| Rate limiting | 100 req/15min global, 10 req/15min on auth routes |
| Input sanitization | express-mongo-sanitize prevents NoSQL injection |
| Input validation | express-validator on all request bodies |
| HTTP security headers | helmet sets X-XSS-Protection, HSTS, CSP, etc. |
| CORS | Restricted to configured frontend origin |
| Payload limit | JSON body limited to 10kb |
| Password never returned | .select('-password') on all user queries |
| Principle of least privilege | Role checks on every protected route |
The app is structured for easy horizontal scaling. Each layer (API, DB) is independent and stateless (JWT is stateless by design).
1. Horizontal Scaling (Load Balancing)
ββββββββββββββββββββ
Users βββββββΆ β Load Balancer β (Nginx / AWS ALB)
ββββββββββ¬ββββββββββ
ββββββββββββββΌβββββββββββββ
βββββββΌββββ βββββββΌββββ βββββββΌββββ
β API Pod β β API Pod β β API Pod β (Docker / K8s)
βββββββββββ βββββββββββ βββββββββββ
β
ββββββββββΌβββββββββ
β MongoDB Atlas β (Replica Set)
βββββββββββββββββββ
2. Caching (Redis)
- Cache task list responses per user (TTL: 60s)
- Cache user profile lookups (TTL: 5min)
- Store refresh token allowlist in Redis for fast revocation
3. Microservices Migration Path The modular structure makes service extraction easy:
auth-serviceβ handles login, token managementtask-serviceβ handles CRUD operationsnotification-serviceβ email/push for due datesadmin-serviceβ analytics and management
4. Database Optimisation
- All queries use compound indexes (owner + status, owner + priority)
- Pagination prevents large data fetches
- MongoDB Atlas supports auto-scaling and global clusters
5. API Gateway Add an API Gateway (Kong / AWS API Gateway) in front for:
- Centralised rate limiting
- SSL termination
- Request routing to microservices
6. CI/CD Pipeline
Push to main β GitHub Actions β Run tests β Build Docker images β Deploy to K8s# Build and start all services
docker-compose up --build
# Run in background
docker-compose up -d
# Seed demo data inside container
docker-compose exec backend node src/seed.js
# View logs
docker-compose logs -f backend
# Stop
docker-compose downServices:
- Frontend:
http://localhost:3000 - Backend API:
http://localhost:5000 - API Docs:
http://localhost:5000/api-docs - MongoDB:
mongodb://localhost:27017
cd backend
npm testbackend/logs/
βββ combined.log # All log levels
βββ error.log # Error level only
Built for the PrimeTrade Backend Developer Intern assignment.
MIT