Repository navigation
Add Built-In Role-Based Access Control (RBAC) with Roles, Permissions, and Assignments #237
Description
✅ Problem
The project currently lacks a reusable and structured RBAC (Role-Based Access Control) system, with the following issues:
-
No Role model or user-role mapping
Users cannot have multiple roles, and roles cannot share permissions in a reusable way. -
No standard way to define permissions
There is no centralized permission list or front-end-friendly permission structure. -
No permission-checking mechanism
Access control relies only onis_superuseror resource ownership, which is insufficient for enterprise multi-role, multi-admin systems. -
No API, dependencies, admin panel, or documentation for RBAC
Teams must implement their own solutions, leading to duplication and inconsistency.
✅ Proposal
Introduce a clean and extensible RBAC system without a database Permission model:
1. Permissions as Code Constants
Define all permissions centrally as code constants:
class PermissionNames:
user = "user"
user_create = f"{user}.create"
user_delete = f"{user}.delete"
book = "book"
book_edit = f"{book}.edit"Benefits:
- Centralized and maintainable
- No database table needed
- Avoids duplicate or stale data
- Adding new permissions only requires code changes
2. Permission Tree for Hierarchy and UI
Use a dedicated class PermissionNode to build hierarchical structures:
PermissionNode(
name=PermissionNames.user,
children=[
PermissionNode(name=PermissionNames.user_create),
PermissionNode(name=PermissionNames.user_delete),
]
)Purpose:
- Render permission tree in admin/front-end UI
- Allow administrators to select permissions
- Single source of truth for permission hierarchy
3. Data Models (Simplified)
roles: id, name, description, timestampsrole_permission: role_id, permission_name (string constant)user_role: user_id, role_id
No separate Permission model is needed, keeping the database simple.
4. API / CRUD
Provide standard endpoints:
- Create/update/delete roles
- Assign/remove permissions to roles (string constants)
- Assign/remove roles to users
- Query a user’s effective permissions
5. Permission Checks
Use FastAPI dependencies:
require_permissions(PermissionNames.user_create,PermissionNames.user_delete)Logic:
- Aggregate permissions from all roles assigned to the user
- Superusers bypass checks
- Supports any/all permission modes
6. Admin Panel Integration
- Role management UI includes permission assignment
- Permission tree automatically rendered from
PermissionNodehierarchy
7. Documentation and Testing
- Document how to define permissions, build the permission tree, and protect endpoints
- Test role assignment and permission checks
📌 Summary
Problem: The project lacks RBAC, making role management and permission control difficult.
Proposal: Add Role, UserRole, and RolePermission models; define permissions as code constants with a hierarchical tree; implement require_permission checks; provide complete API, admin UI, docs, and tests.
Activity
ayushGadag commentedon Aug 8, 2026
Hi! I’m an engineering student and I’m interested in working on this issue as part of my 2–3 month college engineering project.
I’ve studied the issue description and I’m interested in implementing the RBAC functionality, including the database models/migrations, role and permission APIs, permission-checking dependencies, tests, and documentation.
Before starting implementation, I wanted to ask whether the maintainers would be comfortable with me taking this issue up as my academic project.
I will follow the project’s contribution guidelines, discuss the implementation/design with you before making major changes, and submit proper tests and documentation through the normal PR process.
I’m not asking for any special treatment or guaranteed acceptance. I simply want to confirm that you’re comfortable with me working on this issue as part of my college project.
If this scope looks reasonable, I’d be happy to prepare a short implementation plan before beginning.
Thank you!
mo-hossam-stack commentedon Aug 12, 2026
Is any one working on this issue? if not i would like to work on it
sdrarunvarshan commentedon Aug 13, 2026
I would also like to contribute
emiliano-go commentedon Sep 19, 2026
RBAC is one feature, so I'm folding #275 (the admin panel work) into this issue and closing it. The admin views, user-role assignment, effective-permissions display, tests and docs it describes are copied below. One issue, one thread.
Prior art: #278 (closed, unmerged) sketched the role module and the three admin views, but it has no tests and no migration, and it predates the recent auth and error-handling refactors. Use it as a reference, not a branch to revive.
These three decisions are settled, not up for debate:
PermissionNamesplusPERMISSION_TREE); there is no DBPermissiontable.CREATE_TABLES_ON_STARTUP=true, andBase.metadata.create_allruns in the lifespan), so the role tables come from the models. When someone adds the first revision,import_models("src.modules")picks them up automatically.interfaces/admin/widgets.pyis a later, optional addition.The work, as separate pieces you can pick from:
Role,RolePermissionandUserRole, thePermissionNamesconstants andPERMISSION_TREE, and theUser.user_rolesrelationship.require_permissionsdependency, with the superuser bypass and all/any modes, plus the effective-permissions query.RoleAdmin,RolePermissionAdminandUserRoleAdmin, registered with the existing views.UserAdminroles and effective permissions (read only) and role assignment.tests/integration/admin/and wherever the API work needs them.docs/user-guide/admin-panel/.Some pieces depend on others: 1 lands first, and 2 through 6 build on it. Reply with the piece you want and a few lines on how you'd approach it. The three decisions above are fixed, so don't plan around changing them unless you've got a good reason.
How we'll coordinate:
@ayushGadag @mo-hossam-stack @sdrarunvarshan @zayed95 if you want to take a piece, reply and claim it.
ayushGadag commentedon Sep 20, 2026
Hi @emiliano-go, I'd like to take piece #5 — Admin views.
I'll work on implementing RoleAdmin, RolePermissionAdmin, and UserRoleAdmin, and register them with the existing admin views. I'll follow the project's existing SQLAdmin patterns and build on the RBAC models and services provided by the earlier pieces.
I'll keep the changes focused on the admin integration described in this issue.
Krishgit2005 commentedon Sep 24, 2026
Hi @emiliano-go , I'd like to take up an available piece that is relatively easy to start with, preferably Piece #8 — Documentation or another suitable beginner-friendly task.
I'm interested in contributing to the RBAC implementation and will follow the project's existing patterns and guidelines. Please let me know which piece would be suitable for me to work on.
I'll keep my changes focused on the assigned task and coordinate with the other contributors.
emiliano-go commentedon Sep 24, 2026
@Krishgit2005 point 8 is a good start, but we are still waiting on an implemention of point 1, as everything depends on it. I may scaffold it later today as for you guys to keep working on this.
Ping me if needed.
Vins01-07 commentedon Sep 24, 2026
Hi @emiliano-go , I'd like to take up Piece #1 — Core models and permissions.
I'm interested in contributing to the RBAC implementation, specifically the Role, RolePermission, and UserRole models, the PermissionNames constants and PERMISSION_TREE, and the User.user_roles relationship.
I'll follow the project's existing patterns and guidelines and keep my changes focused on this piece. Please let me know if there are any specific considerations or dependencies I should be aware of.
emiliano-go commentedon Sep 24, 2026
@Vins01-07 nice! That is the base where everyone will build on, so I'll probably review it harder than the rest. Feel free to ama, I'll wait for your PR.
Piyagaikwad commentedon Sep 25, 2026
Hi @emiliano-go I’d like to take piece #2 : Role schemas, service and CRUD.
I’ll build the Pydantic schemas and service/CRUD operations around the Role, RolePermission, and UserRole models from piece 1, following the project’s existing service and schema patterns. I’ll keep the scope limited to the role module so that the API routes and permission dependency can build on top of it separately.
mo-hossam-stack commentedon Sep 25, 2026
hi @emiliano-go i would like to take piece #3 - Role API routes
I’ll implement the role-related API endpoints on top of the schemas, service, and CRUD from Piece #2, following the project’s existing FastAPI routing patterns.
I’ll keep the scope focused on the API routes and coordinate with the contributors working on the core models and role service.
Vins01-07 commentedon Sep 25, 2026
Hi @emiliano-go , I’ve submitted PR #302 for Piece 1 (RBAC core models and permissions). Please take a look when you have time and merge it if everything looks good. Thanks!
emiliano-go commentedon Sep 25, 2026
@mo-hossam-stack @Piyagaikwad nice. Feel free to AMA or @ me if you have any issues.
@Vins01-07 looking at your PR rn.
igorbenav commentedon Sep 25, 2026
RBAC spec
Thanks @null-ed for the original proposal, and @Vins01-07 for starting on it in #302. The direction in this issue is right: three tables and permissions defined in code. Before we build the rest in pieces, this comment pins down the details so every PR works from the same spec. Comments are welcome, especially on the open questions at the end.
Goals
Not in scope for v1
is_superuser. It stays and bypasses every permission check.1. Permission format
A permission is a flat string,
"<resource>.<action>", e.g.tier.readorrole.assign.app_label.codename) and Kubernetes (resources × verbs) both work this way. The UI grouping is "group by resource prefix", so nobody maintains a tree by hand.billing.invoice_read.Principal.scopes, so token and API-key scopes can later use the same vocabulary (see §6).2. Declaring permissions
Each module that owns a resource declares its permissions in its own
permissions.py, as aStrEnum(the same style asapi_keys/enums.py):src/modules/role/registry.pyprovides:register_permissions(resource, label=None)f"{resource}."and rejects the same resource registered twice.all_permissions() -> frozenset[str]permission_groups() -> list[PermissionGroup]{resource, label, permissions}, for the UI and API.is_known_permission(name) -> boolDiscovery: at startup, walk
src.modules.*.permissions, the same waymigrations/env.pyalready finds models. A new module is picked up automatically.Built-in permissions:
user.*,role.*(read,create,update,delete,assign) andtier.*.3. Data model
SoftDeleteMixin. FastCRUD soft-deletes any model withis_deleted, so a soft-deleted role would keep its assignments, keep granting access, and keep its name taken. Deleting a role must revoke access.idand no extra unique constraint.RolePermission.permissionis checked againstall_permissions()whenever it's set through the ORM. Reads never assume a stored string is still valid (see §7).user_rolesrows, so restoring a user restores their roles. Authentication already rejects soft-deleted users, so the leftover rows grant nothing.4. Checking permissions
One dependency, built on crudauth's
check=hook so there's no second auth path:require_any_permissionlater.get_effective_permissionsruns one query (user_roles→role_permissions), drops unrecognised strings, and caches the result onrequest.statefor the rest of the request.ForbiddenException; no credentials returns 401 as it does today.5. Rules
get_current_superuser.user.updatemeans "update any user". Editing your own profile stays the existing ownership rule inUserService, not a permission.escalate/bindrules:role.create/role.update, and the actor must already hold every permission they add.role.assign, and the actor must already hold every permission that role grants.6. API keys and tokens (follow-up, but decided now)
When a credential carries scopes, what it can do is the owner's effective permissions narrowed by those scopes. Session credentials carry no scopes, so they get the full set. Moving
KeyPermission(the resource/action enums) onto these strings can be a separate follow-up PR. It isn't part of v1, but because the formats match, it won't need a redesign.7. API surface (Piece 2)
GET /permissions(grouped registry)GET /users/me/permissions(effective set, for frontends)GET/POST /roles,GET/PATCH/DELETE /roles/{id}role.read/create/update/deletePUT /roles/{id}/permissionsrole.update+ escalation rulePOST/DELETE /users/{username}/roles/{role_id}role.assign+ escalation rule8. Delivery plan
Piece 1: core. Registry, per-module enums for
user/role/tier, the three models,require_permissions+get_effective_permissions, and one existing route switched over (e.g. tier create) to prove it end to end. Tests:The cascade test must run against Postgres in CI.
Piece 2: management API. Schemas, CRUD and routes from §7, including the escalation rules and their tests.
Piece 3: admin. A crudadmin view for roles, with permission checkboxes grouped by resource from
permission_groups(), and a user → roles editor.Piece 4: adoption and docs. Move routes that should be delegable from
get_current_superuserto permissions, and document how to declare permissions in a new module.Some open questions for us to discuss
adminwith every permission), or isis_superuserenough for bootstrapping? I lean towards no seeding in v1..fine, or do we want:to match OAuth/GitHub-style scopes (tier:read)? I lean towards.since it's already used in feat: Piece 01: add RBAC core models and permissions #302.ayushGadag commentedon Sep 26, 2026
Hi @emiliano-go @igorbenav, I previously claimed Piece #5 (Admin views) under the earlier plan. With the updated RBAC plan, I’d like to go with Piece #3 — Admin instead.
I’ll work on the SQLAdmin admin views for roles, permissions grouped by resource using permission_groups(), and the user → roles editor, following the existing admin patterns.
Please let me know if that’s okay.
Krishgit2005 commentedon Sep 26, 2026
Hi @emiliano-go @igorbenav, I’d like to take up Piece #2 — Management API.
I’ll implement the schemas, CRUD/service layer, and role management API routes according to the updated RBAC specification, including the required permission and escalation checks. I’ll follow the project’s existing FastAPI patterns and keep the changes focused on Piece 2.
Please let me know if there are any specific considerations I should be aware of before starting.
Piyagaikwad commentedon Sep 26, 2026
Hi @emiliano-go @igorbenav, I’d like to take up Piece #4 — Adoption and docs.
I’ll review the existing routes that currently rely on get_current_superuser, move the appropriate ones to the new permission-based dependency, and document how new modules can declare and use permissions with the RBAC registry. I’ll follow the existing project patterns and keep the changes focused on Piece 4.
emiliano-go commentedon Sep 26, 2026
@ayushGadag @Krishgit2005 @Piyagaikwad nice!
Thanks for the contributions, and @ me if you need anything.
Krishgit2005 commentedon Sep 30, 2026
Hi @emiliano-go @igorbenav,
I’d like to start working on Piece #2 — Management API.
I’ve reviewed the latest RBAC changes and the updated requirements, including the permission/escalation rules and the remaining Piece 2 responsibilities.
Should I go ahead and start implementing Piece 2 now, or is there anything you’d like me to clarify or coordinate before I begin?
Thanks!
igorbenav commentedon Sep 30, 2026
@Krishgit2005 don't start it yet please, there's a huge refactor happening and it will probably conflict. Once I merge #305 you're good to go