advanced-react-role-guard
v1.0.0
Published
Declarative role & permission guards for React apps
Maintainers
Readme
Simple React Role Guard
Declarative role & permission guards for React apps
Centralize roles, permissions, and feature access in React apps. No more scattered if (user.role === "admin") everywhere.
✨ Features
- ✅ Role-based rendering - Declarative role checks
- ✅ Permission-based rendering - Granular permission control
- ✅ Route protection - Guard routes with roles/permissions
- ✅ Feature flags - Lightweight feature toggles
- ✅ Framework-agnostic - Works with React / Next.js
- ✅ SSR-safe - Server-side rendering compatible
- ✅ TypeScript - Full type safety
- ✅ Wildcard permissions - Support for
user:*patterns
🚀 Installation
npm install advanced-react-role-guard📖 Quick Start
import { RoleGuardProvider, Can, useCan } from "advanced-react-role-guard";
function App() {
return (
<RoleGuardProvider
user={{
roles: ["admin"],
permissions: ["user:create", "user:delete"],
}}
config={{
admin: ["*"],
editor: ["post:create", "post:update"],
}}
>
<Dashboard />
</RoleGuardProvider>
);
}
function Dashboard() {
const canDelete = useCan("user:delete");
return (
<div>
<Can role="admin">
<AdminPanel />
</Can>
<Can permission="post:create">
<CreatePostButton />
</Can>
<Can
permissions={["order:edit", "order:cancel"]}
match="any"
fallback={<span>No access</span>}
>
<OrderActions />
</Can>
{canDelete && <DeleteUserButton />}
</div>
);
}🧩 API Reference
RoleGuardProvider
Global configuration and user context.
<RoleGuardProvider
user={{
roles: ["admin", "editor"],
permissions: ["user:create", "post:*"],
}}
config={{
admin: ["*"], // Wildcard: all permissions
editor: ["post:create", "post:update"],
viewer: ["post:read"],
}}
features={{
newDashboard: true,
aiSearch: false,
}}
>
<App />
</RoleGuardProvider>Props:
user?: User | null- Current user with roles and permissionsconfig?: RoleGuardConfig- Role-to-permission mappings and features
<Can /> Component
Declarative access control.
// Single role
<Can role="admin">
<AdminPanel />
</Can>
// Single permission
<Can permission="user:delete">
<DeleteButton />
</Can>
// Multiple permissions (any)
<Can permissions={["post:create", "post:update"]}>
<EditPost />
</Can>
// Multiple permissions (all required)
<Can permissions={["post:create", "post:publish"]} match="all">
<PublishPost />
</Can>
// With fallback
<Can
permission="admin:access"
fallback={<AccessDenied />}
>
<AdminSettings />
</Can>Props:
role?: string- Check if user has this rolepermission?: string- Check if user has this permissionpermissions?: string[]- Check multiple permissionsmatch?: "any" | "all"- Match mode for multiple permissions (default: "any")fallback?: ReactNode- Render when access denied
useCan() Hook
Programmatic access checks.
function MyComponent() {
const canEdit = useCan("post:update");
const isAdmin = useCan({ role: "admin" });
const canManageUsers = useCan({
permissions: ["user:create", "user:delete"],
match: "all"
});
if (!canEdit) return null;
return <EditButton />;
}Parameters:
// Single role
useCan({ role: "admin" })
// Single permission
useCan({ permission: "user:delete" })
// Multiple permissions
useCan({
permissions: ["post:create", "post:update"],
match: "any" | "all" // default: "any"
})<Guard /> Component
Route protection (alias for <Can />).
// React Router example
<Route
path="/admin"
element={
<Guard role="admin" fallback={<Navigate to="/403" />}>
<AdminPage />
</Guard>
}
/><Feature /> Component
Feature flag rendering.
<Feature name="newDashboard">
<DashboardV2 />
</Feature>
<Feature name="aiSearch" fallback={<BasicSearch />}>
<AISearch />
</Feature>🔑 Permission System
Wildcard Permissions
config={{
admin: ["*"], // All permissions
manager: ["user:*"], // All user-related permissions
editor: ["post:*"], // All post-related permissions
}}
user: {
permissions: ["user:create", "post:*"]
}Permission Matching
- Exact match:
"user:delete"matches"user:delete" - Wildcard:
"*"matches any permission - Prefix wildcard:
"user:*"matches"user:create","user:delete", etc.
Role Inheritance
Roles are mapped to permissions in the config:
config={{
admin: ["*"],
editor: ["post:create", "post:update", "post:delete"],
viewer: ["post:read"],
}}
user: {
roles: ["editor"], // Gets post:create, post:update, post:delete
}🏗️ Architecture
User → Roles → Permissions → Access Decision → UI / Route- User: Current user with roles and direct permissions
- Roles: Mapped to permission sets in config
- Permissions: Granular access controls
- Features: Optional feature flags
🔧 Advanced Usage
Custom Context
import { useRoleGuardContext } from "advanced-react-role-guard";
function CustomComponent() {
const { hasRole, hasPermission, hasFeature } = useRoleGuardContext();
// Direct access to context methods
const canAccess = hasPermission("custom:action");
return canAccess ? <CustomUI /> : null;
}TypeScript Types
import type {
User,
RoleConfig,
RoleGuardConfig,
CanProps,
UseCanParams
} from "advanced-react-role-guard";
// Strongly typed usage
const user: User = {
roles: ["admin"],
permissions: ["user:*"]
};🎯 Use Cases
- SaaS Dashboards - Multi-tenant role management
- CMS Systems - Content creation permissions
- E-commerce - Order management access
- Admin Panels - Feature-restricted interfaces
- Enterprise Apps - Complex permission matrices
🤝 Framework Integration
React Router
import { Guard } from "advanced-react-role-guard";
<Route
path="/admin/users"
element={
<Guard permission="user:manage" fallback={<Navigate to="/dashboard" />}>
<UserManagement />
</Guard>
}
/>Next.js
Works seamlessly with Next.js SSR:
// pages/admin.tsx
import { Guard } from "advanced-react-role-guard";
export default function AdminPage() {
return (
<Guard role="admin" fallback={<div>Access Denied</div>}>
<AdminDashboard />
</Guard>
);
}📦 Bundle Size
- Core: ~3.6KB gzipped
- Full: ~8KB gzipped (with all features)
🤝 Contributing
PRs welcome! Please include tests and update documentation.
📄 License
MIT © [Parsa Jiravand]
Made with ❤️ for clean, secure React apps
