Role-based access control (RBAC)

Permissions bundled into named roles like admin, editor, viewer, so people get a role instead of a pile of individual checkboxes.

admin vs regular userpermission levelsroles and permissionsgive this person a role instead of checkboxesrole based acess controlmake some users admins and some read-onlywho can edit versus who can only viewdifferent account types with different access

See it

Live demo coming soon

What it is

RBAC puts a layer between people and permissions: users get roles, roles hold permissions, and code checks permissions. The discipline that makes it worth the indirection is checking can(user, 'invoice:delete') and never if (user.role === 'admin'), because the second form means a new 'billing manager' role turns into a hundred edited conditionals. In a multi-tenant product the role belongs on the membership row, not the user row: the same person can own one workspace and be a viewer in another, and their permissions have to change when they switch context.

Start small, because you can always add. Owner, admin, member, viewer covers most B2B products, plus one billing permission that owners keep to themselves. Write the permission matrix as a literal table (roles down the side, permissions across the top) and generate the check function from it, so the docs and the enforcement cannot drift apart. Protect the last-owner case: never let someone remove or downgrade the final owner of an organization.

Gotchas: role explosion, where every 'they should be able to X but not Y' request adds a role until you are maintaining forty of them. When the rules start depending on the resource rather than the person (only records they created, deals above a threshold, during business hours), roles have run out and you want ABAC or ReBAC instead. And hiding the delete button is presentation, not access control: the same check has to run on the server, since the client is just a suggestion.

Ask AI for it

Add role-based access control to this app. Define a permissions list of 'resource:action' strings and a literal ROLE_PERMISSIONS map for owner, admin, member, and viewer, typed with 'as const' so permission names are checked at compile time. Store the role on the organization membership record, not on the user, so a user can hold different roles in different workspaces. Expose a single can(membership, permission) helper, enforce it server-side in every mutation and query before any data is returned, and use the same helper in the UI to hide actions the user cannot perform. Block removing or downgrading the last owner of an organization, and write tests asserting each role's exact permission set.

You might have meant

authentication vs authorizationorganization workspace membershipattribute based access controlpermission policy engineauth guard protected route