A Node.js REST API for financial dashboard management with role-based access control (RBAC). Built with Express.js, Prisma ORM, and Supabase PostgreSQL. Features JWT authentication, schema validation, rate limiting, and comprehensive API documentation via Swagger UI.
- JWT Authentication: Secure token-based authentication with password hashing (bcryptjs).
- Role-Based Access Control (RBAC): Three user roles with granular permissions:
- VIEWER: Access dashboard overview.
- ANALYST: View financial records and dashboard insights.
- ADMIN: Full CRUD on records, user management.
- Schema Validation: Input validation using Zod for users and transactions.
- Rate Limiting: Global rate limit of 10 requests per minute per IP to prevent abuse.
- Database: Prisma ORM with Supabase PostgreSQL for data persistence.
- API Documentation: Interactive Swagger UI at
/api-docsfor testing and exploring endpoints. - Middleware: Authentication, role authorization, CORS, and error handling.
- Backend: Node.js, Express.js
- Database: Supabase (PostgreSQL) via Prisma ORM
- Authentication: JWT (jsonwebtoken)
- Password Hashing: bcryptjs
- Validation: Zod
- Rate Limiting: express-rate-limit
- CORS: Enabled
- Documentation: Swagger UI (swagger-ui-express)
The application follows a layered REST API architecture where client requests pass through security and validation middleware before reaching the relevant route handlers and business logic.
flowchart LR
Client[Client / Frontend / Postman] -->|HTTP Request| API[Express REST API]
API --> Middleware[Global Middleware\nCORS + JSON Parsing + Rate Limiter]
Middleware --> Routes[Route Modules\nAuth / Records / Users / Dashboard]
Routes --> Controllers[Controllers\nBusiness Logic]
Controllers --> Auth[JWT Authentication + Role Authorization]
Controllers --> Prisma[Prisma Client]
Prisma --> DB[(Supabase PostgreSQL)]
Auth -->|Validate token| Controllers
Controllers -->|JSON Response| Client
- Clients send HTTP requests to the Express API.
- Global middleware enforces CORS, parses JSON payloads, and applies rate limiting.
- Route modules dispatch requests to domain-specific controllers.
- Auth middleware verifies JWT tokens and checks user status and permissions.
- Controllers interact with Prisma ORM to read and write financial data in PostgreSQL.
- Responses are returned to the client in a consistent JSON structure.
The application is organized into modular domain components, each containing its own route and controller logic. This separation keeps authentication, record management, user administration, and dashboard queries independent while sharing the same Prisma data layer.
flowchart TD
subgraph group_server["API server"]
node_server["Express server<br/>[index.js]"]
node_docs["Swagger UI<br/>[swagger.js]"]
end
subgraph group_access["Access control"]
node_limiter["Rate limiter"]
node_auth_middleware["Token authentication<br/>[authMiddleware.js]"]
node_role_middleware["Role authorization<br/>[roleMiddleware.js]"]
end
subgraph group_domains["Finance domains"]
node_auth_routes["Auth routes<br/>[authRoute.js]"]
node_auth_controller["Authentication<br/>[authController.js]"]
node_record_routes["Record routes<br/>[recordRoutes.js]"]
node_record_controller["Record management"]
node_dashboard_routes["Dashboard routes<br/>[dashboardRoutes.js]"]
node_dashboard_controller["Dashboard reporting"]
node_user_routes["User routes<br/>[userRoutes.js]"]
node_user_controller["User management<br/>[userController.js]"]
end
subgraph group_persistence["Persistence and validation"]
node_auth_validation["Auth validation<br/>[userAuthSchema.js]"]
node_record_validation["Transaction validation"]
node_user_validation["User update validation"]
node_prisma["Prisma client<br/>[prismaClient.js]"]
node_database[("PostgreSQL database")]
end
node_client(("API client"))
node_client -->|"sends requests"| node_server
node_server -->|"applies limits"| node_limiter
node_server -->|"mounts routes"| node_auth_routes
node_server -->|"mounts routes"| node_record_routes
node_server -->|"mounts routes"| node_user_routes
node_server -->|"mounts routes"| node_dashboard_routes
node_server -->|"serves docs"| node_docs
node_auth_routes -->|"routes to"| node_auth_controller
node_auth_controller -->|"validates input"| node_auth_validation
node_auth_controller -->|"reads and writes users"| node_prisma
node_record_routes -->|"authenticates"| node_auth_middleware
node_record_routes -->|"checks roles"| node_role_middleware
node_record_routes -->|"routes to"| node_record_controller
node_record_controller -->|"validates input"| node_record_validation
node_record_controller -->|"reads and writes records"| node_prisma
node_dashboard_routes -->|"authenticates"| node_auth_middleware
node_dashboard_routes -->|"checks roles"| node_role_middleware
node_dashboard_routes -->|"routes to"| node_dashboard_controller
node_dashboard_controller -->|"queries records"| node_prisma
node_user_routes -->|"authenticates"| node_auth_middleware
node_user_routes -->|"checks roles"| node_role_middleware
node_user_routes -->|"routes to"| node_user_controller
node_user_controller -->|"validates updates"| node_user_validation
node_user_controller -->|"reads and updates users"| node_prisma
node_auth_middleware -->|"looks up user"| node_prisma
node_auth_middleware -.->|"sets request identity"| node_role_middleware
node_prisma -.->|"persists data"| node_database
click node_server "https://github.com/arjung352/fintrack_api/blob/main/src/index.js"
click node_docs "https://github.com/arjung352/fintrack_api/blob/main/src/swagger.js"
click node_limiter "https://github.com/arjung352/fintrack_api/blob/main/src/middleware/rateLimitMiddleware.js"
click node_auth_routes "https://github.com/arjung352/fintrack_api/blob/main/src/modules/auth/authRoute.js"
click node_auth_controller "https://github.com/arjung352/fintrack_api/blob/main/src/modules/auth/authController.js"
click node_auth_validation "https://github.com/arjung352/fintrack_api/blob/main/src/schemaValidation/userAuthSchema.js"
click node_auth_middleware "https://github.com/arjung352/fintrack_api/blob/main/src/middleware/authMiddleware.js"
click node_role_middleware "https://github.com/arjung352/fintrack_api/blob/main/src/middleware/roleMiddleware.js"
click node_record_routes "https://github.com/arjung352/fintrack_api/blob/main/src/modules/record/recordRoutes.js"
click node_record_controller "https://github.com/arjung352/fintrack_api/blob/main/src/modules/record/recordController.js"
click node_record_validation "https://github.com/arjung352/fintrack_api/blob/main/src/schemaValidation/transactionSchema.js"
click node_dashboard_routes "https://github.com/arjung352/fintrack_api/blob/main/src/modules/dashboard/dashboardRoutes.js"
click node_dashboard_controller "https://github.com/arjung352/fintrack_api/blob/main/src/modules/dashboard/dashboardController.js"
click node_user_routes "https://github.com/arjung352/fintrack_api/blob/main/src/modules/user/userRoutes.js"
click node_user_controller "https://github.com/arjung352/fintrack_api/blob/main/src/modules/user/userController.js"
click node_user_validation "https://github.com/arjung352/fintrack_api/blob/main/src/schemaValidation/userUpdationValidation.js"
click node_prisma "https://github.com/arjung352/fintrack_api/blob/main/src/prisma/prismaClient.js"
classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_server,node_docs,node_client toneBlue
class node_limiter,node_auth_middleware,node_role_middleware toneAmber
class node_auth_routes,node_auth_controller,node_record_routes,node_record_controller,node_dashboard_routes,node_dashboard_controller,node_user_routes,node_user_controller toneMint
class node_auth_validation,node_record_validation,node_user_validation,node_prisma,node_database toneRose
- Express Server: Bootstraps the app, registers middleware, mounts route modules, and starts the HTTP server.
- Auth Module: Handles registration and login, issues JWT tokens, and validates user identity.
- Record Module: Manages income/expense record CRUD operations and filters.
- User Module: Exposes user administration features such as role and status updates.
- Dashboard Module: Aggregates financial summaries and dashboard statistics.
- Middleware Layer: Enforces rate limiting, authentication, and role-based access control.
- Validation Layer: Validates user inputs and transaction payloads before database operations.
- Prisma + PostgreSQL: Provides persistence, relational queries, and schema management for the application data.
- Node.js (v14 or higher)
- npm or yarn
- Supabase account and project
git clone <repository-url>
cd FinTrack_API
npm installCreate a .env file in the root directory by copying the provided .env.example:
cp .env.example .envThen update the values in .env to match your local setup.
Example .env structure:
DATABASE_URL=""
DIRECT_URL=""
JWT_SECRET="Secret_Key_For_JWT"
PORT=3000If you are not using a
dbhost alias, replacedbwith the hostname or IP address of your PostgreSQL server.
This project includes a docker-compose.yml that builds the API container and loads environment variables from .env.
- Build and start the container:
docker compose up --build- Visit the API at:
http://localhost:3000
- For API docs, open:
http://localhost:3000/api-docs
- To stop the container, press
Ctrl+Cin the terminal or run:
docker compose down- Create a Supabase project at supabase.com, or use a local PostgreSQL instance.
- Run Prisma migrations to set up the database schema:
npm run prisma:migrate
npm run prisma:generate- (Optional) Seed the database:
npm run prisma:seedIf you want to run the app outside Docker, use one of the commands below:
# Development mode (with nodemon)
npm run dev
# Production mode
npm startThe server runs on http://localhost:3000.
All endpoints return JSON responses with success (boolean) and message (string) fields. Protected routes require a Bearer token in the Authorization header.
-
POST /api/auth/register
- Body:
{ "name": "string", "email": "string", "password": "string" } - Response: User creation confirmation.
- Public endpoint.
- Body:
-
POST /api/auth/login
- Body:
{ "email": "string", "password": "string" } - Response: JWT token and user info.
- Public endpoint.
- Body:
-
GET /api/records (ANALYST, ADMIN)
- Query params:
type(INCOME/EXPENSE),category,from(date),to(date) - Response: List of records (filtered).
- Query params:
-
POST /api/records (ADMIN)
- Body:
{ "amount": number, "description": "string", "category": "string" } - Response: Record creation confirmation.
- Body:
-
PATCH /api/records/:id (ADMIN)
- Body: Partial update fields (amount, description, category).
- Response: Update confirmation.
-
DELETE /api/records/:id (ADMIN)
- Response: Soft delete confirmation.
-
GET /api/users
- Response: List of all users.
-
PATCH /api/users/:id/role
- Body:
{ "role": "VIEWER" | "ANALYST" | "ADMIN" } - Response: Role update confirmation.
- Body:
-
PATCH /api/users/:id/status
- Body:
{ "status": "ACTIVE" | "INACTIVE" } - Response: Status update confirmation.
- Body:
-
GET /api/dashboard/overview (VIEWER, ANALYST, ADMIN)
- Query:
trendType("monthly" | "weekly") - Response: Global financial overview with trends.
- Query:
-
GET /api/dashboard/summary (ANALYST, ADMIN)
- Response: User-specific financial summary.
- GET /
- Response: Basic server status.
- Public endpoint.
| Endpoint | VIEWER | ANALYST | ADMIN |
|---|---|---|---|
| /api/auth/* | ✅ | ✅ | ✅ |
| /api/records (GET) | ❌ | ✅ | ✅ |
| /api/records (POST/PATCH/DELETE) | ❌ | ❌ | ✅ |
| /api/users/* | ❌ | ❌ | ✅ |
| /api/dashboard/overview | ✅ | ✅ | ✅ |
| /api/dashboard/summary | ❌ | ✅ | ✅ |
- Authentication: JWT tokens expire in 1 day. Inactive users are blocked.
- Authorization: Role-based middleware enforces permissions.
- Validation: Zod schemas validate all inputs (users: name, email, password; transactions: amount, type, category, etc.).
- Rate Limiting: 10 requests/minute/IP to mitigate abuse.
- CORS: Enabled for cross-origin requests.
- Error Handling: Centralized error middleware with consistent JSON responses.
Access interactive API docs at http://localhost:3000/api-docs. Includes endpoint details, request/response schemas, and a built-in tester.
- Create an account using
POST /api/auth/register. - Login using
POST /api/auth/loginand copy the returned JWT token. - Open the Swagger UI and click the
Authorizebutton. - Paste the token in the authorization field as
Bearer <token>. - Click
Authorizeand thenClose. - You can now call protected endpoints directly from Swagger.
id(UUID, PK)name(string)email(string, unique)passwordHash(string)role(enum: VIEWER, ANALYST, ADMIN)status(enum: ACTIVE, INACTIVE)createdAt(timestamp)
id(UUID, PK)userId(UUID, FK to users)amount(decimal)description(text)category(string)createdAt(timestamp)
npm start: Start production server.npm run dev: Start development server with auto-reload.npm run prisma:generate: Generate Prisma client.npm run prisma:migrate: Run database migrations.npm run prisma:studio: Open Prisma Studio for DB management.
└── arjung352-fintrack_api/
├── README.md
├── package.json
└── src/
├── index.js
├── swagger.js
├── middleware/
│ ├── authMiddleware.js
│ ├── rateLimitMiddleware.js
│ └── roleMiddleware.js
├── modules/
│ ├── auth/
│ │ ├── authController.js
│ │ └── authRoute.js
│ ├── dashboard/
│ │ ├── dashboardController.js
│ │ └── dashboardRoutes.js
│ ├── record/
│ │ ├── recordController.js
│ │ └── recordRoutes.js
│ └── user/
│ ├── userController.js
│ └── userRoutes.js
├── prisma/
│ ├── prismaClient.js
│ ├── schema.prisma
│ ├── seed.js
│ └── migrations/
│ ├── migration_lock.toml
│ └── 20260405073824_init/
│ └── migration.sql
└── schemaValidation/
├── transactionSchema.js
├── userAuthSchema.js
└── userUpdationValidation.js
- README.md: This file, containing project documentation and setup instructions.
- package.json: Node.js project configuration with dependencies and scripts.
- src/index.js: Main entry point of the application, sets up the Express server.
- src/swagger.js: Configuration for Swagger UI API documentation.
- src/middleware/authMiddleware.js: Middleware for JWT authentication verification.
- src/middleware/rateLimitMiddleware.js: Middleware for implementing rate limiting.
- src/middleware/roleMiddleware.js: Middleware for role-based access control.
- src/modules/auth/authController.js: Controller handling authentication logic (register, login).
- src/modules/auth/authRoute.js: Routes for authentication endpoints.
- src/modules/dashboard/dashboardController.js: Controller for dashboard-related logic.
- src/modules/dashboard/dashboardRoutes.js: Routes for dashboard endpoints.
- src/modules/record/recordController.js: Controller for financial record operations.
- src/modules/record/recordRoutes.js: Routes for record management endpoints.
- src/modules/user/userController.js: Controller for user management operations.
- src/modules/user/userRoutes.js: Routes for user-related endpoints.
- src/prisma/prismaClient.js: Prisma client instance for database interactions.
- src/prisma/schema.prisma: Prisma schema defining the database models.
- src/prisma/seed.js: Script to seed the database with initial data.
- src/prisma/migrations/migration_lock.toml: Prisma migration lock file.
- src/prisma/migrations/20260405073824_init/migration.sql: Initial database migration SQL.
- src/schemaValidation/transactionSchema.js: Zod schema for transaction validation.
- src/schemaValidation/userAuthSchema.js: Zod schema for user validation.
- src/schemaValidation/userUpdationValidation.js: Additional user validation logic.
- Fork the repo.
- Create a feature branch.
- Commit changes.
- Push and open a PR.
ISC