A production-ready RESTful API built with Node.js, Express, and MongoDB for managing financial records with role-based access control, analytics, and secure authentication.
- Overview
- Features
- API Documentation
- Deployment
- Tech Stack
- Architecture
- Getting Started
- API Reference
- Roles & Permissions
- Data Models
- Testing
- Project Structure
This project implements a secure, multi-role financial records management system. It supports three distinct user roles β Admin, Analyst, and Viewer β each with precisely scoped access to records and analytics. The system features JWT-based authentication delivered via HTTP-only cookies, Zod schema validation, soft-delete record management, and an analytics engine powered by MongoDB aggregation pipelines.
π§ Thought process: For a detailed breakdown of the architectural decisions, potential problems, and rationale behind the tech stack, please refer to the THOUGHT_PROCESS.md file.
- JWT Authentication β Stateless, cookie-based token delivery with configurable expiry
- Role-Based Access Control (RBAC) β Granular route protection via
Admin,Analyst, andViewerroles - Financial Record Management β Full CRUD with soft-delete support and audit tracking (
deletedAt,deletedBy) - Advanced Filtering β Filter records by category, type, date range, and fuzzy text search with pagination
- Analytics Engine β Net balance summaries, category-wise aggregations, and monthly trend breakdowns
- Input Validation β Request body validation using Zod schemas on all write endpoints
- Email Notifications β Nodemailer integration for transactional emails (e.g., new user credentials)
- Security Hardening β Helmet headers, CORS, rate limiting (100 req/hour per IP), bcrypt password hashing
- Global Error Handling β Centralised
AppErrorclass and async wrapper (catchAsync) across all controllers - Testing Suite β Jest + Supertest integration tests backed by
mongodb-memory-server
The API is fully documented using Postman and Swagger. You can access the live documentation and collections via the links below:
- Public Documentation: View on Postman Documenter
- Postman Collection: Import Collection
When the server is running locally, you can access the interactive Swagger UI at:
http://localhost:5000/api-docs
The Swagger UI allows you to directly test the API endpoints with a built-in "Authorize" feature for JWT Bearer tokens.
For immediate testing, you can use these pre-seeded Admin credentials:
- Email:
testadmin@gmail.com - Password:
test@1234 - Role:
Admin
The API is live and can be accessed at the following URL:
π Live Link: https://zorvyn-assignment-fnlh.onrender.com/
Note
The live server might take a few seconds to spin up due to Render's free tier "spinning down" after inactivity.
| Layer | Technology |
|---|---|
| Runtime | Node.js (ESM) |
| Framework | Express 5 |
| Database | MongoDB + Mongoose 9 |
| Authentication | JSON Web Tokens (jsonwebtoken) |
| Validation | Zod |
| Password Hashing | bcryptjs |
| Nodemailer | |
| Security | Helmet, CORS, express-rate-limit |
| Testing | Jest, Supertest, mongodb-memory-server |
| Dev Tools | Nodemon, cross-env |
The system follows a strict, modular Service-Controller architecture. Business logic and analytics pipelines are decoupled from standard request parsing, ensuring that authentication (JWT), strict request validations (Zod), and database querying (MongoDB) operate harmoniously. This separation of concerns creates a highly scalable and easily testable codebase.
- Node.js v18+
- MongoDB instance (local or Atlas)
# Clone the repository
git clone https://github.com/Sammaiah-Guguloth/Zorvyn_Assignment.git
cd Zorvyn_Assignment
# Install dependencies
npm installCopy the example file and populate the values:
cp .env.example .env| Variable | Description |
|---|---|
MONGO_URI |
MongoDB connection string |
NODE_ENV |
development or production |
PORT |
Server port (default: 5000) |
ADMIN_EMAIL |
Initial admin account email |
ADMIN_PASSWORD |
Initial admin account password |
APP_NAME |
Application name for email templates |
EMAIL_HOST |
SMTP host |
EMAIL_PORT |
SMTP port |
EMAIL_USERNAME |
SMTP username |
EMAIL_PASSWORD |
SMTP password |
JWT_SECRET |
Secret key for signing JWTs |
Seed the database with an initial Admin user using the credentials set in .env:
node scripts/seed.js# Development (with hot reload)
npm run dev
# Production
npm startThe server will be available at http://localhost:5000.
All endpoints are prefixed with /api/v1. The API enforces a global rate limit of 100 requests per hour per IP.
| Category | Method | Endpoint | Access | Description |
|---|---|---|---|---|
| Auth | POST |
/auth/login |
Public | Log in with email and password |
POST |
/auth/change-password |
Private | Change the authenticated user's password | |
| Admin | GET |
/admin/users |
Admin | Retrieve all users |
POST |
/admin/users |
Admin | Create a new user (Admin / Analyst / Viewer) | |
PATCH |
/admin/users/:id/status |
Admin | Activate or deactivate a user account | |
DELETE |
/admin/users/:id |
Admin | Delete a user permanently | |
| Records | GET |
/records |
All Roles | List and filter records (Pagination included) |
POST |
/records |
Admin | Create a new financial record | |
PATCH |
/records/:id |
Admin | Update an existing financial record | |
DELETE |
/records/:id |
Admin | Soft-delete a record | |
| Analytics | GET |
/analytics/summary |
Admin, Analyst | Total net balance, income, and expenses |
GET |
/analytics/stats |
Admin | Category-wise sums and monthly trend data |
| Action | Admin | Analyst | Viewer |
|---|---|---|---|
| Login / Change Password | β | β | β |
| Create / Update / Delete Records | β | β | β |
| View Records | β | β | β |
| View Analytics Summary | β | β | β |
| View Analytics Stats | β | β | β |
| Manage Users | β | β | β |
| Field | Type | Description |
|---|---|---|
name |
String | Full name |
email |
String | Unique email address |
password |
String | bcrypt-hashed, hidden from queries |
role |
Enum | admin, analyst, viewer |
status |
Enum | active, inactive |
isPasswordReset |
Boolean | Tracks first-login password change |
| Field | Type | Description |
|---|---|---|
amount |
Number | Positive transaction amount |
type |
Enum | income or expense |
category |
String | e.g., Salary, Food, Rent |
date |
Date | Transaction date |
description |
String | Optional free-text description |
createdBy |
ObjectId | Reference to the creating user |
deletedAt |
Date | Soft-delete timestamp (null if active) |
deletedBy |
ObjectId | Reference to the deleting user |
A compound index on
{ deletedAt, type, date }is applied for optimised query performance on filtered record listings and analytics aggregations.
The test suite uses Jest with Supertest for HTTP assertions and mongodb-memory-server for an isolated, in-memory MongoDB instance. This guarantees that tests can run anywhere with zero external database dependencies.
# Run all automated tests
npm test
# Run tests and generate a complete coverage report
npm test -- --coverageA custom setup script (tests/setup.js) orchestrates the in-memory database, automatically clearing collections between tests to ensure complete isolation. The testing scope includes:
auth.test.jsβ Validates login credentials, secure cookie issuance, JWT verification, and the enforced first-login password change logic.admin.test.jsβ Ensures only Admins can hit provisioning endpoints, verifying user creation, status toggling (active/inactive), and safe deletion algorithms.record.test.jsβ Covers complete REST CRUD patterns, numeric validation for balances, soft-deletion overrides, and complex filtering algorithms.analytics.test.jsβ Verifies MongoDB aggregation pipelines ensuring accurate mathematical calculations for net sums, precise categorisation, and monthly grouping.
Zorvyn_Assignment/
βββ scripts/
β βββ seed.js
βββ src/
β βββ app.js
β βββ config/
β β βββ db.config.js
β β βββ mailer.config.js
β βββ controllers/
β β βββ admin.controller.js
β β βββ analytics.controller.js
β β βββ auth.controller.js
β β βββ record.controller.js
β βββ middlewares/
β β βββ auth.middleware.js
β β βββ error.middleware.js
β β βββ role.middleware.js
β β βββ validate.middleware.js
β βββ models/
β β βββ record.model.js
β β βββ user.model.js
β βββ routes/
β β βββ admin.routes.js
β β βββ analytics.routes.js
β β βββ auth.routes.js
β β βββ record.routes.js
β βββ services/
β β βββ analytics.service.js
β β βββ email.service.js
β βββ utils/
β β βββ appError.util.js
β β βββ catchAsync.util.js
β β βββ constants.util.js
β βββ validations/
β βββ record.validation.js
β βββ user.validation.js
βββ tests/
β βββ admin.test.js
β βββ analytics.test.js
β βββ auth.test.js
β βββ record.test.js
β βββ setup.js
βββ .env.example
βββ .gitignore
βββ jest.config.js
βββ package.json
βββ server.js
Built by Sammaiah Guguloth