Metadata-Version: 2.4
Name: fastapi-fabric-rbac
Version: 0.1.0
Summary: Role-based access control for FastAPI — permissions, roles, groups, and effective-permission resolution.
Project-URL: Homepage, https://git.punakawanlab.id/PunakawanLab/fastapi-fabric
Project-URL: Repository, https://git.punakawanlab.id/PunakawanLab/fastapi-fabric
Author-email: Yoiq S Rambadian <yoiqsram@punakawanlab.id>
License-Expression: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: FastAPI
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
Classifier: Topic :: System :: Systems Administration :: Authentication/Directory
Requires-Python: >=3.10
Requires-Dist: fastapi-fabric-auth<0.2.0,>=0.1.0
Requires-Dist: fastapi-fabric-core<0.2.0,>=0.1.0
Requires-Dist: passlib[argon2]>=1.7.4
Description-Content-Type: text/markdown

# fastapi-fabric-rbac

Role-based access control for FastAPI — permissions, roles, groups, and effective-permission resolution.

## Install

```bash
pip install fastapi-fabric[auth,rbac]
```

## Routers

```python
from fastapi_fabric.rbac import create_roles_router, create_groups_router

app.include_router(create_roles_router())
app.include_router(create_groups_router())
```

## Endpoints

| Method | Path | Description |
|---|---|---|
| `GET` | `/api/v1/permissions` | List all permissions (public) |
| `GET` | `/api/v1/roles` | List roles (`roles:list`) |
| `POST` | `/api/v1/roles` | Create role (`roles:create`) |
| `POST` | `/api/v1/roles/{role_slug}/permissions` | Assign permission to role (`roles:update`) |
| `POST` | `/api/v1/users/{username}/roles` | Assign role to user (`roles:update`) |
| `DELETE` | `/api/v1/users/{username}/roles/{role_slug}` | Remove role from user (`roles:update`) |
| `GET` | `/api/v1/users/{username}/permissions` | Effective permissions for a user (self, or `roles:read`) |
| `GET` | `/api/v1/groups` | List groups (`groups:list`) |
| `POST` | `/api/v1/groups` | Create group (`groups:create`) |
| `POST` | `/api/v1/groups/{group_slug}/members` | Add user to group (`groups:modify`) |
| `POST` | `/api/v1/groups/{group_slug}/roles` | Assign role to group (`groups:modify`) |
| `POST` | `/api/v1/groups/{group_slug}/members/{user_id}/roles` | Assign a role scoped to one group member (`groups:modify`) |

## Guarding routes

```python
from fastapi import Depends
from fastapi_fabric.auth.dependencies.permissions import require_permission

@app.delete(
    "/posts/{post_id}",
    dependencies=[Depends(require_permission("posts:delete"))],
)
async def delete_post(post_id: str):
    ...
```

`require_permission` raises `403` if the principal lacks the permission. The system admin always passes.

## Permissions

Permissions follow a `resource:action` naming convention. Application code defines its own by subclassing nothing special — just assign `Permission(...)` instances on a holder class:

```python
from fastapi_fabric.core import Permission

class ReportPermissions:
    EXPORT = Permission("reports:export", "Export reports to CSV", "Reports")
```

Built-in permissions (seeded automatically by this package and `fastapi-fabric-auth`):

| Permission | Grants |
|---|---|
| `users:list` / `users:read` | Search / view user accounts |
| `users:create` / `users:modify` / `users:deactivate` | Manage user accounts |
| `roles:list` / `roles:read` | View roles and their permissions |
| `roles:create` / `roles:update` / `roles:delete` | Manage roles and role-permission assignments |
| `groups:list` / `groups:read` | View groups and members |
| `groups:create` / `groups:modify` / `groups:delete` | Manage groups, members, and group roles |
| `api_keys:list` / `api_keys:create` | Manage API keys for any user or service account |
| `service_accounts:read` / `service_accounts:create` | Manage service accounts |
| `audit:read` | Query the audit log |
| `analytics:read` | Query analytics events and metrics |

`admin` is seeded with the full set above; `auditor` is seeded with every `*:read`/`*:list` permission (read-only access everywhere, no mutation rights).

## Effective permissions

A user's effective permissions are the union of:
1. Permissions from roles assigned directly to the user
2. Permissions from roles assigned group-wide to groups the user belongs to

Roles assigned to a *specific member* of a group (`groups_members_roles_assign`) are scoped to that group only — they don't leak into the user's global permission set.

```bash
GET /api/v1/users/{username}/permissions
# → { "permissions": ["users:read", "roles:list", "audit:read"] }
```

## Startup seeding

```python
from fastapi_fabric.rbac.seeds import upsert_builtin_roles_and_permissions

async for session in get_session():
    await upsert_builtin_roles_and_permissions(session)
    await session.commit()
```

Creates the built-in `admin` and `auditor` roles and seeds all built-in permissions on first startup. Idempotent — safe to call on every startup.
