fastapi-rebac 0.1.0a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastapi_rebac-0.1.0a1/LICENSE +21 -0
- fastapi_rebac-0.1.0a1/PKG-INFO +398 -0
- fastapi_rebac-0.1.0a1/README.md +322 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/__init__.py +24 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/__version__.py +12 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/access.py +236 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/__init__.py +3 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/api.py +30 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/auth_tables.py +55 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/groups.py +657 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/login.py +259 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/redirects.py +69 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/resources.py +395 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/router.py +30 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/suspicious_alerts.py +59 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/users.py +874 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/admin/utils.py +918 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/anomaly/__init__.py +36 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/anomaly/config.py +31 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/anomaly/feature_builder.py +261 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/anomaly/pyod_detector.py +144 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/anomaly/rules.py +218 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/anomaly/service.py +235 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/auth.py +125 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/csrf.py +86 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/db/__init__.py +10 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/db/adapters.py +51 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/db/base.py +45 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/enums.py +27 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/errors.py +7 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/fastapi_rebac.py +894 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/integrations/__init__.py +3 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/integrations/yandex_2fa/__init__.py +25 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/integrations/yandex_2fa/admin.py +226 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/integrations/yandex_2fa/config.py +26 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/integrations/yandex_2fa/models.py +55 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/integrations/yandex_2fa/router.py +228 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/integrations/yandex_2fa/schemas.py +39 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/integrations/yandex_2fa/service.py +352 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/managers/__init__.py +11 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/managers/access_manager.py +503 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/managers/audit_manager.py +208 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/managers/user_manager.py +149 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/models/__init__.py +20 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/models/audit_log.py +35 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/models/auth_table.py +33 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/models/group.py +46 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/models/group_membership.py +38 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/models/group_permission.py +48 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/models/suspicious_alert.py +66 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/models/user.py +137 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/models/user_permission.py +46 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/py.typed +0 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/schemas.py +248 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/static/rebac_admin/css/rebac_admin.css +813 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/static/rebac_admin/js/rebac_admin.js +189 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/auth_tables.html +41 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/base.html +85 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/group_delete.html +19 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/group_detail.html +211 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/group_form.html +30 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/groups.html +57 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/index.html +28 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/login.html +38 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/resource_delete.html +33 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/resource_detail.html +38 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/resource_form.html +75 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/resource_list.html +86 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/resources.html +36 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/user_create.html +82 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/user_delete.html +19 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/user_detail.html +228 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/user_edit.html +77 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/user_password.html +25 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/templates/rebac_admin/users.html +71 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac/types.py +230 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac.egg-info/PKG-INFO +398 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac.egg-info/SOURCES.txt +81 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac.egg-info/dependency_links.txt +1 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac.egg-info/requires.txt +52 -0
- fastapi_rebac-0.1.0a1/fastapi_rebac.egg-info/top_level.txt +1 -0
- fastapi_rebac-0.1.0a1/pyproject.toml +144 -0
- fastapi_rebac-0.1.0a1/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ldokov Roman
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fastapi-rebac
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: RBAC/ReBAC authorization helpers, audit logging, suspicious activity detection, and admin UI for FastAPI applications.
|
|
5
|
+
Author-email: Ldokov Roman <ldokovroma@gmail.com>
|
|
6
|
+
Maintainer-email: Ldokov Roman <ldokovroma@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/lra-itsolution/fastapi-rebac/
|
|
9
|
+
Project-URL: Repository, https://github.com/lra-itsolution/fastapi-rebac/
|
|
10
|
+
Project-URL: Issues, https://github.com/lra-itsolution/fastapi-rebac/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/lra-itsolution/fastapi-rebac/blob/main/CHANGELOG.md
|
|
12
|
+
Keywords: fastapi,fastapi-users,sqlalchemy,rbac,rebac,authorization,access-control,audit-log,security
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Environment :: Web Environment
|
|
15
|
+
Classifier: Framework :: AsyncIO
|
|
16
|
+
Classifier: Framework :: FastAPI
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
25
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: HTTP Servers
|
|
26
|
+
Classifier: Topic :: Security
|
|
27
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
28
|
+
Classifier: Typing :: Typed
|
|
29
|
+
Requires-Python: >=3.10
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Requires-Dist: fastapi<1.0,>=0.110
|
|
33
|
+
Requires-Dist: fastapi-users[sqlalchemy]<16.0,>=14.0
|
|
34
|
+
Requires-Dist: SQLAlchemy<3.0,>=2.0
|
|
35
|
+
Requires-Dist: pydantic<3.0,>=2.0
|
|
36
|
+
Requires-Dist: jinja2<4.0,>=3.1
|
|
37
|
+
Requires-Dist: python-multipart<1.0,>=0.0.9
|
|
38
|
+
Requires-Dist: email-validator<3.0,>=2.0
|
|
39
|
+
Requires-Dist: greenlet<4.0,>=3.0
|
|
40
|
+
Provides-Extra: anomaly
|
|
41
|
+
Requires-Dist: pyod<4.0,>=2.0; extra == "anomaly"
|
|
42
|
+
Provides-Extra: postgres
|
|
43
|
+
Requires-Dist: asyncpg<1.0,>=0.29; extra == "postgres"
|
|
44
|
+
Requires-Dist: alembic<2.0,>=1.13; extra == "postgres"
|
|
45
|
+
Provides-Extra: yandex
|
|
46
|
+
Requires-Dist: httpx<1.0,>=0.27; extra == "yandex"
|
|
47
|
+
Provides-Extra: example
|
|
48
|
+
Requires-Dist: asyncpg<1.0,>=0.29; extra == "example"
|
|
49
|
+
Requires-Dist: alembic<2.0,>=1.13; extra == "example"
|
|
50
|
+
Requires-Dist: python-dotenv<2.0,>=1.0; extra == "example"
|
|
51
|
+
Requires-Dist: uvicorn[standard]<1.0,>=0.27; extra == "example"
|
|
52
|
+
Provides-Extra: test
|
|
53
|
+
Requires-Dist: pytest<9.0,>=8.0; extra == "test"
|
|
54
|
+
Requires-Dist: pytest-asyncio<1.0,>=0.23; extra == "test"
|
|
55
|
+
Requires-Dist: httpx<1.0,>=0.27; extra == "test"
|
|
56
|
+
Provides-Extra: lint
|
|
57
|
+
Requires-Dist: ruff<1.0,>=0.6; extra == "lint"
|
|
58
|
+
Requires-Dist: mypy<2.0,>=1.8; extra == "lint"
|
|
59
|
+
Provides-Extra: release
|
|
60
|
+
Requires-Dist: build<2.0,>=1.2; extra == "release"
|
|
61
|
+
Requires-Dist: twine<7.0,>=5.0; extra == "release"
|
|
62
|
+
Provides-Extra: dev
|
|
63
|
+
Requires-Dist: pytest<9.0,>=8.0; extra == "dev"
|
|
64
|
+
Requires-Dist: pytest-asyncio<1.0,>=0.23; extra == "dev"
|
|
65
|
+
Requires-Dist: httpx<1.0,>=0.27; extra == "dev"
|
|
66
|
+
Requires-Dist: ruff<1.0,>=0.6; extra == "dev"
|
|
67
|
+
Requires-Dist: mypy<2.0,>=1.8; extra == "dev"
|
|
68
|
+
Requires-Dist: build<2.0,>=1.2; extra == "dev"
|
|
69
|
+
Requires-Dist: twine<7.0,>=5.0; extra == "dev"
|
|
70
|
+
Provides-Extra: all
|
|
71
|
+
Requires-Dist: asyncpg<1.0,>=0.29; extra == "all"
|
|
72
|
+
Requires-Dist: alembic<2.0,>=1.13; extra == "all"
|
|
73
|
+
Requires-Dist: httpx<1.0,>=0.27; extra == "all"
|
|
74
|
+
Requires-Dist: pyod<4.0,>=2.0; extra == "all"
|
|
75
|
+
Dynamic: license-file
|
|
76
|
+
|
|
77
|
+
# fastapi-rebac
|
|
78
|
+
|
|
79
|
+
`fastapi-rebac` is an alpha-stage FastAPI extension for relationship-based and role-aware access control. It combines FastAPI dependencies, FastAPI Users authentication, SQLAlchemy 2.0 models, a bundled HTML admin panel, audit logging, optional suspicious-activity detection, and optional Yandex ID two-factor authentication.
|
|
80
|
+
|
|
81
|
+
The library is designed for applications where access cannot be described by simple roles only. It supports direct user permissions, group permissions, user hierarchies, object-level checks, and SQLAlchemy query filtering for objects visible to the current user.
|
|
82
|
+
|
|
83
|
+
> Status: alpha. The public API is usable, but database schema and integration APIs may still change before a stable `1.0` release.
|
|
84
|
+
|
|
85
|
+
## Features
|
|
86
|
+
|
|
87
|
+
- FastAPI dependency helpers for authenticated users, staff users, superusers, table-level permissions, object-level permissions, and accessible SQLAlchemy `select()` statements.
|
|
88
|
+
- SQLAlchemy 2.0 models for users, groups, group membership, registered protected tables, user permissions, group permissions, audit logs, and suspicious alerts.
|
|
89
|
+
- Integration layer around FastAPI Users for JWT bearer and cookie authentication backends.
|
|
90
|
+
- Relationship-aware visibility based on `created_by_id`, `supervisor_id`, and configurable group visibility flags.
|
|
91
|
+
- Bundled admin UI for users, groups, permissions, registered tables, audit logs, and suspicious alerts.
|
|
92
|
+
- Optional audit logging for security-relevant operations.
|
|
93
|
+
- Optional suspicious-activity detection with rule-based checks and PyOD ECOD outlier detection.
|
|
94
|
+
- Optional Yandex ID second-factor integration for API login and admin login flows.
|
|
95
|
+
|
|
96
|
+
## Installation
|
|
97
|
+
|
|
98
|
+
Core package:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
pip install fastapi-rebac
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
PostgreSQL and Alembic support for production-style applications:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
pip install "fastapi-rebac[postgres]"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Optional suspicious-activity detection:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pip install "fastapi-rebac[anomaly]"
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Optional Yandex ID two-factor authentication:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
pip install "fastapi-rebac[yandex]"
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Everything optional:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
pip install "fastapi-rebac[all]"
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Requirements
|
|
129
|
+
|
|
130
|
+
- Python 3.10+
|
|
131
|
+
- FastAPI
|
|
132
|
+
- FastAPI Users with SQLAlchemy support
|
|
133
|
+
- SQLAlchemy 2.0+
|
|
134
|
+
- Pydantic 2+
|
|
135
|
+
- Jinja2 and `python-multipart` for the bundled admin UI
|
|
136
|
+
|
|
137
|
+
The package is database-driver agnostic. Install a driver that matches your application database, for example `asyncpg` for PostgreSQL.
|
|
138
|
+
|
|
139
|
+
## Quick start
|
|
140
|
+
|
|
141
|
+
The example below shows the minimal integration shape. Real applications should keep configuration values in environment variables and create Alembic migrations for the ReBAC tables.
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
from collections.abc import AsyncGenerator
|
|
145
|
+
|
|
146
|
+
from fastapi import Depends, FastAPI
|
|
147
|
+
from fastapi_users.db import SQLAlchemyUserDatabase
|
|
148
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
149
|
+
|
|
150
|
+
from fastapi_rebac import Action, FastAPIReBAC
|
|
151
|
+
from fastapi_rebac.auth import build_bearer_backend, build_get_user_manager
|
|
152
|
+
from fastapi_rebac.managers import ReBACUserManager
|
|
153
|
+
from fastapi_rebac.models import User
|
|
154
|
+
|
|
155
|
+
app = FastAPI()
|
|
156
|
+
|
|
157
|
+
async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
|
|
158
|
+
# yield your SQLAlchemy AsyncSession here
|
|
159
|
+
...
|
|
160
|
+
|
|
161
|
+
async def get_user_db(
|
|
162
|
+
session: AsyncSession = Depends(get_async_session),
|
|
163
|
+
) -> AsyncGenerator[SQLAlchemyUserDatabase[User, str], None]:
|
|
164
|
+
yield SQLAlchemyUserDatabase(session, User)
|
|
165
|
+
|
|
166
|
+
class UserManager(ReBACUserManager[User]):
|
|
167
|
+
reset_password_token_secret = "change-me"
|
|
168
|
+
verification_token_secret = "change-me"
|
|
169
|
+
|
|
170
|
+
get_user_manager = build_get_user_manager(UserManager, get_user_db)
|
|
171
|
+
auth_backend = build_bearer_backend(secret="change-me")
|
|
172
|
+
|
|
173
|
+
rebac = FastAPIReBAC(
|
|
174
|
+
get_user_manager,
|
|
175
|
+
[auth_backend],
|
|
176
|
+
get_async_session=get_async_session,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
app.include_router(rebac.get_auth_router(), prefix="/auth/jwt", tags=["auth"])
|
|
180
|
+
rebac.mount_admin(app, prefix="/admin")
|
|
181
|
+
|
|
182
|
+
@app.get("/protected")
|
|
183
|
+
async def protected_route(user: User = Depends(rebac.auth_required)):
|
|
184
|
+
return {"user_id": str(user.id)}
|
|
185
|
+
|
|
186
|
+
@app.post("/notes", dependencies=[Depends(rebac.require(Action.CREATE, "note"))])
|
|
187
|
+
async def create_note():
|
|
188
|
+
return {"status": "allowed"}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Registering protected entities
|
|
192
|
+
|
|
193
|
+
`fastapi-rebac` stores protected entities in the `auth_table` table. Registered models are synchronized through the `FastAPIReBAC.sync_auth_tables()` helper.
|
|
194
|
+
|
|
195
|
+
```python
|
|
196
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
197
|
+
|
|
198
|
+
from my_app.models import Note
|
|
199
|
+
|
|
200
|
+
rebac.register_admin_model(
|
|
201
|
+
Note,
|
|
202
|
+
title="Notes",
|
|
203
|
+
user_ref_attr=Note.created_by_id,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
async def sync_rebac_tables(session: AsyncSession) -> None:
|
|
207
|
+
await rebac.sync_auth_tables(session)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
After synchronization, administrators can grant `CREATE`, `READ`, `UPDATE`, and `DELETE` permissions for the registered entity.
|
|
211
|
+
|
|
212
|
+
## Object-level access
|
|
213
|
+
|
|
214
|
+
For owned resources, pass a SQLAlchemy mapped user reference attribute. The access manager will build SQL that restricts data to the current user's visible user graph.
|
|
215
|
+
|
|
216
|
+
```python
|
|
217
|
+
from fastapi import Depends
|
|
218
|
+
from sqlalchemy import select
|
|
219
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
220
|
+
|
|
221
|
+
from fastapi_rebac import Action
|
|
222
|
+
from my_app.models import Note
|
|
223
|
+
|
|
224
|
+
@app.get("/notes")
|
|
225
|
+
async def list_notes(
|
|
226
|
+
stmt = Depends(rebac.accessible_select(Note.created_by_id)),
|
|
227
|
+
session: AsyncSession = Depends(rebac.session_dependency),
|
|
228
|
+
):
|
|
229
|
+
result = await session.execute(stmt.order_by(Note.created_at.desc()))
|
|
230
|
+
return result.scalars().all()
|
|
231
|
+
|
|
232
|
+
@app.get("/notes/{note_id}")
|
|
233
|
+
async def get_note(
|
|
234
|
+
note = Depends(rebac.require_object(Action.READ, Note.created_by_id, object_id_param="note_id")),
|
|
235
|
+
):
|
|
236
|
+
return note
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Admin UI
|
|
240
|
+
|
|
241
|
+
The bundled admin UI is mounted on a FastAPI app with:
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
rebac.mount_admin(app, prefix="/admin")
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
It includes pages for:
|
|
248
|
+
|
|
249
|
+
- users;
|
|
250
|
+
- groups and memberships;
|
|
251
|
+
- protected tables;
|
|
252
|
+
- user permissions;
|
|
253
|
+
- group permissions;
|
|
254
|
+
- audit logs;
|
|
255
|
+
- suspicious alerts.
|
|
256
|
+
|
|
257
|
+
The UI uses package templates and static assets from `fastapi_rebac/templates` and `fastapi_rebac/static`, so keep package data enabled when building distributions.
|
|
258
|
+
|
|
259
|
+
## Audit logging
|
|
260
|
+
|
|
261
|
+
Audit logging is enabled by default in `FastAPIReBAC`. Use the audit manager when application code performs security-relevant actions:
|
|
262
|
+
|
|
263
|
+
```python
|
|
264
|
+
audit = rebac.get_audit_manager(session)
|
|
265
|
+
await audit.log_success(
|
|
266
|
+
actor_id=user.id,
|
|
267
|
+
action=Action.UPDATE,
|
|
268
|
+
table_key="note",
|
|
269
|
+
object_id=str(note.id),
|
|
270
|
+
)
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Audit events can be used for incident analysis and for suspicious-activity detection.
|
|
274
|
+
|
|
275
|
+
## Suspicious-activity detection
|
|
276
|
+
|
|
277
|
+
Install the optional extra:
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
pip install "fastapi-rebac[anomaly]"
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Configure detection:
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from fastapi_rebac import FastAPIReBAC
|
|
287
|
+
from fastapi_rebac.anomaly import SuspiciousActivityConfig
|
|
288
|
+
|
|
289
|
+
rebac = FastAPIReBAC(
|
|
290
|
+
get_user_manager,
|
|
291
|
+
[auth_backend],
|
|
292
|
+
get_async_session=get_async_session,
|
|
293
|
+
suspicious_activity_config=SuspiciousActivityConfig(
|
|
294
|
+
enabled=True,
|
|
295
|
+
rules_enabled=True,
|
|
296
|
+
pyod_enabled=True,
|
|
297
|
+
window_minutes=60,
|
|
298
|
+
),
|
|
299
|
+
)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Run detection manually or from the admin UI:
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
from fastapi_rebac.anomaly import run_suspicious_activity_detection
|
|
306
|
+
|
|
307
|
+
alerts = await run_suspicious_activity_detection(
|
|
308
|
+
session,
|
|
309
|
+
config=rebac.suspicious_activity_config,
|
|
310
|
+
)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Rule-based detection works without PyOD. PyOD is imported lazily and is required only when `pyod_enabled=True`.
|
|
314
|
+
|
|
315
|
+
## Yandex ID two-factor authentication
|
|
316
|
+
|
|
317
|
+
Install the optional extra:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
pip install "fastapi-rebac[yandex]"
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
Then include the Yandex 2FA router instead of exposing a direct login route for users that must pass the second factor:
|
|
324
|
+
|
|
325
|
+
```python
|
|
326
|
+
from fastapi_rebac.integrations.yandex_2fa import Yandex2FAConfig, get_yandex_2fa_router
|
|
327
|
+
|
|
328
|
+
config = Yandex2FAConfig(
|
|
329
|
+
client_id="...",
|
|
330
|
+
client_secret="...",
|
|
331
|
+
redirect_uri="http://127.0.0.1:8000/auth/yandex-2fa/callback",
|
|
332
|
+
link_redirect_uri="http://127.0.0.1:8000/auth/yandex-2fa/link/callback",
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
app.include_router(
|
|
336
|
+
get_yandex_2fa_router(rebac, config),
|
|
337
|
+
prefix="/auth/yandex-2fa",
|
|
338
|
+
tags=["auth"],
|
|
339
|
+
)
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
Do not expose a separate direct JWT login route for accounts that must use Yandex 2FA; otherwise the second factor can be bypassed.
|
|
343
|
+
|
|
344
|
+
## Examples
|
|
345
|
+
|
|
346
|
+
The repository contains two runnable examples:
|
|
347
|
+
|
|
348
|
+
- `example_app` — PostgreSQL example with JWT authentication, notes, admin UI, Alembic migrations, audit, and suspicious alerts.
|
|
349
|
+
- `example_yandex_2fa_app` — Yandex ID two-factor authentication example.
|
|
350
|
+
|
|
351
|
+
Typical local setup:
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
python -m venv .venv
|
|
355
|
+
source .venv/bin/activate
|
|
356
|
+
python -m pip install --upgrade pip
|
|
357
|
+
pip install -e ".[example,anomaly,yandex]"
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Then follow the README inside the selected example directory.
|
|
361
|
+
|
|
362
|
+
## Building and publishing
|
|
363
|
+
|
|
364
|
+
Build locally:
|
|
365
|
+
|
|
366
|
+
```bash
|
|
367
|
+
python -m pip install --upgrade build twine
|
|
368
|
+
python -m build
|
|
369
|
+
python -m twine check dist/*
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Publish to TestPyPI:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
python -m twine upload --repository testpypi dist/*
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Publish to PyPI:
|
|
379
|
+
|
|
380
|
+
```bash
|
|
381
|
+
python -m twine upload dist/*
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
For GitHub Actions, prefer PyPI Trusted Publishing and the included `publish.yml` workflow.
|
|
385
|
+
|
|
386
|
+
## Development
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
python -m pip install -e ".[dev,all]"
|
|
390
|
+
python -m ruff check .
|
|
391
|
+
python -m pytest
|
|
392
|
+
python -m build
|
|
393
|
+
python -m twine check dist/*
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
## License
|
|
397
|
+
|
|
398
|
+
MIT License. See [LICENSE](LICENSE).
|