UNPKG

rab-access

Version:

Role based access control

227 lines (180 loc) 6.89 kB
# **Rab Access Control Middleware** A robust, flexible, and declarative access control library for Node.js applications. With `rab-access`, you can define and enforce fine-grained access policies using schemas, roles, and custom validations. It’s ideal for multi-role systems requiring granular control over resource access. --- ## **Features** - **Declarative Schema-Based Access Control**: Define access policies for resources and operations. - **Role-Based Permissions**: Grant permissions based on roles and extend roles with additional access rights. - **Dynamic Filters and Validators**: Use dynamic data (e.g., user attributes, query parameters) to filter or validate access. - **Middleware Generation**: Seamlessly integrate with your Node.js apps via middleware. --- ## **Installation** Install the package using npm: ```bash npm install rab-access ``` --- ## **Getting Started** ### **1. Import Required Modules** ```javascript const { Rab } = require("rab-access"); ``` ### **2. Define Roles** Define the roles within your system: ```javascript const roles = { SYSTEM_ADMIN: "System Admin", ADMIN: "Admin", SUPERVISOR: "Supivisor", }; ``` ### **3. Define Access Control Schema** Create a schema that specifies access rules for various operations: ```javascript const userAccessControl = Rab.schema({ canReadUser: [ Rab.alwaysGrant().ifEqual(Rab.user("user_id"), Rab.params("user_id")), Rab.grant(roles.SYSTEM_ADMIN).columns(["id"]), Rab.grant(roles.ADMIN).filters({ "organization_id": Rab.user( "organization_id") }) .columns(["id"]), Rab.grant(roles.SUPERVISOR) .extend(roles.ADMIN, "canReadUser") .columns(["id", "name"]), ], canReadAllUsers: [Rab.grant(roles.SYSTEM_ADMIN).columns(["id"])], canDeleteUser: [ Rab.alwaysGrant().ifEqual(Rab.user("user_id"), Rab.params("user_id")), Rab.grant(roles.SYSTEM_ADMIN), Rab.grant(roles.SUPERVISOR).validator("customValidationFunction"), ], }); ``` ### **4. Define Custom Validations** Add custom validation logic for specific scenarios: ```javascript const customValidations = { customValidationFunction: async (request) => { // Perform your custom validation return Promise.resolve(); }, }; ``` ### **5. Generate Middleware** Create middleware to enforce your access policies: ```javascript const createMiddleware = (accessControl, validations) => (permission) => async (req, res, next) => { const { isAuthorized, fields, filters, lookupFilters } = await accessControl.can({ validations, request: req, role: req.role, permission, }); if (isAuthorized) { req.fields = fields; req.filters = filters; req.lookupFilters = lookupFilters; return next(); } res.status(403).json({ error: "FORBIDDEN" }); }; const accessMiddleware = createMiddleware(userAccessControl, customValidations); ``` ### **6. Export and Use** Export the middleware and roles for use in your application: ```javascript module.exports = { accessMiddleware, roles, }; ``` --- ## **Usage Example** Integrate the middleware into your application to secure routes: ```javascript const express = require("express"); const { accessMiddleware, roles } = require("./accessControl"); const app = express(); // Example route using middleware app.get("/users/:userId", accessMiddleware("canReadUser"), (req, res) => { res.send("Access granted to a user data!"); }); app.get("/users", accessMiddleware("canReadAllUsers"), (req, res) => { res.send("Access granted to a users!"); }); app.listen(3000, () => console.log("Server running on port 3000")); ``` ## **API Reference** ### **Core Classes** #### **`Rab`** The main class for managing access control. Use it to define schemas, manage roles, and evaluate permissions. ##### **Methods** - **`Rab.schema(config: Record<string, Permission[]>)`** Defines the access control schema with a configuration object mapping actions to role-based permissions. - **Parameters**: - `config`: An object where keys are permission names and values are arrays of `Permission` instances. - **Example**: ```javascript Rab.schema({ canReadUsers: [ Rab.grant("Admin").columns(["id", "name"]), ], }); ``` - **`Rab.grant(role: string): Permission`** Creates a new `Permission` instance for a specific role. - **`Rab.user(path: string[] | string): string[]`** Retrieves the user's data path for dynamic access control rules. - **`Rab.params(path: string[] | string): string[]`** Retrieves the request parameters path for dynamic access control. - **`Rab.query(path: string[] | string): string[]`** Retrieves the query parameters path for dynamic access control. - **`Rab.can(options: Omit<EvaluatePermissionParams, "permissions"> & { permission: string }): Promise<Authorization>`** Checks if a user is authorized to perform a specific action. - **Parameters**: - `options`: Includes the role, request, and permission name. - **Returns**: A promise resolving to an `Authorization` object. - **Example**: ```javascript const {isAuthorized} = await Rab.can({ role: "Admin", request: req, permission: "canReadUsers", }); ``` --- #### **`Permission`** Defines the rules and constraints for a specific role's access. ##### **Methods** - **`columns(columns: string[]): this`** Specifies the columns that the role can access. - **`lookupFilters(filters: Record<string, any>): this`** Adds lookup filters to the permission. - **`filters(filters: Record<string, any>): this`** Adds filters to refine the permission further. - **`ifEqual(...fields: string[][]): this`** Adds an equality condition for the permission. - **Parameters**: - `fields`: Arrays of field pairs to compare for equality. - **`ifContains(...fields: string[][]): this`** Adds a containment condition for the permission. - **Parameters**: - `fields`: Arrays of field pairs to check for containment. - **`validator(method: string, variables?: Record<string, any>): this`** Adds a custom validator function to the permission. - **Parameters**: - `method`: The name of the custom validation method. - `variables`: Optional key-value map of variables. - **`extend(role: string, permission: string): this`** Extends another permission for the current role. - **Parameters**: - `role`: The base role. - `permission`: The name of the permission to extend. ## **Contributing** Contributions are welcome! Feel free to submit issues or pull requests to improve this library. --- ## **License** This project is licensed under the [MIT License](LICENSE). ---