Skip to content

Commit 56f7906

Browse files
authored
Merge pull request #2 from Zxilly/master
feat: early implement of fastapi-authz
2 parents 3ae06b5 + f0a58a4 commit 56f7906

14 files changed

+371
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,7 @@ dmypy.json
127127

128128
# Pyre type checker
129129
.pyre/
130+
131+
.idea/
132+
133+
test/

dev-requirements.in

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fastapi
2+
casbin
3+
pytest
4+
pip-tools
5+
pytest-cov
6+
coverage
7+
pypi-publisher
8+
bumpversion
9+
uvicorn
10+
starlette-auth-toolkit
11+
requests

dev-requirements.txt

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
#
2+
# This file is autogenerated by pip-compile
3+
# To update, run:
4+
#
5+
# pip-compile dev-requirements.in
6+
#
7+
--index-url https://mirrors.aliyun.com/pypi/simple/
8+
9+
atomicwrites==1.4.0
10+
# via pytest
11+
attrs==20.3.0
12+
# via pytest
13+
bump2version==1.0.1
14+
# via bumpversion
15+
bumpversion==0.6.0
16+
# via -r dev-requirements.in
17+
casbin==0.18.1
18+
# via -r dev-requirements.in
19+
certifi==2020.12.5
20+
# via requests
21+
chardet==4.0.0
22+
# via requests
23+
click==7.1.2
24+
# via
25+
# pip-tools
26+
# uvicorn
27+
colorama==0.4.4
28+
# via pytest
29+
coverage==5.4
30+
# via
31+
# -r dev-requirements.in
32+
# pytest-cov
33+
fastapi==0.63.0
34+
# via -r dev-requirements.in
35+
gitdb==4.0.5
36+
# via gitpython
37+
gitpython==0.3.6
38+
# via pypi-publisher
39+
h11==0.12.0
40+
# via uvicorn
41+
idna==2.10
42+
# via requests
43+
iniconfig==1.1.1
44+
# via pytest
45+
packaging==20.9
46+
# via pytest
47+
pip-tools==5.5.0
48+
# via -r dev-requirements.in
49+
pluggy==0.13.1
50+
# via pytest
51+
py==1.10.0
52+
# via pytest
53+
pydantic==1.7.3
54+
# via fastapi
55+
pyparsing==2.4.7
56+
# via packaging
57+
pypi-publisher==0.0.4
58+
# via -r dev-requirements.in
59+
pytest-cov==2.11.1
60+
# via -r dev-requirements.in
61+
pytest==6.2.2
62+
# via
63+
# -r dev-requirements.in
64+
# pytest-cov
65+
requests==2.25.1
66+
# via -r dev-requirements.in
67+
simpleeval==0.9.10
68+
# via casbin
69+
smmap==3.0.5
70+
# via gitdb
71+
starlette-auth-toolkit==0.5.0
72+
# via -r dev-requirements.in
73+
starlette==0.13.6
74+
# via
75+
# fastapi
76+
# starlette-auth-toolkit
77+
toml==0.10.2
78+
# via pytest
79+
urllib3==1.26.3
80+
# via requests
81+
uvicorn==0.13.4
82+
# via -r dev-requirements.in
83+
84+
# The following packages are considered to be unsafe in a requirements file:
85+
# pip

examples/rbac_model.conf

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[request_definition]
2+
r = sub, obj, act
3+
4+
[policy_definition]
5+
p = sub, obj, act
6+
7+
[role_definition]
8+
g = _, _
9+
10+
[policy_effect]
11+
e = some(where (p.eft == allow))
12+
13+
[matchers]
14+
m = (p.sub == "*" || g(r.sub, p.sub)) && (r.obj == p.obj || keyMatch(r.obj, p.obj)) && (p.act == "*" || r.act == p.act)

examples/rbac_policy.csv

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
p, alice, /dataset1/*, GET
2+
p, alice, /dataset1/resource1, POST
3+
p, bob, /dataset2/resource1, *
4+
p, bob, /dataset2/resource2, GET
5+
p, bob, /dataset2/folder1/*, POST
6+
p, dataset1_admin, /dataset1/*, *
7+
p, *, /login, *
8+
9+
p, anonymous, /, GET
10+
11+
g, cathy, dataset1_admin

fastapi_authz/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .middleware import CasbinMiddleware

fastapi_authz/middleware.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from casbin.enforcer import Enforcer
2+
from starlette.authentication import BaseUser
3+
from starlette.requests import Request
4+
from starlette.responses import JSONResponse
5+
from starlette.status import HTTP_403_FORBIDDEN
6+
from starlette.types import ASGIApp, Receive, Scope, Send
7+
8+
9+
class CasbinMiddleware:
10+
"""
11+
Middleware for Casbin
12+
"""
13+
14+
def __init__(
15+
self,
16+
app: ASGIApp,
17+
enforcer: Enforcer,
18+
) -> None:
19+
"""
20+
Configure Casbin Middleware
21+
22+
:param app:Retain for ASGI.
23+
:param enforcer:Casbin Enforcer, must be initialized before FastAPI start.
24+
"""
25+
self.app = app
26+
self.enforcer = enforcer
27+
28+
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
29+
if scope["type"] not in ("http", "websocket"):
30+
await self.app(scope, receive, send)
31+
return
32+
33+
if self._enforce(scope, receive):
34+
await self.app(scope, receive, send)
35+
return
36+
else:
37+
response = JSONResponse(
38+
status_code=HTTP_403_FORBIDDEN,
39+
content="Forbidden"
40+
)
41+
42+
await response(scope, receive, send)
43+
return
44+
45+
def _enforce(self, scope: Scope, receive: Receive) -> bool:
46+
"""
47+
Enforce a request
48+
49+
:param user: user will be sent to enforcer
50+
:param request: ASGI Request
51+
:return: Enforce Result
52+
"""
53+
54+
request = Request(scope, receive)
55+
56+
path = request.url.path
57+
method = request.method
58+
if 'user' not in scope:
59+
raise RuntimeError("Casbin Middleware must work with an Authentication Middleware")
60+
61+
assert isinstance(request.user, BaseUser)
62+
63+
user = request.user.display_name if request.user.is_authenticated else 'anonymous'
64+
65+
print(user, path, method)
66+
67+
return self.enforcer.enforce(user, path, method)

requirements.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
fastapi
2+
casbin

requirements.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#
2+
# This file is autogenerated by pip-compile
3+
# To update, run:
4+
#
5+
# pip-compile requirements.in
6+
#
7+
8+
casbin==0.18.1
9+
# via -r requirements.in
10+
fastapi==0.63.0
11+
# via -r requirements.in
12+
pydantic==1.7.3
13+
# via fastapi
14+
simpleeval==0.9.10
15+
# via casbin
16+
starlette==0.13.6
17+
# via fastapi

setup.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[bdist_wheel]
2+
universal=1
3+
4+
[metadata]
5+
description-file=README.md

0 commit comments

Comments
 (0)