This is the backend system for the Shift Manager application, built with Node.js, Express, and MongoDB. It supports:
- User registration and login with JWT authentication
- Protected routes for shift management
- Password reset via email with secure token flow
- Auto-generated API docs using Swagger (OpenAPI 3.0)
orta-full-stack-dev-test-be/
├── src/ # Source code directory
│ ├── controllers/ # Route handlers
│ │ ├── authentication.controller.js # User auth (login, register, password reset)
│ │ ├── location.controller.js # Location management
│ │ ├── shifts.controller.js # Shift management (CRUD, clock in/out)
│ │ └── worker.controller.js # Worker-specific operations
│ ├── middlewares/ # Express middleware
│ │ ├── error-handler.middleware.js # Global error handling
│ │ ├── require-admin.middleware.js # Admin authorization
│ │ └── require-auth.middleware.js # JWT authentication
│ ├── migrations/ # Database migration scripts
│ ├── models/ # Mongoose schemas
│ │ ├── location.model.js # Location schema
│ │ ├── shifts.model.js # Shift schema
│ │ └── user.model.js # User schema
│ ├── routes/ # API route definitions
│ │ ├── authentication.router.js # Auth routes (/auth/*)
│ │ ├── location.router.js # Location routes (/locations/*)
│ │ ├── shifts.router.js # Shift routes (/shifts/*)
│ │ └── worker.router.js # Worker routes (/workers/*)
│ ├── services/ # Business logic layer
│ │ ├── authentication/
│ │ │ └── index.js # Auth service functions
│ │ ├── location/
│ │ ├── shift/
│ │ │ ├── constants.js # Shift status/type constants
│ │ │ └── index.js # Shift service functions
│ │ └── worker/
│ ├── swagger/ # API documentation
│ │ └── swaggerConfig.js # Swagger/OpenAPI configuration
│ ├── utils/ # Utility functions
│ │ ├── errors/ # Custom error classes
│ │ │ ├── app.error.js # Generic app errors
│ │ │ ├── auth.error.js # Authentication errors
│ │ │ ├── utils.js # Error utilities
│ │ │ └── validation.error.js # Validation errors
│ │ ├── datetime.js # Date/time utilities
│ │ └── email.js # Email utilities
│ ├── db.js # Database connection setup
│ └── server.js # Application entry point
├── test/ # Test files
├── coverage/ # Test coverage reports
├── .env # Environment variables (not committed)
├── .gitignore # Git ignore rules
├── .prettierrc # Prettier config
├── eslint.config.js # ESLint configuration
├── jsconfig.json # JavaScript config
├── package.json # Dependencies & scripts
└── README.md # Project documentation
Before you begin, ensure you have the following installed on your system:
- Node.js (v20 or higher) - Download here
- Git - Download here
- npm (comes with Node.js) or yarn
- MongoDB - Choose one option:
- MongoDB Atlas (cloud database - recommended)
- MongoDB Community Server (local installation)
node --version # Should be v20+
npm --version # Should be 8+
git --version # Any recent versiongit clone https://github.com/dearzubi/orta-full-stack-dev-test-be
cd orta-full-stack-dev-test-benpm installOption A: MongoDB Atlas (Cloud)
- Create a free account at MongoDB Atlas
- Create a new cluster
- Get your connection string from the "Connect" button
- Replace
<username>,<password>, and<cluster-url>with your details
Option B: Local MongoDB
- Install MongoDB Community Server
- Start MongoDB service:
- Windows: MongoDB should start automatically
- macOS:
brew services start mongodb/brew/mongodb-community - Linux:
sudo systemctl start mongod
- Your local connection string will be:
mongodb://localhost:27017/shift-manager
Create a .env file in the root directory with the following variables:
# Database
MONGO_URI=mongodb+srv://<username>:<password>@<cluster-url>/shift-manager?retryWrites=true&w=majority
# Server
PORT=8000
NODE_ENV=development
# Authentication
JWT_SECRET=your-super-secure-jwt-secret-here-min-32-chars
# Email Setup - Required for Forgot Password functionality Only
SUPPORT_EMAIL=from-emai@gmail.com
GMAIL_USERNAME=your-email@gmail.com
GMAIL_PASSWORD=your-app-password
FRONTEND_URL=your-frontend-url-hereSecurity Note: Replace
JWT_SECRETwith a strong, random string (at least 32 characters)
npm run devSuccess! Your server should now be running at: http://localhost:8000
Swagger UI is available at:
http://localhost:8000/api/docs
- Local:
http://localhost:8000/api
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/user/register |
Register a new user | No |
POST |
/user/login |
Login user & get JWT token | No |
GET |
/user/getuser |
Get current user profile | No |
POST |
/user/promote-to-admin |
Promote user to admin role | Admin |
POST /api/user/register
{
"name": "John Doe",
"email": "john@example.com",
"password": "StrongPass123!"
}POST /api/user/login
{
"email": "john@example.com",
"password": "StrongPass123!"
}| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
POST |
/user/forgotPassword |
Send password reset email | No |
POST |
/user/resetPassword |
Reset password with token | No |
POST /api/user/forgotPassword
{
"email": "john@example.com"
}POST /api/user/resetPassword
{
"id": "64a7b2f5e1d3c2a1b4c5d6e7",
"resetToken": "d4c68f30aa0b5c2d...",
"newPassword": "NewStrongPassword123!"
}| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/shifts |
Get all shifts (with pagination) | Admin |
GET |
/shifts/my-shifts |
Get current user's shifts | User |
GET |
/shifts/:id |
Get specific shift details | User |
POST |
/shifts |
Create a new shift | Admin |
POST |
/shifts/batch |
Batch create/update shifts | Admin |
PUT |
/shifts/:id |
Update existing shift | Admin |
DELETE |
/shifts/:id |
Delete shift | Admin |
PATCH |
/shifts/:id/cancel |
Cancel shift | Admin |
PATCH |
/shifts/:id/clock-in |
Clock in to shift | User |
PATCH |
/shifts/:id/clock-out |
Clock out of shift | User |
page- Page number (default: 1)limit- Items per page (default: 10, max: 1000)status- Filter by status:active,cancelled,completed,in_progresssortBy- Sort field (default: "date")sortOrder- Sort order:ascordesc(default: "asc")
POST /api/shifts
{
"title": "Morning Cleaning Shift",
"role": "Cleaner",
"typeOfShift": ["morning", "weekday"],
"user": "64a7b2f5e1d3c2a1b4c5d6e7",
"startTime": "09:00",
"finishTime": "17:00",
"numOfShiftsPerDay": 1,
"location": {
"name": "Office Building A",
"address": "123 Main Street",
"postCode": "12345",
"cordinates": {
"longitude": -74.006,
"latitude": 40.7128
}
},
"date": "2024-12-25T00:00:00Z"
}| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/workers/all |
Get all workers | Admin |
| Method | Endpoint | Description | Auth Required |
|---|---|---|---|
GET |
/locations/all |
Get all locations | Admin |
- Public - No authentication required
- User - Requires valid JWT token
- Admin - Requires JWT token + admin role
All API responses follow this consistent format:
{
"success": true,
"data": {
/* response data */
},
"message": "Operation successful"
}{
"success": false,
"error": "Error message description",
"code": "ERROR_CODE"
}For protected endpoints, include the JWT token in the Authorization header:
Authorization: Bearer <your-jwt-token>| Script | Command | Description |
|---|---|---|
npm start |
node src/server.js |
Start production server |
npm run dev |
nodemon src/server.js |
Start development server with auto-reload |
npm test |
mocha test/**/*.test.js |
Run all tests |
npm run coverage |
c8 mocha test/... |
Run tests with coverage report |
npm run format |
prettier --write ... |
Format code with Prettier |
npm testnpm run coverageThis will generate coverage reports in multiple formats:
- Terminal output - Quick coverage summary
- HTML report - Detailed coverage at
coverage/index.html - LCOV report - For CI/CD integration
# On macOS (if you have the script)
npm run coverage:openThe project uses c8 for code coverage with the following thresholds:
{
"lines": 70,
"functions": 70,
"branches": 60,
"statements": 70
}Coverage includes:
src/**/*.js - All source files
test/
├── auth.test.js # Authentication & user tests
└── shift.test.js # Shift management tests
- Test Framework: Mocha - Feature-rich testing framework
- Assertions: Chai - BDD/TDD assertion library
- HTTP Testing: Supertest - HTTP assertions
- Test Database: MongoDB Memory Server - In-memory MongoDB
- Mocking: Sinon - Standalone test spies, stubs and mocks
- Coverage: c8 - Native V8 code coverage
npm run devThis starts the server with nodemon for automatic restart on file changes.
# Run tests whenever files change
npm test -- --watchnpm run formatnpm run coverage
open coverage/index.html # View detailed coverage- Start the server:
npm run dev - Visit: http://localhost:8000/api/docs
- Use the interactive API explorer
Register a user:
curl -X POST http://localhost:8000/api/user/register \
-H "Content-Type: application/json" \
-d '{"name":"Test User","email":"test@example.com","password":"Test123!"}'Login:
curl -X POST http://localhost:8000/api/user/login \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com","password":"Test123!"}'Get user shifts (requires JWT):
curl -X GET http://localhost:8000/api/shifts/my-shifts \
-H "Authorization: Bearer YOUR_JWT_TOKEN"- Enable debug logs - Set
NODE_ENV=developmentin your.env - Check database connection - Verify
MONGO_URIis correct - Validate JWT tokens - Use jwt.io to decode tokens
- Monitor server logs - Check console output for error details
- Use Postman/Insomnia - For advanced API testing