@mamoorali295/rbac
Version:
Complete RBAC (Role-Based Access Control) system for Node.js with Express middleware, NestJS integration, GraphQL support, MongoDB & PostgreSQL support, modern admin dashboard, TypeScript support, and dynamic permission management
287 lines (286 loc) • 11.1 kB
TypeScript
type ExpressRequest = any;
type ExpressResponse = any;
type ExpressNextFunction = any;
import { RBACConfig, PermissionCheckOptions, RegisterUserOptions, AdminDashboardOptions } from "./types";
/**
* Role-Based Access Control (RBAC) system for Node.js applications.
* Provides middleware functions for authentication, authorization, and user management.
*
* @class RBACSystem
*/
declare class RBACSystem {
private config;
private initialized;
private dbAdapter;
/**
* Initialize the RBAC system with the provided configuration.
* Sets up database connection and creates standard permissions.
*
* @param {RBACConfig} config - Configuration object containing database connection and optional hooks
* @returns {Promise<void>} Promise that resolves when initialization is complete
* @throws {Error} If database connection fails or standard permissions cannot be created
*
* @example
* ```typescript
* // MongoDB configuration
* await RBAC.init({
* database: {
* type: 'mongodb',
* connection: mongoose.connection
* },
* authAdapter: async (req) => ({ user_id: req.user.id }),
* defaultRole: 'user'
* });
*
* // PostgreSQL configuration
* await RBAC.init({
* database: {
* type: 'postgresql',
* connection: pgPool
* },
* authAdapter: async (req) => ({ user_id: req.user.id }),
* defaultRole: 'user'
* });
*
* // Legacy MongoDB configuration (deprecated)
* await RBAC.init({
* db: mongoose.connection,
* authAdapter: async (req) => ({ user_id: req.user.id }),
* defaultRole: 'user'
* });
* ```
*/
init(config: RBACConfig): Promise<void>;
/**
* Ensures that the RBAC system has been initialized before use.
*
* @private
* @throws {Error} If the system has not been initialized
*/
private ensureInitialized;
/**
* Automatically infers the feature and permission from the HTTP request.
* Uses the first path segment as the feature and HTTP method/path patterns for permission.
*
* @private
* @param {ExpressRequest} req - Express request object
* @returns {{feature: string, permission: string}} Inferred feature and permission
*
* @example
* GET /billing/invoices -> { feature: 'billing', permission: 'read' }
* POST /billing/create -> { feature: 'billing', permission: 'create' }
* DELETE /billing/remove -> { feature: 'billing', permission: 'delete' }
*/
private inferFeatureAndPermission;
/**
* Extracts user identity from the request using authAdapter or fallback properties.
*
* @private
* @param {ExpressRequest} req - Express request object
* @returns {Promise<{user_id: string, email?: string}>} User identity object
* @throws {Error} If user identity cannot be determined
*/
private getUserIdentity;
/**
* Express middleware that checks if the current user has the required permissions.
* Can auto-infer permissions from the route or use explicitly provided options.
*
* @param {PermissionCheckOptions} options - Optional feature and permission specification
* @returns {Function} Express middleware function
*
* @example
* // Auto-inferred permissions
* app.get('/billing/invoices', RBAC.checkPermissions(), handler);
*
* // Explicit permissions
* app.post('/admin/reset', RBAC.checkPermissions({
* feature: 'admin',
* permission: 'sudo'
* }), handler);
*/
checkPermissions(options?: PermissionCheckOptions): (req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => Promise<any>;
/**
* Express middleware that registers a new user in the RBAC system.
* Automatically assigns default role if configured and calls registration hooks.
*
* @param {RegisterUserOptions} options - Optional user data extractor function
* @returns {Function} Express middleware function
*
* @example
* // Default extraction from req.body
* app.post('/signup', RBAC.registerUser(), handler);
*
* // Custom user data extraction
* app.post('/signup', RBAC.registerUser({
* userExtractor: (req) => ({
* user_id: req.body.id,
* name: req.body.fullName,
* email: req.body.emailAddress
* })
* }), handler);
*/
registerUser(options?: RegisterUserOptions): (req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => Promise<any>;
/**
* Manually register a user in the RBAC system without using middleware.
* Useful for programmatic user registration outside of HTTP requests.
*
* @param {string} user_id - Unique identifier for the user
* @param {Object} userData - User data object
* @param {string} [userData.name] - User's display name
* @param {string} [userData.email] - User's email address
* @returns {Promise<void>} Promise that resolves when user is registered
* @throws {Error} If user already exists or registration fails
*
* @example
* ```typescript
* await RBAC.registerUserManual('user123', {
* name: 'John Doe',
* email: 'john@example.com'
* });
* ```
*/
registerUserManual(user_id: string, userData: {
name?: string;
email?: string;
}): Promise<void>;
/**
* Update user information in the RBAC system.
*
* @param {string} user_id - Unique identifier for the user
* @param {Object} userData - User data to update
* @param {string} [userData.name] - New display name
* @param {string} [userData.email] - New email address
* @returns {Promise<void>} Promise that resolves when user is updated
* @throws {Error} If user is not found
*
* @example
* ```typescript
* await RBAC.updateUser('user123', {
* name: 'John Smith',
* email: 'johnsmith@example.com'
* });
* ```
*/
updateUser(user_id: string, userData: {
name?: string;
email?: string;
}): Promise<void>;
/**
* Assign a role to a user in the RBAC system.
*
* @param {string} user_id - Unique identifier for the user
* @param {string} roleName - Name of the role to assign
* @returns {Promise<void>} Promise that resolves when role is assigned
* @throws {Error} If user or role is not found
*
* @example
* ```typescript
* await RBAC.assignRole('user123', 'admin');
* ```
*/
assignRole(user_id: string, roleName: string): Promise<void>;
/**
* Get the role name assigned to a user.
*
* @param {string} user_id - Unique identifier for the user
* @returns {Promise<string | null>} Promise that resolves to the role name or null if no role assigned
*
* @example
* ```typescript
* const role = await RBAC.getUserRole('user123');
* console.log(role); // 'admin' or null
* ```
*/
getUserRole(user_id: string): Promise<string | null>;
/**
* Get all permissions a user has for a specific feature.
*
* @param {string} user_id - Unique identifier for the user
* @param {string} featureName - Name of the feature to check permissions for
* @returns {Promise<string[]>} Promise that resolves to an array of permission names
*
* @example
* ```typescript
* const permissions = await RBAC.getFeaturePermissions('user123', 'billing');
* console.log(permissions); // ['read', 'create', 'update']
* ```
*/
getFeaturePermissions(user_id: string, featureName: string): Promise<string[]>;
/**
* Creates an Express router for the RBAC admin dashboard.
* Provides a complete web interface for managing users, roles, features, and permissions.
*
* @param {AdminDashboardOptions} options - Dashboard configuration options
* @param {string} options.user - Admin username for authentication
* @param {string} options.pass - Admin password for authentication
* @param {string} [options.sessionSecret] - Secret key for session encryption
* @param {string} [options.sessionName] - Custom session cookie name
* @returns {express.Router} Express router instance for the admin dashboard
*
* @example
* ```typescript
* app.use('/rbac-admin', RBAC.adminDashboard({
* user: 'admin',
* pass: 'secure-password',
* sessionSecret: 'your-secret-key',
* sessionName: 'rbac.admin.sid'
* }));
* ```
*/
adminDashboard(options: AdminDashboardOptions): any;
/**
* Provides access to internal controllers for advanced database operations.
* These controllers offer direct database access for complex RBAC operations.
*
* @returns {Object} Object containing controller instances
* @returns {Object} controllers.userRole - User role management controller
* @returns {Object} controllers.feature - Feature management controller
*
* @example
* ```typescript
* const { userRole, feature } = RBAC.controllers;
* const allRoles = await userRole.getAllRoles();
* const allFeatures = await feature.getAllFeatures();
* ```
*/
get controllers(): {
userRole: {
getAllRoles: () => Promise<any>;
createRole: (name: string, description: string, features: import("./mongo/models/UserRole").IFeaturePermission[]) => Promise<any>;
deleteRole: (roleId: string) => Promise<any>;
addFeatureToUserRole: (roleId: string, featureIds: string[]) => Promise<any>;
removeFeatureFromUserRole: (roleId: string, featureIds: string[]) => Promise<any>;
addPermissionToFeatureInUserRole: (roleId: string, featureIds: string[], permissionIds: string[]) => Promise<any>;
removePermissionToFeatureInUserRole: (roleId: string, featureIds: string[], permissionIds: string[]) => Promise<any>;
getPermissions: () => Promise<any>;
};
feature: {
getAllFeatures: () => Promise<any>;
createFeature: (name: string, description: string) => Promise<any>;
updateFeature: (featureId: string, name: string, description: string) => Promise<any>;
deleteFeature: (featureId: string) => Promise<any>;
};
};
}
/**
* Singleton instance of the RBACSystem class.
* This is the main export that applications should use for all RBAC operations.
*
* @example
* ```typescript
* import { RBAC } from '@sheikh295/rbac';
*
* // Initialize the system
* await RBAC.init({
* db: mongoose.connection,
* authAdapter: async (req) => ({ user_id: req.user.id }),
* defaultRole: 'user'
* });
*
* // Use middleware
* app.get('/protected', RBAC.checkPermissions(), handler);
* app.use('/admin', RBAC.adminDashboard({ user: 'admin', pass: 'secret' }));
* ```
*/
export declare const RBAC: RBACSystem;
export {};