Scalable REST API with JWT Authentication & Role-Based Access Control
Built with Node.js Β· Express Β· PostgreSQL Β· Docker
| Category | Details |
|---|---|
| Auth | Register, login, JWT tokens, bcrypt password hashing |
| RBAC | user and admin roles with route-level enforcement |
| Tasks CRUD | Create, read, update, delete with filters & pagination |
| Admin | User management, role promotion, platform stats |
| Security | Helmet, CORS, rate limiting, input validation (Joi) |
| Docs | Swagger UI at /api-docs + Postman collection |
| API Versioning | /api/v1/... prefix for forward compatibility |
| Deployment | Docker Compose with PostgreSQL + Redis included |
- Node.js 20+
- PostgreSQL 14+
- (Optional) Docker & Docker Compose
git clone https://github.com/YOUR_USERNAME/taskflow-api.git
cd taskflow-api/backend
npm installcp .env.example .env
# Edit .env and set your DB credentials and JWT_SECRET# Create the database first
psql -U postgres -c "CREATE DATABASE taskflow_db;"
# Run schema + seed
npm run db:initnpm run dev # development (nodemon)
npm start # productionServer runs on http://localhost:5000
# From project root
docker-compose up --build
# Scale API horizontally
docker-compose up --scale api=4Services:
- Frontend: http://localhost:3000
- API: http://localhost:5000
- Swagger: http://localhost:5000/api-docs
- PostgreSQL: localhost:5432
- Redis: localhost:6379
http://localhost:5000/api/v1
All protected endpoints require:
Authorization: Bearer <token>
| Method | Endpoint | Auth | Description |
|---|---|---|---|
POST |
/auth/register |
β | Register new user |
POST |
/auth/login |
β | Login β get JWT |
GET |
/auth/me |
β | Get own profile |
PATCH |
/auth/me |
β | Update name / password |
Register
curl -X POST http://localhost:5000/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"Jane","email":"jane@example.com","password":"SecurePass1"}'Login
curl -X POST http://localhost:5000/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@taskflow.dev","password":"Admin@1234"}'| Method | Endpoint | Auth | Role | Description |
|---|---|---|---|---|
GET |
/tasks |
β | any | List tasks (with filters) |
GET |
/tasks/:id |
β | any | Get single task |
POST |
/tasks |
β | any | Create task |
PATCH |
/tasks/:id |
β | owner/admin | Update task |
DELETE |
/tasks/:id |
β | owner/admin | Delete task |
Query Parameters (GET /tasks):
| Param | Values | Default |
|---|---|---|
status |
todo, in_progress, done |
β |
priority |
low, medium, high |
β |
page |
integer | 1 |
limit |
1β50 | 10 |
sort |
created_at, updated_at, priority, title |
created_at |
order |
asc, desc |
desc |
| Method | Endpoint | Description |
|---|---|---|
GET |
/admin/stats |
Platform statistics |
GET |
/admin/users |
List all users |
PATCH |
/admin/users/:id/role |
Change user role |
DELETE |
/admin/users/:id |
Delete user account |
users
id UUID PRIMARY KEY
name VARCHAR(50)
email VARCHAR(255) UNIQUE
password_hash TEXT
role VARCHAR(10) DEFAULT 'user' -- 'user' | 'admin'
created_at TIMESTAMPTZ
updated_at TIMESTAMPTZ
tasks
id UUID PRIMARY KEY
title VARCHAR(120)
description TEXT
status VARCHAR(20) DEFAULT 'todo' -- 'todo' | 'in_progress' | 'done'
priority VARCHAR(10) DEFAULT 'medium' -- 'low' | 'medium' | 'high'
user_id UUID REFERENCES users(id) ON DELETE CASCADE
created_at TIMESTAMPTZ
updated_at TIMESTAMPTZtaskflow-api/
βββ backend/
β βββ src/
β β βββ config/
β β β βββ db.js # PostgreSQL connection pool
β β β βββ swagger.js # OpenAPI spec config
β β βββ controllers/
β β β βββ auth.controller.js
β β β βββ tasks.controller.js
β β β βββ admin.controller.js
β β βββ middleware/
β β β βββ auth.js # JWT verify + role check
β β β βββ validate.js # Joi validation factory
β β β βββ errorHandler.js # Global error handler
β β βββ routes/
β β β βββ index.js # Version router
β β β βββ v1/
β β β βββ auth.routes.js
β β β βββ tasks.routes.js
β β β βββ admin.routes.js
β β βββ validators/
β β β βββ auth.validator.js
β β β βββ task.validator.js
β β βββ schema/
β β βββ init.sql # DB schema + seed
β β βββ initDb.js # Runner script
β βββ server.js
β βββ Dockerfile
β βββ package.json
βββ frontend/
β βββ index.html # Single-page UI
βββ docs/
β βββ TaskFlow.postman_collection.json
βββ docker-compose.yml
βββ SCALABILITY.md
βββ README.md
Swagger UI: http://localhost:5000/api-docs
Postman: Import docs/TaskFlow.postman_collection.json
- Run Login first β token is auto-saved to collection variable
- All authenticated requests use
{{token}}automatically
- Password hashing: bcrypt with cost factor 12
- JWT: Signed with
HS256, expiry enforced, user existence re-checked on every request - Input validation: Joi schemas strip unknown fields, enforce types and lengths
- Rate limiting: 100 req/15 min globally, 20 req/15 min on auth routes
- HTTP headers:
helmetsets HSTS, X-Frame-Options, CSP, etc. - CORS: Explicit allowlist, no wildcard in production
- Generic auth errors: "Invalid email or password" prevents email enumeration
- SQL injection: Parameterised queries throughout (no string interpolation)
| Password | Role | |
|---|---|---|
| admin@taskflow.dev | Admin@1234 | admin |
β οΈ Change the default password immediately in any non-demo environment.
- Redis caching for task lists
- Email verification on registration
- Refresh token rotation
- File attachments on tasks (S3)
- WebSocket notifications (Socket.IO)
- Unit & integration tests (Jest + Supertest)
- CI/CD pipeline (GitHub Actions)