zrb 0.0.52__py3-none-any.whl → 0.0.53__py3-none-any.whl
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.
- zrb/builtin/generator/fastapp/template/_automate/snake_app_name/cmd/start.sh +1 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/.gitignore +1 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/config.py +14 -5
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/.env.local +4 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/.gitignore +1 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/README.md +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/package-lock.json +16 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/package.json +2 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/playwright.config.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/postcss.config.js +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/app.css +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/app.d.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/app.html +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/index.test.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/helper.ts +146 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/store.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/type.ts +3 -3
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/Menu.svelte +19 -16
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/Navigation.svelte +14 -11
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/helper.ts +18 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/type.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/config/app.ts +9 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/config/navData.ts +6 -17
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/error/helper.ts +12 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+error.svelte +8 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+layout.js +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+layout.svelte +4 -3
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+page.svelte +2 -8
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/static/favicon.png +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/static/logo.png +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/svelte.config.js +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/tailwind.config.js +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/tests/test.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/tsconfig.json +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/vite.config.ts +0 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/__init__.py +8 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/access_token_scheme.py +14 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/access_token_util.py +17 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/bearer_token_scheme.py +5 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/model/user_model.py +9 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/refresh_token_util.py +17 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/__init__.py +14 -9
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_scheme/oauth2_bearer_token_scheme.py → access_token/scheme.py} +11 -11
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/access_token/util.py +69 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/authorizer/rpc_authorizer.py +4 -2
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_util/jwt_token_util.py → refresh_token/util.py} +18 -6
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/group/api.py +9 -7
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/group/rpc.py +4 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/permission/api.py +9 -7
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/permission/rpc.py +4 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/api.py +25 -15
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/model.py +44 -19
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/rpc.py +19 -11
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/schema/request.py +2 -2
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/schema/token.py +7 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/requirements.txt +1 -0
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/template.env +7 -3
- zrb/builtin/generator/fastapp_crud/add.py +7 -21
- zrb/builtin/generator/fastapp_crud/add_navigation.py +32 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/+page.svelte +121 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/delete/[id]/+page.svelte +75 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/delete/[id]/+page.ts +5 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/detail/[id]/+page.svelte +54 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/detail/[id]/+page.ts +5 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/new/+page.svelte +52 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/update/[id]/+page.svelte +78 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/update/[id]/+page.ts +5 -0
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/module/snake_module_name/entity/snake_entity_name/api.py +9 -7
- zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/module/snake_module_name/entity/snake_entity_name/rpc.py +4 -4
- zrb/builtin/generator/fastapp_field/add.py +203 -4
- zrb/builtin/generator/project/template/.gitignore +1 -1
- zrb/builtin/generator/simple_python_app/template/src/kebab-app-name/src/.gitignore +1 -1
- zrb/helper/util.py +4 -0
- zrb/task/resource_maker.py +2 -1
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/METADATA +3 -3
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/RECORD +64 -56
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/auth.ts +0 -83
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/config/config.ts +0 -4
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/cookie/cookie.ts +0 -19
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/about/+page.svelte +0 -2
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/greetings/[slug]/+page.js +0 -6
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/greetings/[slug]/+page.svelte +0 -5
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/sample/+page.svelte +0 -37
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/sample/delete/[id]/+page.svelte +0 -1
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/token_scheme.py +0 -11
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/token_util.py +0 -17
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/token_scheme/token_sheme.py +0 -5
- zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/token_util/token_util.py +0 -13
- /zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_scheme/__init__.py → access_token/_init_.py} +0 -0
- /zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_util/__init__.py → refresh_token/_init_.py} +0 -0
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/LICENSE +0 -0
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/WHEEL +0 -0
- {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
from config import (
|
2
|
+
app_auth_refresh_token_type, app_auth_jwt_token_algorithm,
|
3
|
+
app_auth_jwt_token_secret_key
|
4
|
+
)
|
5
|
+
from module.auth.core import RefreshTokenUtil, JWTRefreshTokenUtil
|
6
|
+
|
7
|
+
|
8
|
+
def init_token_util() -> RefreshTokenUtil:
|
9
|
+
if app_auth_refresh_token_type.lower() == 'jwt':
|
10
|
+
return JWTRefreshTokenUtil(
|
11
|
+
secret_key=app_auth_jwt_token_secret_key,
|
12
|
+
algorithm=app_auth_jwt_token_algorithm
|
13
|
+
)
|
14
|
+
raise ValueError(f'Invalid auth token type: {app_auth_refresh_token_type}')
|
15
|
+
|
16
|
+
|
17
|
+
refresh_token_util = init_token_util()
|
@@ -4,18 +4,23 @@ from module.auth.core.password_hasher.password_hasher import PasswordHasher
|
|
4
4
|
from module.auth.core.password_hasher.bcrypt_password_hasher import (
|
5
5
|
BcryptPasswordHasher
|
6
6
|
)
|
7
|
-
from module.auth.core.
|
8
|
-
|
9
|
-
|
7
|
+
from module.auth.core.access_token.scheme import (
|
8
|
+
AccessTokenScheme, create_oauth2_bearer_access_token_scheme
|
9
|
+
)
|
10
|
+
from module.auth.core.access_token.util import (
|
11
|
+
AccessTokenUtil, JWTAccessTokenUtil
|
12
|
+
)
|
13
|
+
from module.auth.core.refresh_token.util import (
|
14
|
+
RefreshTokenUtil, JWTRefreshTokenUtil
|
10
15
|
)
|
11
|
-
from module.auth.core.token_util.token_util import TokenUtil
|
12
|
-
from module.auth.core.token_util.jwt_token_util import JWTTokenUtil
|
13
16
|
|
14
17
|
assert Authorizer
|
15
18
|
assert RPCAuthorizer
|
16
19
|
assert PasswordHasher
|
17
20
|
assert BcryptPasswordHasher
|
18
|
-
assert
|
19
|
-
assert
|
20
|
-
assert
|
21
|
-
assert
|
21
|
+
assert AccessTokenScheme
|
22
|
+
assert create_oauth2_bearer_access_token_scheme
|
23
|
+
assert AccessTokenUtil
|
24
|
+
assert JWTAccessTokenUtil
|
25
|
+
assert RefreshTokenUtil
|
26
|
+
assert JWTRefreshTokenUtil
|
@@ -1,19 +1,20 @@
|
|
1
|
-
from typing import Optional
|
1
|
+
from typing import Callable, Optional
|
2
2
|
from starlette.requests import Request
|
3
3
|
from fastapi import Depends
|
4
4
|
from fastapi.security import OAuth2PasswordBearer
|
5
|
-
from module.auth.
|
6
|
-
from module.auth.core.token_scheme.token_sheme import TokenScheme
|
7
|
-
from module.auth.schema.token import TokenData
|
5
|
+
from module.auth.schema.token import AccessTokenData
|
8
6
|
from module.auth.schema.user import User
|
7
|
+
from module.auth.core.access_token.util import AccessTokenUtil
|
9
8
|
|
9
|
+
AccessTokenScheme = Callable[[Request], AccessTokenData]
|
10
10
|
|
11
|
-
|
11
|
+
|
12
|
+
def create_oauth2_bearer_access_token_scheme(
|
12
13
|
guest_user: User,
|
13
|
-
|
14
|
+
access_token_util: AccessTokenUtil,
|
14
15
|
token_url: str,
|
15
16
|
token_cookie_key: str
|
16
|
-
) ->
|
17
|
+
) -> AccessTokenScheme:
|
17
18
|
|
18
19
|
oauth2_scheme = OAuth2PasswordBearer(
|
19
20
|
tokenUrl=token_url, auto_error=False
|
@@ -22,17 +23,16 @@ def create_oauth2_bearer_token_scheme(
|
|
22
23
|
async def oauth2_bearer_token_scheme(
|
23
24
|
request: Request,
|
24
25
|
token: Optional[str] = Depends(oauth2_scheme)
|
25
|
-
) ->
|
26
|
+
) -> AccessTokenData:
|
26
27
|
token: Optional[str] = await oauth2_scheme(request)
|
27
28
|
if token is None:
|
28
29
|
request.cookies.get(token_cookie_key, None)
|
29
30
|
if token is None:
|
30
|
-
return
|
31
|
+
return AccessTokenData(
|
31
32
|
user_id=guest_user.id,
|
32
33
|
username=guest_user.username,
|
33
|
-
permission_names=[],
|
34
34
|
expire_seconds=300
|
35
35
|
)
|
36
|
-
return
|
36
|
+
return access_token_util.decode(token, parse_expired_token=False)
|
37
37
|
|
38
38
|
return oauth2_bearer_token_scheme
|
zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/access_token/util.py
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
from typing import Any, Mapping
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
from core.error import HTTPAPIException
|
4
|
+
from module.auth.schema.token import AccessTokenData
|
5
|
+
from datetime import datetime, timedelta
|
6
|
+
from jose import jwt
|
7
|
+
|
8
|
+
import jsons
|
9
|
+
|
10
|
+
|
11
|
+
class AccessTokenUtil(ABC):
|
12
|
+
|
13
|
+
@abstractmethod
|
14
|
+
def encode(self, token_data: AccessTokenData) -> str:
|
15
|
+
pass
|
16
|
+
|
17
|
+
@abstractmethod
|
18
|
+
def decode(
|
19
|
+
self, token_str: str, parse_expired_token: bool = False
|
20
|
+
) -> AccessTokenData:
|
21
|
+
pass
|
22
|
+
|
23
|
+
|
24
|
+
class JWTAccessTokenUtil(AccessTokenUtil):
|
25
|
+
|
26
|
+
def __init__(self, secret_key: str, algorithm: str = 'HS256'):
|
27
|
+
self.secret_key = secret_key
|
28
|
+
self.algorithm = algorithm
|
29
|
+
|
30
|
+
def encode(self, data: AccessTokenData) -> str:
|
31
|
+
expire_time = datetime.utcnow() + timedelta(
|
32
|
+
seconds=data.expire_seconds
|
33
|
+
)
|
34
|
+
sub = jsons.dumps(data.dict())
|
35
|
+
data_dict = {'sub': sub, 'exp': expire_time}
|
36
|
+
encoded_jwt = jwt.encode(
|
37
|
+
data_dict, self.secret_key, algorithm=self.algorithm
|
38
|
+
)
|
39
|
+
return encoded_jwt
|
40
|
+
|
41
|
+
def decode(
|
42
|
+
self, token: str, parse_expired_token: bool = False
|
43
|
+
) -> AccessTokenData:
|
44
|
+
try:
|
45
|
+
decoded_data = jwt.decode(
|
46
|
+
token,
|
47
|
+
self.secret_key,
|
48
|
+
algorithms=[self.algorithm],
|
49
|
+
options=self._get_decode_options(parse_expired_token)
|
50
|
+
)
|
51
|
+
sub = jsons.loads(decoded_data['sub'])
|
52
|
+
token_data = AccessTokenData.parse_obj(sub)
|
53
|
+
if not parse_expired_token:
|
54
|
+
expire_time = decoded_data['exp']
|
55
|
+
token_data.expire_seconds = ((
|
56
|
+
datetime.fromtimestamp(expire_time) - datetime.utcnow()
|
57
|
+
).total_seconds())
|
58
|
+
if token_data.expire_seconds < 0:
|
59
|
+
raise HTTPAPIException(422, 'Expired token')
|
60
|
+
return token_data
|
61
|
+
except jwt.JWTError:
|
62
|
+
raise HTTPAPIException(422, 'Invalid token')
|
63
|
+
|
64
|
+
def _get_decode_options(
|
65
|
+
self, parse_expired_token: bool
|
66
|
+
) -> Mapping[str, Any]:
|
67
|
+
if parse_expired_token:
|
68
|
+
return {'verify_exp': False}
|
69
|
+
return {}
|
@@ -27,10 +27,12 @@ class RPCAuthorizer(Authorizer):
|
|
27
27
|
)
|
28
28
|
|
29
29
|
async def is_having_permission(
|
30
|
-
self, user_id: str, *
|
30
|
+
self, user_id: str, *permission_name: str
|
31
31
|
) -> bool:
|
32
32
|
permission_map = await self.rpc_caller.call(
|
33
|
-
self.is_user_authorized_rpc_name,
|
33
|
+
self.is_user_authorized_rpc_name,
|
34
|
+
id=user_id,
|
35
|
+
permission_name=permission_name
|
34
36
|
)
|
35
37
|
for permission in permission_map:
|
36
38
|
if not permission_map[permission]:
|
@@ -1,18 +1,30 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
1
2
|
from core.error import HTTPAPIException
|
2
|
-
from module.auth.schema.token import
|
3
|
-
from module.auth.core.token_util.token_util import TokenUtil
|
3
|
+
from module.auth.schema.token import RefreshTokenData
|
4
4
|
from datetime import datetime, timedelta
|
5
5
|
from jose import jwt
|
6
|
+
|
6
7
|
import jsons
|
7
8
|
|
8
9
|
|
9
|
-
class
|
10
|
+
class RefreshTokenUtil(ABC):
|
11
|
+
|
12
|
+
@abstractmethod
|
13
|
+
def encode(self, token_data: RefreshTokenData) -> str:
|
14
|
+
pass
|
15
|
+
|
16
|
+
@abstractmethod
|
17
|
+
def decode(self, token_str: str) -> RefreshTokenData:
|
18
|
+
pass
|
19
|
+
|
20
|
+
|
21
|
+
class JWTRefreshTokenUtil(RefreshTokenUtil):
|
10
22
|
|
11
23
|
def __init__(self, secret_key: str, algorithm: str = 'HS256'):
|
12
24
|
self.secret_key = secret_key
|
13
25
|
self.algorithm = algorithm
|
14
26
|
|
15
|
-
def encode(self, data:
|
27
|
+
def encode(self, data: RefreshTokenData) -> str:
|
16
28
|
expire_time = datetime.utcnow() + timedelta(
|
17
29
|
seconds=data.expire_seconds
|
18
30
|
)
|
@@ -23,13 +35,13 @@ class JWTTokenUtil(TokenUtil):
|
|
23
35
|
)
|
24
36
|
return encoded_jwt
|
25
37
|
|
26
|
-
def decode(self, token: str) ->
|
38
|
+
def decode(self, token: str) -> RefreshTokenData:
|
27
39
|
try:
|
28
40
|
decoded_data = jwt.decode(
|
29
41
|
token, self.secret_key, algorithms=[self.algorithm]
|
30
42
|
)
|
31
43
|
sub = jsons.loads(decoded_data['sub'])
|
32
|
-
token_data =
|
44
|
+
token_data = RefreshTokenData.parse_obj(sub)
|
33
45
|
expire_time = decoded_data['exp']
|
34
46
|
token_data.expire_seconds = ((
|
35
47
|
datetime.fromtimestamp(expire_time) - datetime.utcnow()
|
zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/group/api.py
CHANGED
@@ -7,8 +7,8 @@ from module.auth.core import Authorizer
|
|
7
7
|
from module.auth.schema.group import (
|
8
8
|
Group, GroupData, GroupResult
|
9
9
|
)
|
10
|
-
from module.auth.schema.token import
|
11
|
-
from module.auth.component import
|
10
|
+
from module.auth.schema.token import AccessTokenData
|
11
|
+
from module.auth.component import access_token_scheme
|
12
12
|
|
13
13
|
|
14
14
|
def register_api(
|
@@ -25,7 +25,7 @@ def register_api(
|
|
25
25
|
)
|
26
26
|
async def get_groups(
|
27
27
|
keyword: str = '', limit: int = 100, offset: int = 0,
|
28
|
-
user_token_data:
|
28
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme),
|
29
29
|
):
|
30
30
|
if not await authorizer.is_having_permission(
|
31
31
|
user_token_data.user_id, 'auth:permission:get'
|
@@ -48,7 +48,7 @@ def register_api(
|
|
48
48
|
'/api/v1/auth/groups/{id}', response_model=Group
|
49
49
|
)
|
50
50
|
async def get_group_by_id(
|
51
|
-
id: str, user_token_data:
|
51
|
+
id: str, user_token_data: AccessTokenData = Depends(access_token_scheme)
|
52
52
|
):
|
53
53
|
if not await authorizer.is_having_permission(
|
54
54
|
user_token_data.user_id, 'auth:group:get_by_id'
|
@@ -67,7 +67,8 @@ def register_api(
|
|
67
67
|
'/api/v1/auth/groups', response_model=Group
|
68
68
|
)
|
69
69
|
async def insert_group(
|
70
|
-
data: GroupData,
|
70
|
+
data: GroupData,
|
71
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
71
72
|
):
|
72
73
|
if not await authorizer.is_having_permission(
|
73
74
|
user_token_data.user_id, 'auth:group:insert'
|
@@ -87,7 +88,7 @@ def register_api(
|
|
87
88
|
)
|
88
89
|
async def update_group(
|
89
90
|
id: str, data: GroupData,
|
90
|
-
user_token_data:
|
91
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
91
92
|
):
|
92
93
|
if not await authorizer.is_having_permission(
|
93
94
|
user_token_data.user_id, 'auth:group:update'
|
@@ -106,7 +107,8 @@ def register_api(
|
|
106
107
|
'/api/v1/auth/groups/{id}', response_model=Group
|
107
108
|
)
|
108
109
|
async def delete_group(
|
109
|
-
id: str,
|
110
|
+
id: str,
|
111
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
110
112
|
):
|
111
113
|
if not await authorizer.is_having_permission(
|
112
114
|
user_token_data.user_id, 'auth:group:delete'
|
zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/group/rpc.py
CHANGED
@@ -5,7 +5,7 @@ from core.rpc import Caller, Server
|
|
5
5
|
from core.repo import SearchFilter
|
6
6
|
from module.auth.component.model.group_model import group_model
|
7
7
|
from module.auth.schema.group import GroupData
|
8
|
-
from module.auth.schema.token import
|
8
|
+
from module.auth.schema.token import AccessTokenData
|
9
9
|
|
10
10
|
|
11
11
|
def register_rpc(
|
@@ -46,7 +46,7 @@ def register_rpc(
|
|
46
46
|
data: Mapping[str, Any],
|
47
47
|
user_token_data: Mapping[str, Any]
|
48
48
|
) -> Mapping[str, Any]:
|
49
|
-
user_token_data:
|
49
|
+
user_token_data: AccessTokenData = AccessTokenData(**user_token_data)
|
50
50
|
data['created_by'] = user_token_data.user_id
|
51
51
|
data['updated_by'] = user_token_data.user_id
|
52
52
|
row = await group_model.insert(
|
@@ -60,7 +60,7 @@ def register_rpc(
|
|
60
60
|
data: Mapping[str, Any],
|
61
61
|
user_token_data: Mapping[str, Any]
|
62
62
|
) -> Mapping[str, Any]:
|
63
|
-
user_token_data:
|
63
|
+
user_token_data: AccessTokenData = AccessTokenData(**user_token_data)
|
64
64
|
data['updated_by'] = user_token_data.user_id
|
65
65
|
row = await group_model.update(
|
66
66
|
id=id, data=GroupData(**data)
|
@@ -72,6 +72,6 @@ def register_rpc(
|
|
72
72
|
id: str,
|
73
73
|
user_token_data: Mapping[str, Any]
|
74
74
|
) -> Mapping[str, Any]:
|
75
|
-
user_token_data =
|
75
|
+
user_token_data = AccessTokenData(**user_token_data)
|
76
76
|
row = await group_model.delete(id=id)
|
77
77
|
return row.dict()
|
zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/permission/api.py
CHANGED
@@ -7,8 +7,8 @@ from module.auth.core import Authorizer
|
|
7
7
|
from module.auth.schema.permission import (
|
8
8
|
Permission, PermissionData, PermissionResult
|
9
9
|
)
|
10
|
-
from module.auth.schema.token import
|
11
|
-
from module.auth.component import
|
10
|
+
from module.auth.schema.token import AccessTokenData
|
11
|
+
from module.auth.component import access_token_scheme
|
12
12
|
|
13
13
|
|
14
14
|
def register_api(
|
@@ -25,7 +25,7 @@ def register_api(
|
|
25
25
|
)
|
26
26
|
async def get_permissions(
|
27
27
|
keyword: str = '', limit: int = 100, offset: int = 0,
|
28
|
-
user_token_data:
|
28
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
29
29
|
):
|
30
30
|
if not await authorizer.is_having_permission(
|
31
31
|
user_token_data.user_id, 'auth:permission:get'
|
@@ -48,7 +48,8 @@ def register_api(
|
|
48
48
|
'/api/v1/auth/permissions/{id}', response_model=Permission
|
49
49
|
)
|
50
50
|
async def get_permission_by_id(
|
51
|
-
id: str,
|
51
|
+
id: str,
|
52
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
52
53
|
):
|
53
54
|
if not await authorizer.is_having_permission(
|
54
55
|
user_token_data.user_id, 'auth:permission:get_by_id'
|
@@ -68,7 +69,7 @@ def register_api(
|
|
68
69
|
)
|
69
70
|
async def insert_permission(
|
70
71
|
data: PermissionData,
|
71
|
-
user_token_data:
|
72
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
72
73
|
):
|
73
74
|
if not await authorizer.is_having_permission(
|
74
75
|
user_token_data.user_id, 'auth:permission:insert'
|
@@ -88,7 +89,7 @@ def register_api(
|
|
88
89
|
)
|
89
90
|
async def update_permission(
|
90
91
|
id: str, data: PermissionData,
|
91
|
-
user_token_data:
|
92
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
92
93
|
):
|
93
94
|
if not await authorizer.is_having_permission(
|
94
95
|
user_token_data.user_id, 'auth:permission:update'
|
@@ -107,7 +108,8 @@ def register_api(
|
|
107
108
|
'/api/v1/auth/permissions/{id}', response_model=Permission
|
108
109
|
)
|
109
110
|
async def delete_permission(
|
110
|
-
id: str,
|
111
|
+
id: str,
|
112
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
111
113
|
):
|
112
114
|
if not await authorizer.is_having_permission(
|
113
115
|
user_token_data.user_id, 'auth:permission:delete'
|
zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/permission/rpc.py
CHANGED
@@ -5,7 +5,7 @@ from core.rpc import Caller, Server
|
|
5
5
|
from core.repo import SearchFilter
|
6
6
|
from module.auth.component.model.permission_model import permission_model
|
7
7
|
from module.auth.schema.permission import PermissionData
|
8
|
-
from module.auth.schema.token import
|
8
|
+
from module.auth.schema.token import AccessTokenData
|
9
9
|
|
10
10
|
|
11
11
|
def register_rpc(
|
@@ -52,7 +52,7 @@ def register_rpc(
|
|
52
52
|
data: Mapping[str, Any],
|
53
53
|
user_token_data: Mapping[str, Any]
|
54
54
|
) -> Mapping[str, Any]:
|
55
|
-
user_token_data =
|
55
|
+
user_token_data = AccessTokenData(**user_token_data)
|
56
56
|
data['created_by'] = user_token_data.user_id
|
57
57
|
data['updated_by'] = user_token_data.user_id
|
58
58
|
row = await permission_model.insert(
|
@@ -66,7 +66,7 @@ def register_rpc(
|
|
66
66
|
data: Mapping[str, Any],
|
67
67
|
user_token_data: Mapping[str, Any]
|
68
68
|
) -> Mapping[str, Any]:
|
69
|
-
user_token_data =
|
69
|
+
user_token_data = AccessTokenData(**user_token_data)
|
70
70
|
data['updated_by'] = user_token_data.user_id
|
71
71
|
row = await permission_model.update(
|
72
72
|
id=id, data=PermissionData(**data)
|
@@ -78,6 +78,6 @@ def register_rpc(
|
|
78
78
|
id: str,
|
79
79
|
user_token_data: Mapping[str, Any]
|
80
80
|
) -> Mapping[str, Any]:
|
81
|
-
user_token_data =
|
81
|
+
user_token_data = AccessTokenData(**user_token_data)
|
82
82
|
row = await permission_model.delete(id=id)
|
83
83
|
return row.dict()
|
zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/api.py
CHANGED
@@ -9,9 +9,9 @@ from module.auth.core import Authorizer
|
|
9
9
|
from module.auth.schema.user import (
|
10
10
|
User, UserData, UserResult, UserLogin
|
11
11
|
)
|
12
|
-
from module.auth.schema.token import
|
12
|
+
from module.auth.schema.token import AccessTokenData, TokenResponse
|
13
13
|
from module.auth.schema.request import RefreshTokenRequest, IsAuthorizedRequest
|
14
|
-
from module.auth.component import
|
14
|
+
from module.auth.component import access_token_scheme, bearer_token_scheme
|
15
15
|
|
16
16
|
|
17
17
|
def register_auth_api(
|
@@ -39,32 +39,39 @@ def register_auth_api(
|
|
39
39
|
|
40
40
|
async def _create_token(data: UserLogin) -> TokenResponse:
|
41
41
|
try:
|
42
|
-
|
42
|
+
token_response_dict = await rpc_caller.call(
|
43
43
|
'auth_create_token', login_data=data.dict()
|
44
44
|
)
|
45
|
-
return TokenResponse(
|
45
|
+
return TokenResponse(**token_response_dict)
|
46
46
|
except Exception as e:
|
47
47
|
raise HTTPAPIException(error=e)
|
48
48
|
|
49
49
|
@app.post('/api/v1/auth/refresh-token', response_model=TokenResponse)
|
50
|
-
async def refresh_token(
|
50
|
+
async def refresh_token(
|
51
|
+
data: RefreshTokenRequest,
|
52
|
+
refresh_token: str = Depends(bearer_token_scheme)
|
53
|
+
) -> TokenResponse:
|
51
54
|
try:
|
52
|
-
|
53
|
-
'auth_refresh_token',
|
55
|
+
token_response_dict = await rpc_caller.call(
|
56
|
+
'auth_refresh_token',
|
57
|
+
refresh_token=refresh_token,
|
58
|
+
access_token=data.access_token
|
54
59
|
)
|
55
|
-
return TokenResponse(
|
60
|
+
return TokenResponse(**token_response_dict)
|
56
61
|
except Exception as e:
|
57
62
|
raise HTTPAPIException(error=e)
|
58
63
|
|
59
64
|
@app.post('/api/v1/auth/is-authorized', response_model=Mapping[str, bool])
|
60
65
|
async def is_authorized(
|
61
66
|
data: IsAuthorizedRequest,
|
62
|
-
user_token_data:
|
67
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
63
68
|
) -> Mapping[str, str]:
|
64
69
|
try:
|
65
70
|
user_id = user_token_data.user_id
|
66
71
|
return await rpc_caller.call(
|
67
|
-
'auth_is_user_authorized',
|
72
|
+
'auth_is_user_authorized',
|
73
|
+
id=user_id,
|
74
|
+
permission_name=data.permission_names
|
68
75
|
)
|
69
76
|
except Exception as e:
|
70
77
|
raise HTTPAPIException(error=e)
|
@@ -84,7 +91,7 @@ def register_api(
|
|
84
91
|
)
|
85
92
|
async def get_users(
|
86
93
|
keyword: str = '', limit: int = 100, offset: int = 0,
|
87
|
-
user_token_data:
|
94
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
88
95
|
):
|
89
96
|
if not await authorizer.is_having_permission(
|
90
97
|
user_token_data.user_id, 'auth:user:get'
|
@@ -107,7 +114,8 @@ def register_api(
|
|
107
114
|
'/api/v1/auth/users/{id}', response_model=User
|
108
115
|
)
|
109
116
|
async def get_user_by_id(
|
110
|
-
id: str,
|
117
|
+
id: str,
|
118
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
111
119
|
):
|
112
120
|
if not await authorizer.is_having_permission(
|
113
121
|
user_token_data.user_id, 'auth:user:get_by_id'
|
@@ -126,7 +134,8 @@ def register_api(
|
|
126
134
|
'/api/v1/auth/users', response_model=User
|
127
135
|
)
|
128
136
|
async def insert_user(
|
129
|
-
data: UserData,
|
137
|
+
data: UserData,
|
138
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
130
139
|
):
|
131
140
|
if not await authorizer.is_having_permission(
|
132
141
|
user_token_data.user_id, 'auth:user:insert'
|
@@ -146,7 +155,7 @@ def register_api(
|
|
146
155
|
)
|
147
156
|
async def update_user(
|
148
157
|
id: str, data: UserData,
|
149
|
-
user_token_data:
|
158
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
150
159
|
):
|
151
160
|
if not await authorizer.is_having_permission(
|
152
161
|
user_token_data.user_id, 'auth:user:update'
|
@@ -165,7 +174,8 @@ def register_api(
|
|
165
174
|
'/api/v1/auth/users/{id}', response_model=User
|
166
175
|
)
|
167
176
|
async def delete_user(
|
168
|
-
id: str,
|
177
|
+
id: str,
|
178
|
+
user_token_data: AccessTokenData = Depends(access_token_scheme)
|
169
179
|
):
|
170
180
|
if not await authorizer.is_having_permission(
|
171
181
|
user_token_data.user_id, 'auth:user:delete'
|
zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/model.py
CHANGED
@@ -4,8 +4,10 @@ from module.auth.schema.user import (
|
|
4
4
|
User, UserData, UserResult, UserLogin
|
5
5
|
)
|
6
6
|
from module.auth.entity.user.repo import UserRepo
|
7
|
-
from module.auth.schema.token import
|
8
|
-
|
7
|
+
from module.auth.schema.token import (
|
8
|
+
AccessTokenData, RefreshTokenData, TokenResponse
|
9
|
+
)
|
10
|
+
from module.auth.core import AccessTokenUtil, RefreshTokenUtil
|
9
11
|
from module.auth.entity.permission.model import PermissionModel
|
10
12
|
|
11
13
|
|
@@ -18,16 +20,20 @@ class UserModel(
|
|
18
20
|
self,
|
19
21
|
repo: UserRepo,
|
20
22
|
permission_model: PermissionModel,
|
21
|
-
|
22
|
-
|
23
|
+
access_token_util: AccessTokenUtil,
|
24
|
+
access_token_expire_seconds: int,
|
25
|
+
refresh_token_util: RefreshTokenUtil,
|
26
|
+
refresh_token_expire_seconds: int,
|
23
27
|
guest_user: User,
|
24
28
|
admin_user: Optional[User] = None,
|
25
29
|
admin_user_password: str = ''
|
26
30
|
):
|
27
31
|
self.repo = repo
|
28
32
|
self.permission_model = permission_model
|
29
|
-
self.
|
30
|
-
self.
|
33
|
+
self.access_token_util = access_token_util
|
34
|
+
self.access_token_expire_seconds = access_token_expire_seconds
|
35
|
+
self.refresh_token_util = refresh_token_util
|
36
|
+
self.refresh_token_expire_seconds = refresh_token_expire_seconds
|
31
37
|
self.guest_user = guest_user
|
32
38
|
self.admin_user = admin_user
|
33
39
|
self.admin_user_pasword = admin_user_password
|
@@ -116,21 +122,44 @@ class UserModel(
|
|
116
122
|
return False
|
117
123
|
return id == self.admin_user.id
|
118
124
|
|
119
|
-
async def
|
125
|
+
async def create_auth_token(self, user_login: UserLogin) -> TokenResponse:
|
120
126
|
user = await self._get_user_by_user_login(user_login)
|
121
|
-
return
|
127
|
+
return TokenResponse(
|
128
|
+
access_token=self._get_access_token(user),
|
129
|
+
refresh_token=self._get_refresh_token(user),
|
130
|
+
token_type='bearer'
|
131
|
+
)
|
122
132
|
|
123
|
-
async def
|
124
|
-
|
125
|
-
|
133
|
+
async def refresh_auth_token(
|
134
|
+
self, refresh_token: str, access_token: str
|
135
|
+
) -> TokenResponse:
|
136
|
+
access_token_data = self.access_token_util.decode(
|
137
|
+
access_token, parse_expired_token=True
|
138
|
+
)
|
139
|
+
refresh_token_data = self.refresh_token_util.decode(refresh_token)
|
140
|
+
if access_token_data.user_id != refresh_token_data.user_id:
|
141
|
+
raise ValueError('Unmatch refresh and access token')
|
142
|
+
user = await self.get_by_id(refresh_token_data.user_id)
|
143
|
+
return TokenResponse(
|
144
|
+
access_token=self._get_access_token(user),
|
145
|
+
refresh_token=self._get_refresh_token(user),
|
146
|
+
token_type='bearer'
|
147
|
+
)
|
126
148
|
|
127
|
-
def
|
128
|
-
|
149
|
+
def _get_access_token(self, user: User) -> str:
|
150
|
+
access_token_data = AccessTokenData(
|
129
151
|
user_id=user.id,
|
130
152
|
username=user.username,
|
131
|
-
expire_seconds=self.
|
153
|
+
expire_seconds=self.access_token_expire_seconds
|
132
154
|
)
|
133
|
-
return self.
|
155
|
+
return self.access_token_util.encode(access_token_data)
|
156
|
+
|
157
|
+
def _get_refresh_token(self, user: User) -> str:
|
158
|
+
refresh_token_data = RefreshTokenData(
|
159
|
+
user_id=user.id,
|
160
|
+
expire_seconds=self.refresh_token_expire_seconds
|
161
|
+
)
|
162
|
+
return self.refresh_token_util.encode(refresh_token_data)
|
134
163
|
|
135
164
|
async def _get_user_by_user_login(self, user_login: UserLogin) -> User:
|
136
165
|
if user_login.identity == '':
|
@@ -146,7 +175,3 @@ class UserModel(
|
|
146
175
|
):
|
147
176
|
return self.admin_user
|
148
177
|
return await self.repo.get_by_user_login(user_login)
|
149
|
-
|
150
|
-
async def _get_user_by_token(self, token: str) -> User:
|
151
|
-
token_data = self.token_util.decode(token)
|
152
|
-
return await self.get_by_id(token_data.user_id)
|