Metadata-Version: 2.4
Name: fastapi-rbac-kit
Version: 0.1.0
Summary: Drop-in role-based access control for FastAPI — roles, permissions, decorators.
Author-email: Shahab Rashidian Dezfuly <mm4heidary@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/shahabRDZ/fastapi-rbac
Project-URL: Repository, https://github.com/shahabRDZ/fastapi-rbac
Project-URL: Issues, https://github.com/shahabRDZ/fastapi-rbac/issues
Keywords: fastapi,rbac,authorization,roles,permissions,security
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 :: Security
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: fastapi>=0.100.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: httpx>=0.24; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# fastapi-rbac

[![PyPI version](https://badge.fury.io/py/fastapi-rbac.svg)](https://pypi.org/project/fastapi-rbac/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://www.python.org/downloads/)
[![FastAPI](https://img.shields.io/badge/FastAPI-0.100%2B-009688.svg)](https://fastapi.tiangolo.com)

Drop-in role-based access control for FastAPI. Define roles and permissions, protect endpoints with dependency injection.

## Installation

```bash
pip install fastapi-rbac
```

## Quick Start

```python
from fastapi import FastAPI, Depends
from fastapi_rbac import RBAC, Permission, require_role, require_permission

app = FastAPI()
rbac = RBAC()  # comes with admin, editor, viewer roles

# Add a custom role
rbac.add_role("moderator", ["read", "write", "delete"])
```

## Protecting Endpoints

### By Role

Restrict access to specific roles:

```python
from fastapi_rbac import require_role, set_default_rbac

set_default_rbac(rbac)

# Your auth dependency that returns a user object with a .role attribute
def get_current_user():
    ...

@app.get(
    "/admin/dashboard",
    dependencies=[require_role("admin", get_user=get_current_user)],
)
def admin_dashboard():
    return {"message": "Welcome, admin!"}


@app.get(
    "/content",
    dependencies=[require_role("admin", "editor", get_user=get_current_user)],
)
def manage_content():
    return {"message": "Content management"}
```

### By Permission

Check if the user's role has a specific permission:

```python
from fastapi_rbac import require_permission

@app.get(
    "/articles",
    dependencies=[require_permission("read", rbac=rbac, get_user=get_current_user)],
)
def list_articles():
    return {"articles": []}


@app.post(
    "/articles",
    dependencies=[require_permission("write", rbac=rbac, get_user=get_current_user)],
)
def create_article():
    return {"created": True}


@app.delete(
    "/articles/{id}",
    dependencies=[require_permission("delete", rbac=rbac, get_user=get_current_user)],
)
def delete_article(id: int):
    return {"deleted": id}
```

## Built-in Roles

| Role     | Permissions                      |
|----------|----------------------------------|
| `admin`  | All (wildcard)                   |
| `editor` | `read`, `write`                  |
| `viewer` | `read`                           |

## User Object Contract

Your authentication dependency must return an object with a `.role` attribute:

```python
from dataclasses import dataclass

@dataclass
class User:
    id: int
    username: str
    role: str  # must match a registered role name
```

## Custom Roles

```python
rbac = RBAC()

# Add roles
rbac.add_role("moderator", ["read", "write", "delete"])
rbac.add_role("analyst", ["read", "export"])

# Check programmatically
rbac.check_permission("moderator", "delete")  # True
rbac.check_permission("analyst", "write")      # False

# List roles
rbac.roles  # ['admin', 'editor', 'viewer', 'moderator', 'analyst']

# Remove a role
rbac.remove_role("analyst")
```

## Using `request.state.user`

If you prefer middleware-based auth, `require_role` and `require_permission` can read the user from `request.state.user` automatically when no `get_user` dependency is provided:

```python
@app.middleware("http")
async def auth_middleware(request, call_next):
    request.state.user = authenticate(request)
    return await call_next(request)

# No get_user needed — reads from request.state.user
@app.get("/protected", dependencies=[require_role("admin")])
def protected():
    return {"ok": True}
```

## Permission Constants

Use the `Permission` class for cleaner code:

```python
from fastapi_rbac import Permission

rbac.add_role("support", [Permission.READ, Permission.WRITE])
rbac.check_permission("support", Permission.DELETE)  # False
```

## License

MIT License. See [LICENSE](LICENSE) for details.
