permit-core
v1.2.1
Published
Core RBAC implementation for Permit
Readme
🛡️ Access Control Module
Enterprise-grade access control system with visual UML documentation
Featuring role-based permissions, group inheritance, and extensible validation
A robust implementation of role-based access control (RBAC) with:
- Visual UML documentation of business logic
- Hierarchical permissions with role/group inheritance
- Extensible validation for routes, components, dropdowns, and menus
- Type-safe API with full TypeScript support
Features ✨
Role & Group Management
- Define roles with custom configurations
- Organize roles into permission groups
- Hierarchical permission inheritance
Permission Types
- 🚦 Route access control with regex support
- 🧩 Component-level permission granularity
- 📋 Menu visibility management
- 🔌 Extensible custom permission types
Enterprise Features
- Middleware support
- Comprehensive error handling
Installation 💻
npm install @ricky-fn/permit-coreQuick Start 🚀
1. Import Required Modules
import {
Role,
Group,
createAccessControl,
createRoutePermission,
RouteAccessAction,
} from "@ricky-fn/permit-core";2. Create Roles and Groups
// Create roles and groups
const adminRole = new Role("admin");
const group = new Group("content-team");
// Assign roles to group
group.assignRole(adminRole);3. Define Permissions
// Group Route Permissions
const groupRoutePermission = createRoutePermission(adminRole, [
{ route: /.*/ },
]);
// Role route permissions, add exclude flag to deny the access.
const adminDropdownPermission = createDropdownPermission(adminRole, [
{ route: /^admin\/*+/ }, // Allow access to routes starting with 'admin/' and any subpaths
{ route: /^system\/*+/, exclude: true }, // Deny access to routes starting with 'system/' and any subpaths
]);4. Initialize Access Control
// Initialize access control
const accessControl = createAccessControl({
roles: [adminRole],
});5. Check Access Permissions
// Check admin/ route access - Expected to succeed
const adminRouteAccessAction = new RouteAccessAction(adminRole.getCode(), {
route: "admin/password",
});
accessControl.checkPermissions(adminRouteAccessAction, {
onSuccess: () => console.log("✅ Admin route access granted!"),
onFailure: (action, message) =>
console.error("❌ Admin route access denied:", message),
});
// Check system/ route access - Expected to fail
const systemRouteAccessAction = new RouteAccessAction(adminRole.getCode(), {
route: "system/reset",
});
accessControl.checkPermissions(systemRouteAccessAction, {
onSuccess: () => console.log("✅ System route access granted!"),
onFailure: (action, message) =>
console.error("❌ System route access denied:", message),
});Documentation 📚
Core Concepts
| Concept | Description | | -------------- | --------------------------------------- | | Role | Defines user permissions and privileges | | Group | Organizes roles with shared permissions | | Permission | Rule set for specific resource access | | Action | Request to perform an operation | | Validator | Checks if action meets permission rules |
Permission Types
| Type | Use Case | | ------------- | ------------------------------- | | Route | Page navigation control | | Component | UI element visibility/actions | | Menu | Navigation menu item visibility | | Dropdown | Dropdown options visibility |
Route Permissions
// Route Permissions
const routePermission = createRoutePermission(adminRole, [
{ route: /^dashboard\/*+/ }, // Allow access to routes starting with 'dashboard/' and any subpaths
{ route: /^settings\/*+/, exclude: true }, // Deny access to routes starting with 'settings/' and any subpaths
{ route: "/profile" }, // Allow access to the exact route '/profile'
]);Key Features:
- Regex Support: Use regular expressions (e.g.,
/^dashboard\/*+/) to match routes dynamically. - Exact Matches: Use strings (e.g.,
'/profile') to match routes exactly. - Exclude Flag: Set
exclude: trueto explicitly deny access to specific routes or patterns.
Component Permissions
// Component Permissions
const componentPermission = createComponentPermission(adminRole, [
{ identifier: "dashboard", actions: ["view", "edit"] }, // Allow 'view' and 'edit' actions on the 'dashboard' component
{ identifier: /^settings-.*/, actions: ["view", "edit"] }, // Allow 'view' and 'edit' action on components with identifiers starting with 'settings-'
{ identifier: "settings-password", actions: ["edit"], exclude: true }, // Deny 'edit' action on the 'settings-password' component
]);Key Features:
- Identifier Matching: Use strings (e.g.,
'dashboard') for exact component matches or regular expressions (e.g.,/^settings-.*/) for dynamic matching. - Action Control: Specify allowed actions (e.g.,
['view', 'edit']) for each component. - Exclude Flag: Set
exclude: trueto explicitly deny specific actions on components.
Menu Permissions
// Menu Permissions
const menuPermission = createMenuPermission(adminRole, [
{ identifier: "main-menu", list: ["dashboard", "settings"] }, // Allow 'dashboard' and 'settings' in the 'main-menu'
{ identifier: "admin-menu", list: ["users", "logs"], exclude: true }, // Deny 'users' and 'logs' in the 'admin-menu'
]);Key Features:
- Identifier Matching: Use strings (e.g.,
'main-menu') or regular expressions (e.g.,/^admin-.*/) to match menu identifiers dynamically. - List Control: Define allowed or denied items in the menu list (e.g.,
['dashboard', 'settings']). - Exclude Flag: Set
exclude: trueto explicitly deny specific items in the menu.
Dropdown Permissions
// Dropdown Permissions
const dropdownPermission = createDropdownPermission(adminRole, [
{ identifier: "actions-dropdown", list: ["edit", "delete"] }, // Allow 'edit' and 'delete' in the 'actions-dropdown'
{ identifier: "admin-dropdown", list: ["reset", "shutdown"], exclude: true }, // Deny 'reset' and 'shutdown' in the 'admin-dropdown'
]);Key Features:
- Identifier Matching: Use strings (e.g.,
'actions-dropdown') or regular expressions (e.g.,/^admin-.*/) to match dropdown identifiers dynamically. - List Control: Define allowed or denied items in the dropdown list (e.g.,
['edit', 'delete']). - Exclude Flag: Set
exclude: trueto explicitly deny specific items in the dropdown.
How Roles and Groups Work
- Roles are the building blocks of the access control system. Each role defines a set of permissions that determine what actions a user can perform.
- Groups are collections of roles. By assigning roles to groups, you can manage permissions more efficiently, especially in large systems with many roles.
- Group Inheritance: Groups can inherit permissions from other groups. For example, if
Group Ainherits fromGroup B, all roles inGroup Awill also have the permissions ofGroup B. This allows for hierarchical permission structures, where higher-level groups grant broader permissions that are inherited by lower-level groups.
UML Design Overview
Basic Access Control Flow:
Basic Permission Assignment Flow:
Basic Permission Validation Flow:

Contributing 🤝
We welcome contributions! Please follow these steps:
- Fork the repository
- Create your feature branch (
git checkout -b feat/your-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin feat/your-feature) - Open a pull request
Commit Message Guidelines
<type>(<scope>): <subject>
<body>
<footer>Example:
feat(permissions): add custom validator hooks
- Implemented beforeValidate/afterValidate hooks
- Added documentation examples
- Updated test coverage
Resolves: #123License 📄
This project is licensed under the MIT License - see the LICENSE file for details.
Changelog 📜
v1.2.0
- Change: Updated permission inheritance logic. Previously, both the group and the role had to contain the permission and rule for an action to be allowed. Now, if a group contains the permission, roles assigned to that group will inherit it; the role no longer needs to duplicate the same permission/rule.
v1.1.0
- New Feature: Enhanced
AccessControlto support groups with new methods for adding and retrieving groups
v1.0.0 (Initial Release)
- Core RBAC implementation
- Role and Group management
- Route, Component, Menu, and Dropdown permissions
- TypeScript support
- UML documentation
