This project is a Node.js-based REST API designed for a multi-tenant system with role-based access control (RBAC). It leverages Express.js for routing, Prisma for database interactions with PostgreSQL, and JWT for secure authentication. The system supports a single Super Admin with full permissions and allows for the creation of roles and permissions for other users, making it suitable for multi-tenant applications.
- Features
- Technologies Used
- Prerequisites
- Installation
- Environment Variables
- Project Structure
- API Endpoints
- Database Schema
- Seeding the Database
- Middleware
- Running the Application
- Graceful Shutdown
- Contributing
- License
- Multi-Tenant Support: Designed to handle multiple tenants with a single Super Admin overseeing the system.
- Role-Based Access Control (RBAC): Assign roles and permissions to users for fine-grained access control.
- JWT Authentication: Secure user authentication using JSON Web Tokens stored in cookies.
- Prisma ORM: Simplified database operations with PostgreSQL.
- Database Seeding: Automatically creates a Super Admin role, permissions, and user on startup.
- CORS Support: Configured to allow requests from a specified frontend URL.
- Error Handling: Custom middleware for consistent error responses.
- Request Logging: Uses Morgan for logging HTTP requests.
- Graceful Shutdown: Ensures proper disconnection of Prisma and server closure on termination.
- Node.js: JavaScript runtime for server-side development.
- Express.js: Web framework for building RESTful APIs.
- Prisma: ORM for PostgreSQL database interactions.
- PostgreSQL: Relational database for storing user, role, and permission data.
- JWT (jsonwebtoken): For secure authentication.
- Bcrypt: For password hashing.
- Morgan: For HTTP request logging.
- CORS: For enabling cross-origin requests.
- Body-Parser: For parsing JSON and URL-encoded request bodies.
- Cookie-Parser: For handling cookies in requests.
- Dotenv: For managing environment variables.
- Node.js: Version 14 or higher.
- PostgreSQL: A running PostgreSQL instance (local or cloud-hosted).
- NPM: For installing dependencies.
- A
.env
file with the required environment variables (see Environment Variables).
-
Clone the Repository:
git clone <repository-url> cd <repository-folder>
-
Install Dependencies:
npm install
-
Set Up PostgreSQL:
- Ensure a PostgreSQL database is running.
- Update the
DATABASE_URL
in the.env
file to point to your database.
-
Run Prisma Migrations:
npx prisma migrate dev --name init
This creates the necessary tables based on the Prisma schema.
-
Start the Server:
npm start
The server will start on the port specified in the
.env
file (default: 8008).
Create a .env
file in the root directory with the following variables:
NODE_ENV="development
DATABASE_URL="postgresql://<user>:<password>@<host>:<port>/<database>?schema=public"
JWT_SECRET=<your_jwt_secret>
FRONTEND_URL=<your_frontend_url>
NODE_ENV
: development || production.DATABASE_URL
: Connection string for your PostgreSQL database.JWT_SECRET
: Secret key for signing JWTs.FRONTEND_URL
: The URL of the frontend application for CORS configuration.
├── middlewares/
│ ├── authenticationMiddleware.js # JWT-based authentication
│ ├── authorizationMiddleware.js # Permission-based authorization
│ ├── errorMiddleware.js # Custom error handling
├── routes/
│ ├── authRoutes.js # Authentication and role/permission routes
├── utils/
│ ├── seedDatabase.js # Database seeding logic
├── controllers/
│ ├── authController.js # Route handlers for auth, roles, permissions
├── prisma/
│ ├── schema.prisma # Prisma schema for database models
├── .env # Environment variables
├── index.js # Main application entry point
├── package.json # Project metadata and dependencies
└── README.md # Project documentation
Method | Endpoint | Description | Middleware |
---|---|---|---|
POST | /api/auth/register/admin |
Register a new admin user | protect , authorize("*") |
POST | /api/auth/register/user |
Register a new regular user | protect , authorize("*") |
POST | /api/auth/login |
User login with JWT token generation | None |
POST | /api/auth/change-password |
Change user password | protect |
GET | /api/auth/login-status |
Check if user is logged in | None |
POST | /api/auth/logout |
Log out user (clear JWT cookie) | None |
GET | /api/auth/user-details |
Get details of the logged-in user | protect |
Method | Endpoint | Description | Middleware |
---|---|---|---|
POST | /api/auth/roles |
Create a new role | protect , authorize("MANAGE_ROLES") |
PUT | /api/auth/roles/:id |
Update an existing role | protect , authorize("MANAGE_ROLES") |
DELETE | /api/auth/roles/:id |
Delete a role | protect , authorize("MANAGE_ROLES") |
Method | Endpoint | Description | Middleware |
---|---|---|---|
POST | /api/auth/permissions |
Create a new permission | protect , authorize("MANAGE_PERMISSIONS") |
PUT | /api/auth/permissions/:id |
Update an existing permission | protect , authorize("MANAGE_PERMISSIONS") |
DELETE | /api/auth/permissions/:id |
Delete a permission | protect , authorize("MANAGE_PERMISSIONS") |
The Prisma schema (prisma/schema.prisma
) defines three main models:
id
: Auto-incremented unique identifier.name
: User's name.email
: Unique email address.phoneno
: Unique phone number.password
: Hashed password (using bcrypt).role
: Relation to a single Role (one-to-many).createdAt
/updatedAt
: Timestamps for record creation and updates.
id
: Auto-incremented unique identifier.name
: Unique role name (e.g., "SUPER_ADMIN").permissions
: Many-to-many relation with Permissions.users
: One-to-many relation with Users.createdAt
/updatedAt
: Timestamps.
id
: Auto-incremented unique identifier.name
: Unique permission name (e.g., "*").description
: Optional description of the permission.roles
: Many-to-many relation with Roles.createdAt
/updatedAt
: Timestamps.
The seedDatabase.js
utility ensures the following on server startup:
- Creates a
SUPER_ADMIN
role if it doesn't exist. - Creates a
*
permission (granting all access) if it doesn't exist. - Links the
*
permission to theSUPER_ADMIN
role. - Creates a default
SYS ADMIN
user with the emailadmin@sys.com
, a hashed password, and theSUPER_ADMIN
role.
To customize the seed data, modify the seedDatabase.js
file.
- Verifies the JWT token stored in the
token
cookie. - Fetches the user from the database (excluding the password) and attaches it to
req.user
. - Throws a 401 error if the token is missing, invalid, or the user is not found.
- Checks if the logged-in user has the required permissions.
- Allows users with the
*
permission to bypass all checks. - Throws a 403 error if the user lacks the necessary permissions.
- Catches errors thrown by route handlers or other middleware.
- Returns standardized JSON error responses.
- Ensure PostgreSQL is running and the
DATABASE_URL
is correctly configured. - Install dependencies and run migrations as described in Installation.
- Start the server:
npm start
- The server will:
- Connect to PostgreSQL via Prisma.
- Seed the database with the Super Admin role and user.
- Listen on the specified port (default: 8008).
The application handles graceful shutdown by:
- Listening for the
SIGINT
signal (e.g., Ctrl+C). - Disconnecting the Prisma client to close the database connection pool.
- Closing the Express server to ensure no new requests are accepted.
Contributions are welcome! Please follow these steps:
- Fork the repository.
- Create a new branch (
git checkout -b feature/your-feature
). - Make your changes and commit (
git commit -m "Add your feature"
). - Push to the branch (
git push origin feature/your-feature
). - Open a pull request.
This project is licensed under the MIT License.