A comprehensive REST API for e-commerce backend built with NestJS, MongoDB, and JWT authentication.
- 🔐 JWT Authentication - Secure user authentication with JWT tokens
- 👻 Guest User Support - Temporary tokens for browsing without registration
- 🔄 Refresh Tokens - Long-lived tokens for seamless re-authentication
- 🛡️ RBAC System - Role-Based Access Control with multi-store support
- 🏢 Multi-Tenant Architecture - Organization → Store → User hierarchy
- 👥 User Management - Complete user CRUD operations with role-based access
- Customer Type - Regular customers with shopping capabilities
- Staff Type - Store/organization employees with role-based permissions
- 📦 Product Management - Full product catalog with category organization
- 🛒 Order Management - Order creation with stock management
- 🏷️ Category Management - Product categorization system
- 🎭 Role & Permission Management - Flexible role and permission assignment
- 🏪 Store Context - Multi-store operations via x-store-id header
- 📝 Swagger Documentation - Interactive API documentation at
/api - ✅ Validation - Request validation using class-validator
- 🔒 Security - JWT guards and secure password hashing with bcryptjs
- 🗄️ MongoDB - NoSQL database with Mongoose ODM
- 🧪 Testing - Comprehensive unit tests with Jest
- NestJS - Progressive Node.js framework
- MongoDB - NoSQL database
- Mongoose - ODM for MongoDB
- JWT - JSON Web Token authentication
- Passport - Authentication middleware
- Swagger - API documentation
- class-validator - DTO validation
- bcryptjs - Password hashing
- Node.js (v14 or higher)
- MongoDB (v4.4 or higher)
- npm or yarn
- Clone the repository:
git clone https://github.com/timothy-pham/nestjs-api.git
cd nestjs-api- Install dependencies:
npm install- Create a
.envfile in the root directory:
cp .env.example .env- Configure your environment variables in
.env:
MONGODB_URI=mongodb://localhost:27017/ecommerce
JWT_SECRET=your-secret-key-change-in-production
JWT_EXPIRES_IN=1d
PORT=3000
NODE_ENV=development- Seed the RBAC system with default roles and permissions:
npm run seed:rbacThis will create:
- Default roles:
super_admin,organization_admin,store_owner,store_manager,staff,customer - Permissions for all resources across different scopes (system, organization, store)
- Role-permission associations
- (Optional) Seed sample users and test data:
npm run seed:usersThis will create:
- Sample organization (ACME Corporation)
- Sample stores (Downtown Store, Mall Store)
- Sample users with different roles (admin, manager, owner, staff, customers)
- See console output for login credentials
npm run start:devnpm run build
npm run start:prodThe API will be available at http://localhost:3000
Once the application is running, visit:
- Swagger UI:
http://localhost:3000/api - RBAC Guide: See RBAC_GUIDE.md for detailed RBAC documentation
POST /auth/register- Register a new customer account (automatically assigns customer role)POST /auth/login- Login user (returns JWT access token and refresh token)POST /auth/refresh- Refresh access token using refresh tokenPOST /auth/guest- Generate guest token for browsing without registration
POST /organizations- Create organization (super_admin only)GET /organizations- List all organizationsGET /organizations/:id- Get organization detailsPATCH /organizations/:id- Update organization (super_admin, organization_admin)DELETE /organizations/:id- Delete organization (super_admin only)
POST /stores- Create store (super_admin, organization_admin)GET /stores- List all storesGET /stores/:id- Get store detailsPATCH /stores/:id- Update store (super_admin, organization_admin, store_owner)DELETE /stores/:id- Delete store (super_admin, organization_admin)
POST /roles- Create role (super_admin, organization_admin)GET /roles- List all rolesGET /roles/:id- Get role detailsPATCH /roles/:id- Update role (super_admin, organization_admin)POST /roles/:id/permissions/add- Add permissions to rolePOST /roles/:id/permissions/remove- Remove permissions from roleDELETE /roles/:id- Delete role (super_admin only, cannot delete system roles)
POST /permissions- Create permission (super_admin only)GET /permissions- List all permissionsGET /permissions/:id- Get permission detailsPATCH /permissions/:id- Update permission (super_admin only)DELETE /permissions/:id- Delete permission (super_admin only)
POST /user-roles/assign- Assign role to userPOST /user-roles/revoke- Revoke role from userGET /user-roles/user/:userId- Get user's rolesGET /user-roles/user/:userId/permissions- Get user's permissionsGET /user-roles/me/permissions- Get current user's permissionsGET /user-roles/:id- Get user role detailsPATCH /user-roles/:id- Update user role
POST /users- Create a new user (requires super_admin or organization_admin role)GET /users- Get all users (requires admin or manager role)GET /users/me- Get current user profile (requires authentication)GET /users/:id- Get user by ID (requires admin or manager role)PATCH /users/me- Update current user profile (requires authentication)PATCH /users/:id- Update user (requires super_admin, organization_admin, or store_owner role)DELETE /users/:id- Delete user (requires super_admin or organization_admin role)
POST /categories- Create category (requires authentication)GET /categories- Get all categoriesGET /categories/:id- Get category by IDPATCH /categories/:id- Update category (requires authentication)DELETE /categories/:id- Delete category (requires authentication)
POST /products- Create product (requires authentication)GET /products- Get all productsGET /products?category=:categoryId- Get products by categoryGET /products/:id- Get product by IDPATCH /products/:id- Update product (requires authentication)DELETE /products/:id- Delete product (requires authentication)
POST /orders- Create order (requires orders:create permission)GET /orders- Get orders (role-based: super_admin, organization_admin, store_owner, store_manager, staff)- Use
x-store-idheader for store context
- Use
GET /orders/:id- Get order by ID (requires orders:read permission)PATCH /orders/:id/status- Update order status (requires store_manager or above)DELETE /orders/:id- Delete order (requires store_owner or above)
This API implements a comprehensive Role-Based Access Control system with support for guest users, customers, and staff members across multiple stores.
- Temporary access without registration
- Can browse products and add to cart (session-based)
- Short-lived token (1 hour expiration)
- No database record required
- Registered users with customer accounts
- Can create orders, view order history, update profile
- Automatically assigned "customer" role on registration
- Long-lived sessions with refresh tokens
- Store or organization employees
- Assigned specific roles (owner, manager, staff)
- Can be associated with specific stores or organizations
- Role-based permissions for management operations
- super_admin: Full system access across all organizations and stores
- organization_admin: Manages organization and all its stores
- store_owner: Full management of a specific store
- store_manager: Manages products and orders in a store
- staff: Basic order and product access in a store
- customer: Browse products, create orders, manage own profile
- System: Global permissions across entire platform
- Organization: Permissions within a specific organization
- Store: Permissions within a specific store
Include the x-store-id header in requests to set the store context:
curl -X GET http://localhost:3000/orders \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "x-store-id: STORE_ID"For detailed RBAC documentation, see RBAC_GUIDE.md
src/
├── auth/ # Authentication module
│ ├── dto/ # Data transfer objects
│ ├── guards/ # JWT auth guard
│ ├── strategies/ # Passport strategies
│ ├── auth.controller.ts
│ ├── auth.service.ts
│ └── auth.module.ts
├── organizations/ # Organization management (RBAC)
│ ├── dto/
│ ├── organization.schema.ts
│ ├── organizations.controller.ts
│ ├── organizations.service.ts
│ └── organizations.module.ts
├── stores/ # Store management (RBAC)
│ ├── dto/
│ ├── store.schema.ts
│ ├── stores.controller.ts
│ ├── stores.service.ts
│ └── stores.module.ts
├── roles/ # Role management (RBAC)
│ ├── dto/
│ ├── role.schema.ts
│ ├── roles.controller.ts
│ ├── roles.service.ts
│ └── roles.module.ts
├── permissions/ # Permission management (RBAC)
│ ├── dto/
│ ├── permission.schema.ts
│ ├── permissions.controller.ts
│ ├── permissions.service.ts
│ └── permissions.module.ts
├── user-roles/ # User-Role assignment (RBAC)
│ ├── dto/
│ ├── user-role.schema.ts
│ ├── user-roles.controller.ts
│ ├── user-roles.service.ts
│ └── user-roles.module.ts
├── users/ # User management module
│ ├── dto/
│ ├── user.schema.ts
│ ├── users.controller.ts
│ ├── users.service.ts
│ └── users.module.ts
├── categories/ # Category management module
│ ├── dto/
│ ├── category.schema.ts
│ ├── categories.controller.ts
│ ├── categories.service.ts
│ └── categories.module.ts
├── products/ # Product management module
│ ├── dto/
│ ├── product.schema.ts
│ ├── products.controller.ts
│ ├── products.service.ts
│ └── products.module.ts
├── orders/ # Order management module
│ ├── dto/
│ ├── order.schema.ts
│ ├── orders.controller.ts
│ ├── orders.service.ts
│ └── orders.module.ts
├── common/ # Shared resources
│ ├── decorators/ # Custom decorators
│ │ ├── current-role.decorator.ts # @CurrentRole() - Get user's roles
│ │ ├── current-store.decorator.ts # @CurrentStore() - Get store context
│ │ ├── get-user.decorator.ts # @GetUser() - Get authenticated user
│ │ ├── get-store-id.decorator.ts # @GetStoreId() - Get store ID from header
│ │ ├── permissions.decorator.ts # @Permissions() - Check permissions
│ │ └── roles.decorator.ts # @Roles() - Check roles
│ ├── guards/ # Custom guards
│ │ ├── roles.guard.ts # RolesGuard - Role-based access
│ │ └── permissions.guard.ts # PermissionsGuard - Permission-based access
│ ├── middleware/ # Middleware
│ │ └── store-context.middleware.ts # Extract x-store-id header
│ └── common.module.ts # Common module (global)
├── app.module.ts # Root module
└── main.ts # Application entry point
Validates JWT token and attaches user info to request.
@UseGuards(JwtAuthGuard)
@Get('profile')
async getProfile(@GetUser() user: any) {
return user;
}Allows both authenticated and guest access. Attaches user info if token provided.
@UseGuards(OptionalAuthGuard)
@Get('products')
async getProducts(@GetUser() user?: any) {
// Works with or without authentication
}Checks if user has required roles. Works with @Roles() decorator.
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('super_admin', 'organization_admin')
@Post('sensitive-data')
async createSensitiveData() {
// Only super_admin or organization_admin can access
}Checks if user has required permissions. Works with @Permissions() decorator.
@UseGuards(JwtAuthGuard, PermissionsGuard)
@Permissions('orders:create', 'orders:update')
@Post('orders')
async createOrder() {
// User must have orders:create or orders:update permission
}Extracts authenticated user from request.
@Get('me')
async getCurrentUser(@GetUser() user: any) {
// user = { userId, email, userType, roles, isGuest }
}Extracts user's roles from JWT payload.
@Get('dashboard')
async getDashboard(@CurrentRole() roles: string[]) {
// roles = ['store_manager', 'staff']
}Extracts store ID from x-store-id header.
@Get('orders')
async getOrders(@CurrentStore() storeId?: string) {
// storeId from x-store-id header
}Specifies required roles for endpoint access.
@Roles('store_owner', 'store_manager')
@Get('reports')
async getReports() {
// Requires store_owner or store_manager role
}Specifies required permissions for endpoint access.
@Permissions('products:create', 'products:update')
@Post('products')
async createProduct() {
// Requires products:create or products:update permission
}# Unit tests
npm run test
# E2E tests
npm run test:e2e
# Test coverage
npm run test:covnpm run build- Change
JWT_SECRETin production to a strong, random string - Use environment variables for sensitive data
- Enable HTTPS in production
- Implement rate limiting for API endpoints
- Keep dependencies up to date
- Use MongoDB authentication in production
ISC
Timothy Pham