This directory contains all the application logic for the Custom Admin Panel Service. This guide will help you navigate the codebase and understand the main components.
- Quick Navigation
- Directory Structure
- Core Components
- Component Details
- Architecture Pattern
- How to Add New Features
| What You Need | Location | Purpose |
|---|---|---|
| Define API routes | routes/ |
Endpoint definitions |
| Handle requests | controllers/ |
Request processing logic |
| Business logic | services/ |
Core service implementations |
| Database models | models/ |
MongoDB schemas |
| Input validation | middlewares/ |
Validation & authorization |
| Settings & constants | configs/ |
Configuration values |
| Utility functions | utils/ |
Helper functions |
| API responses | responses/ |
Response formatting |
| Rate limits | rate-limiters/ |
Request throttling |
| Scheduled tasks | cron-jobs/ |
Automated tasks |
| Microservice comms | internals/ |
Internal service calls |
src/
├── app.js # ⭐ Express app setup
├── bootstrap/ # Initialization scripts
├── configs/ # Configuration files (25+ config files)
├── controllers/ # Request handlers (8 modules)
├── cron-jobs/ # Scheduled tasks
├── internals/ # Microservice communication
├── middlewares/ # Custom middleware functions
├── models/ # MongoDB schemas (10 models)
├── rate-limiters/ # Rate limiting strategies
├── responses/ # Response formatters
├── routes/ # API route definitions
├── services/ # Business logic layer
└── utils/ # Utility & helper functions
// Core Express configuration
// Initializes middleware stack in correct order:
// 1. CORS middleware
// 2. Global rate limiter
// 3. JSON parser
// 4. Cookie parser
// 5. Malformed JSON handler
// 6. Routes
// 7. Unknown route handlerKey Points:
- Middleware order is critical for proper functionality
- CORS must be first
- Routes are mounted here
- Global rate limiter protects all endpoints
Files:
routes/
├── index.js # Main route aggregator
├── admin.routes.js # Admin endpoints
├── user.routes.js # User endpoints
├── organization.routes.js # Organization endpoints
├── organization-users.routes.js # Org-user relationships
├── device.routes.js # Device endpoints
├── activity-tracker.routes.js # Activity tracking
├── client-conversion-request.routes.js # Conversion requests
├── internal.routes.js # Microservice internal routes
└── middleware.gateway.routes.js # Gateway middlewares
Pattern:
router.get('/path', middlewares, controller.method);
router.post('/path', middlewares, controller.method);Responsibility: Process incoming requests and call appropriate services
Modules:
controllers/
├── admins/ # Admin request handlers
├── users/ # User request handlers
├── organizations/ # Organization handlers
├── organization-users/ # Org-user handlers
├── devices/ # Device handlers
├── activity-trackers/ # Activity tracking handlers
├── client-conversion-requests/ # Conversion handlers
└── internals/ # Internal API handlers
Typical Controller Pattern:
exports.createAdmin = async (req, res) => {
try {
const data = req.body;
const result = await adminService.createAdmin(data);
res.status(201).json(result);
} catch (error) {
res.status(error.statusCode).json({ error: error.message });
}
};Responsibility: Core business logic, database operations, external service calls
Modules:
services/
├── admins/ # Admin business logic
├── users/ # User business logic
├── organizations/ # Organization business logic
├── organizational-users/ # Org-user business logic
├── devices/ # Device business logic
├── activity-trackers/ # Activity tracking logic
├── client-conversion-requests/ # Conversion logic
├── common/ # Shared service utilities
├── audit/ # Audit logging
├── internals/ # Internal service calls
└── bootstrap/ # Initialization services
Key Service:
// microservice-init.service.js
// Initializes microservice communication with:
// - Custom Auth Service
// - Other dependent microservices
// - Token rotation schedulerTypical Service Pattern:
exports.createAdmin = async (adminData) => {
// 1. Validate input
// 2. Check for duplicates
// 3. Encrypt sensitive data
// 4. Create in database
// 5. Return result or throw error
};MongoDB Models:
models/
├── admin.model.js # Admin schema
├── user.model.js # User schema
├── organization.model.js # Organization schema
├── organizational-user.model.js # Org-user relationship
├── device.model.js # Device schema
├── activity-tracker.model.js # Activity log schema
├── client-conversion-request.model.js # Conversion schema
├── service-token.model.js # Service token schema
├── service-tracker.model.js # Service tracking
└── index.js # Export all models
Schema Example:
const adminSchema = new Schema({
email: { type: String, unique: true },
name: String,
role: String,
permissions: [String],
createdAt: { type: Date, default: Date.now },
updatedAt: { type: Date, default: Date.now }
});Purpose: Validate, authorize, and preprocess requests
Categories:
middlewares/
├── admins/ # Admin-specific middleware
├── users/ # User-specific middleware
├── organizations/ # Organization-specific middleware
├── devices/ # Device-specific middleware
├── client-conversion-requests/ # Conversion-specific
├── activity-trackers/ # Activity-specific
├── common/ # Shared middleware
├── handlers/ # Error handlers
├── factory/ # Middleware factories
└── internals/ # Microservice validation
Common Middleware:
common/
├── auth-token-validator.middleware.js # Validate JWT
├── role-permission-validator.middleware.js # Check permissions
├── input-validation.middleware.js # Validate input
├── normalize-request.middleware.js # Normalize data
Pattern:
exports.validateAdmin = (req, res, next) => {
if (!req.body.email || !req.body.name) {
return res.status(400).json({ error: 'Missing required fields' });
}
next();
};25+ Configuration Files:
configs/
├── db.config.js # Database connection
├── redis.config.js # Redis setup
├── server.config.js # Server settings
├── headers.config.js # HTTP headers
├── api-role-permission.config.js # Role permissions
├── role-transitions.config.js # Role workflow
├── validation.config.js # Validation rules
├── validation-sets.config.js # Input validation schemas
├── regex.config.js # Regex patterns
├── http-status.config.js # HTTP status codes
├── service-error.config.js # Error messages
├── microservice.config.js # Microservice endpoints
├── internal-uri.config.js # Internal URIs
├── token.config.js # JWT configuration
├── rate-limit.config.js # Rate limit settings
├── security.config.js # Security settings
├── enums.config.js # Enumerations
├── db-collections.config.js # Collection names
├── field-definitions.config.js # Field metadata
├── fields-length.config.js # Field length limits
├── required-fields.config.js # Required field lists
├── tracker.config.js # Tracking configuration
├── system-log-events.config.js # Log events
└── README.md # Config documentation
Usage Pattern:
const { DB_URL } = require("@configs/db.config");
const { ADMIN_PERMISSIONS } = require("@configs/api-role-permission.config");Standardized API Responses:
responses/
├── common/ # Common response handlers
│ ├── error-handler.response.js
│ ├── success-response.js
│ └── validation-error.response.js
├── success/ # Success response templates
└── internals/ # Internal service responses
Pattern:
// Send standardized success response
res.status(200).json({
success: true,
data: result,
message: 'Operation successful'
});
// Send standardized error response
res.status(400).json({
success: false,
error: 'Error message',
code: 'ERROR_CODE'
});Files:
rate-limiters/
├── global.rate-limiter.js # Global rate limiter (100 req/10 min)
├── general-api.rate-limiter.js # General API limit
├── create.rate-limiter.js # Create operation limit
├── device-based.rate-limiter.js # Device creation limit
├── create-redis-device.rate-limiter.js # Redis device limit
└── README.md
Usage:
router.post('/create', createRateLimiter, controller.create);Purpose: Automated background tasks
Implementation:
cron-jobs/
├── index.js # Main cron scheduler
└── README.md
Examples of scheduled tasks:
- Token rotation (via
setupTokenRotationScheduler) - Activity log cleanup
- Cache refresh
- Database maintenance
Purpose: Handle inter-microservice requests
internals/
├── index.js # Internal routes
├── microservice.guard.js # Security guard
├── constants/ # Constants
├── internal-client/ # Client setup
├── redis-session/ # Session management
├── service-token/ # Token handling
└── README.md
Key Feature: microservice.guard.js
- Validates internal service tokens
- Ensures secure microservice-to-microservice communication
Common utilities:
utils/
├── time-stamps.util.js # Timestamp handling (logWithTime)
├── data-validation.util.js # Input validation
├── encryption.util.js # Data encryption
├── token.util.js # Token operations
├── response.util.js # Response helpers
├── array.util.js # Array operations
├── object.util.js # Object operations
└── string.util.js # String operations
The application follows the MVC (Model-View-Controller) + Services pattern:
Request
↓
Routes (Endpoint definition)
↓
Middlewares (Validation & Authorization)
↓
Controllers (Request handler)
↓
Services (Business logic)
↓
Models (Database operations)
↓
Response (Formatted output)
Data Flow Example:
POST /api/admins
→ admin.routes.js (route definition)
→ validateAdmin middleware (check permissions)
→ adminController.createAdmin (handle request)
→ adminService.createAdmin (business logic)
→ Admin.create() (database operation)
→ success response
File: routes/report.routes.js
const express = require('express');
const router = express.Router();
const reportController = require('@controllers/reports');
const { validateReport } = require('@middlewares/reports');
router.get('/', reportController.getAllReports);
router.post('/', validateReport, reportController.createReport);
module.exports = router;File: routes/index.js
const reportRoutes = require('./report.routes');
app.use('/api/reports', reportRoutes);File: controllers/reports/report.controller.js
exports.getAllReports = async (req, res) => {
try {
const reports = await reportService.getAllReports();
res.status(200).json({ data: reports });
} catch (error) {
res.status(500).json({ error: error.message });
}
};File: services/reports/report.service.js
exports.getAllReports = async () => {
return await Report.find();
};File: models/report.model.js
const reportSchema = new Schema({
title: String,
content: String,
createdAt: { type: Date, default: Date.now }
});
module.exports = mongoose.model('Report', reportSchema);File: middlewares/reports/validate-report.middleware.js
exports.validateReport = (req, res, next) => {
if (!req.body.title) {
return res.status(400).json({ error: 'Title is required' });
}
next();
};// Use @alias instead of relative paths
require('@models/admin.model'); // instead of ../../../models/admin.model
require('@services/admin'); // instead of ../../../services/adminthrow {
statusCode: 400,
message: 'Invalid input',
code: 'INVALID_INPUT'
};// Applied at route level
router.post('/create', createRateLimiter, controller.create);// Check JWT token and permissions
app.use(authTokenValidator);
app.use(rolePermissionValidator);| Config File | Purpose |
|---|---|
db.config.js |
MongoDB connection URL |
redis.config.js |
Redis connection settings |
server.config.js |
Server port and environment |
api-role-permission.config.js |
Role and permission mappings |
validation.config.js |
Input validation rules |
http-status.config.js |
HTTP status codes |
service-error.config.js |
Error message templates |
rate-limit.config.js |
Rate limit thresholds |
Routes
↓ (calls)
Controllers
↓ (calls)
Services
↓ (calls)
Models ← (uses) Configs
↓ (validates via)
Middlewares
↓ (formats response via)
Responses
- File Naming: Use kebab-case (e.g.,
admin.controller.js) - Functions: Use camelCase (e.g.,
createAdmin()) - Constants: Use UPPER_SNAKE_CASE
- Classes: Use PascalCase
- Error Handling: Always use try-catch in async functions
- Imports: Group by type (external, internal, configs)
- Understand the routes: Look at
routes/index.js - Find the controller: Check
controllers/for the handler - Find the logic: Check
services/for business logic - Find the schema: Check
models/for data structure - Add validation: Update relevant
middlewares/ - Test with Postman: Use the collection in
/postman
Last Updated: May 2026
Maintainer: Development Team