Skip to content

Rqdhw3ns/react-access-control

Repository files navigation

@rqdhw3n/react-access-control

Lightweight access control utilities for React applications. The package provides a small context provider, a declarative Can component, focused hooks, pure utility functions, and an optional React Router entrypoint for page protection.

GitHub: https://github.com/rqdhw3ns

Features

  • Tiny runtime footprint
  • React 18+ compatible
  • Works with Vite, Next.js, CRA, and TypeScript React apps
  • Roles and permissions support
  • Declarative and programmatic access checks
  • Optional React Router v6 route protection
  • Shared access context across both the main package and router entrypoint
  • ESM, CJS, and TypeScript declaration output

Installation

Install the core package:

npm install @rqdhw3n/react-access-control

If you want route protection, install React Router too:

npm install @rqdhw3n/react-access-control react-router-dom
yarn add @rqdhw3n/react-access-control react-router-dom
pnpm add @rqdhw3n/react-access-control react-router-dom

Quick Start

import {
  AccessProvider,
  Can,
  useCanPermission
} from '@rqdhw3n/react-access-control';

function DeleteButton() {
  const canDeleteUsers = useCanPermission('users.delete');

  if (!canDeleteUsers) {
    return null;
  }

  return <button type="button">Delete user</button>;
}

export function App() {
  return (
    <AccessProvider
      roles={['admin']}
      permissions={['users.create', 'users.delete']}
    >
      <Can role="admin">
        <section>Admin panel</section>
      </Can>

      <DeleteButton />
    </AccessProvider>
  );
}

AccessProvider

Wrap your app with AccessProvider to make the current user's roles and permissions available throughout the tree.

import { AccessProvider } from '@rqdhw3n/react-access-control';

<AccessProvider
  roles={['admin']}
  permissions={['users.create', 'users.delete']}
>
  <App />
</AccessProvider>;

Can Component

Render children only when the access requirement is satisfied.

import { Can } from '@rqdhw3n/react-access-control';

<Can role="admin">
  <AdminPanel />
</Can>;
<Can permission="users.delete" fallback={<NoAccess />}>
  <DeleteButton />
</Can>;
<Can permissions={['users.create', 'users.update']} requireAll>
  <UserActions />
</Can>;

You can combine role and permission requirements. When requireAll is false, matching any supplied role or permission is enough. When requireAll is true, every supplied role and permission requirement must match.

ProtectedRoute

ProtectedRoute is available from a separate router entrypoint so apps that do not use React Router do not need the dependency. It uses the same AccessProvider context as the main package, so one provider can drive both component-level and route-level access checks.

import { ProtectedRoute } from '@rqdhw3n/react-access-control/router';

ProtectedRoute must be rendered inside AccessProvider.

Basic Example

import { AccessProvider } from '@rqdhw3n/react-access-control';
import { ProtectedRoute } from '@rqdhw3n/react-access-control/router';

<AccessProvider
  roles={['admin']}
  permissions={['users.view', 'users.delete']}
>
  <ProtectedRoute permission="users.delete" redirectTo="/">
    <DeleteUsersPage />
  </ProtectedRoute>
</AccessProvider>;

React Router v6 Example

import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { AccessProvider } from '@rqdhw3n/react-access-control';
import { ProtectedRoute } from '@rqdhw3n/react-access-control/router';

function App() {
  return (
    <AccessProvider
      roles={['admin']}
      permissions={['dashboard.view', 'users.view', 'users.delete']}
    >
      <BrowserRouter>
        <Routes>
          <Route path="/" element={<HomePage />} />

          <Route
            path="/dashboard"
            element={
              <ProtectedRoute permission="dashboard.view" redirectTo="/">
                <DashboardPage />
              </ProtectedRoute>
            }
          />

          <Route
            path="/admin"
            element={
              <ProtectedRoute role="admin" redirectTo="/">
                <AdminPage />
              </ProtectedRoute>
            }
          />

          <Route
            path="/users/delete"
            element={
              <ProtectedRoute permission="users.delete" redirectTo="/">
                <DeleteUsersPage />
              </ProtectedRoute>
            }
          />
        </Routes>
      </BrowserRouter>
    </AccessProvider>
  );
}

Redirect Example

<ProtectedRoute permission="users.delete" redirectTo="/">
  <DeleteUsersPage />
</ProtectedRoute>

Fallback Example

<ProtectedRoute role="admin" fallback={<NoAccessPage />}>
  <AdminPage />
</ProtectedRoute>

If access is denied, ProtectedRoute behaves like this:

  • redirectTo provided: renders React Router's <Navigate />
  • fallback provided without redirectTo: renders the fallback
  • neither provided: returns null

Hooks

useAccess()

import { useAccess } from '@rqdhw3n/react-access-control';

function Summary() {
  const { roles, permissions, canAccess } = useAccess();

  return (
    <pre>
      {JSON.stringify(
        {
          roles,
          permissions,
          canManageUsers: canAccess({ permission: 'users.manage' })
        },
        null,
        2
      )}
    </pre>
  );
}

useCanRole(role)

import { useCanRole } from '@rqdhw3n/react-access-control';

function AdminBadge() {
  const isAdmin = useCanRole('admin');

  return isAdmin ? <span>Admin</span> : null;
}

useCanPermission(permission)

import { useCanPermission } from '@rqdhw3n/react-access-control';

function CreateUserButton() {
  const canCreateUser = useCanPermission('users.create');

  return canCreateUser ? <button>Create user</button> : null;
}

useCanAccess(options)

import { useCanAccess } from '@rqdhw3n/react-access-control';

function UserActions() {
  const canManageUsers = useCanAccess({
    roles: ['admin', 'manager'],
    permissions: ['users.create', 'users.update'],
    requireAll: false
  });

  return canManageUsers ? <div>User actions</div> : null;
}

Utility Functions

All utility functions are pure and can be used outside React.

import {
  hasRole,
  hasPermission,
  canAccess
} from '@rqdhw3n/react-access-control';

hasRole(['admin', 'editor'], ['admin']);
hasPermission(['users.create'], ['users.create', 'users.update'], false);

canAccess({
  userRoles: ['manager'],
  userPermissions: ['reports.view'],
  roles: ['admin', 'manager'],
  permission: 'reports.view'
});

Props

AccessProviderProps

Prop Type Required Description
roles string[] No Current user roles
permissions string[] No Current user permissions
children ReactNode Yes React tree that receives access context

CanProps

Prop Type Required Description
role string No Single required role
roles string[] No Multiple required roles
permission string No Single required permission
permissions string[] No Multiple required permissions
requireAll boolean No Require all supplied checks to pass
fallback ReactNode No Rendered when access is denied
children ReactNode Yes Rendered when access is allowed

ProtectedRouteProps

Prop Type Required Description
role string No Single required role
roles string[] No Multiple required roles
permission string No Single required permission
permissions string[] No Multiple required permissions
requireAll boolean No Require all supplied checks to pass
redirectTo string No Redirect path when access is denied
fallback ReactNode No Rendered when access is denied and no redirect is used
children ReactNode Yes Rendered when access is allowed

TypeScript

The package ships with full type declarations and exports the main public types:

import type {
  AccessProviderProps,
  CanProps,
  AccessContextValue,
  AccessCheckOptions,
  ProtectedRouteProps
} from '@rqdhw3n/react-access-control';

Security Note

This package only controls client-side rendering and navigation. Your backend must still enforce roles, permissions, and authorization rules for every protected action and route.

Example App

A minimal Vite example app is included in example/ for local development and manual testing.

License

MIT

About

React access control library for managing roles, permissions, protected routes, and conditional rendering with TypeScript support.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors