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.
Files changed (93) hide show
  1. zrb/builtin/generator/fastapp/template/_automate/snake_app_name/cmd/start.sh +1 -1
  2. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/.gitignore +1 -1
  3. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/config.py +14 -5
  4. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/.env.local +4 -0
  5. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/.gitignore +1 -1
  6. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/README.md +0 -0
  7. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/package-lock.json +16 -0
  8. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/package.json +2 -0
  9. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/playwright.config.ts +0 -0
  10. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/postcss.config.js +0 -0
  11. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/app.css +0 -0
  12. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/app.d.ts +0 -0
  13. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/app.html +0 -0
  14. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/index.test.ts +0 -0
  15. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/helper.ts +146 -0
  16. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/store.ts +0 -0
  17. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/type.ts +3 -3
  18. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/Menu.svelte +19 -16
  19. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/Navigation.svelte +14 -11
  20. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/helper.ts +18 -0
  21. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/components/navigation/type.ts +0 -0
  22. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/config/app.ts +9 -0
  23. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/config/navData.ts +6 -17
  24. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/error/helper.ts +12 -0
  25. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+error.svelte +8 -0
  26. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+layout.js +0 -0
  27. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+layout.svelte +4 -3
  28. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/+page.svelte +2 -8
  29. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/static/favicon.png +0 -0
  30. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/static/logo.png +0 -0
  31. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/svelte.config.js +0 -0
  32. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/tailwind.config.js +0 -0
  33. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/tests/test.ts +0 -0
  34. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/tsconfig.json +0 -0
  35. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/vite.config.ts +0 -0
  36. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/__init__.py +8 -4
  37. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/access_token_scheme.py +14 -0
  38. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/access_token_util.py +17 -0
  39. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/bearer_token_scheme.py +5 -0
  40. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/model/user_model.py +9 -4
  41. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/refresh_token_util.py +17 -0
  42. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/__init__.py +14 -9
  43. 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
  44. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/access_token/util.py +69 -0
  45. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/authorizer/rpc_authorizer.py +4 -2
  46. 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
  47. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/group/api.py +9 -7
  48. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/group/rpc.py +4 -4
  49. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/permission/api.py +9 -7
  50. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/permission/rpc.py +4 -4
  51. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/api.py +25 -15
  52. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/model.py +44 -19
  53. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/entity/user/rpc.py +19 -11
  54. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/schema/request.py +2 -2
  55. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/schema/token.py +7 -1
  56. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/requirements.txt +1 -0
  57. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/template.env +7 -3
  58. zrb/builtin/generator/fastapp_crud/add.py +7 -21
  59. zrb/builtin/generator/fastapp_crud/add_navigation.py +32 -0
  60. zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/frontend/src/routes/kebab-module-name/kebab-entity-name/+page.svelte +121 -0
  61. 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
  62. 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
  63. 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
  64. 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
  65. 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
  66. 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
  67. 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
  68. zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/module/snake_module_name/entity/snake_entity_name/api.py +9 -7
  69. zrb/builtin/generator/fastapp_crud/template/src/kebab-app-name/src/module/snake_module_name/entity/snake_entity_name/rpc.py +4 -4
  70. zrb/builtin/generator/fastapp_field/add.py +203 -4
  71. zrb/builtin/generator/project/template/.gitignore +1 -1
  72. zrb/builtin/generator/simple_python_app/template/src/kebab-app-name/src/.gitignore +1 -1
  73. zrb/helper/util.py +4 -0
  74. zrb/task/resource_maker.py +2 -1
  75. {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/METADATA +3 -3
  76. {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/RECORD +64 -56
  77. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/auth/auth.ts +0 -83
  78. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/config/config.ts +0 -4
  79. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/lib/cookie/cookie.ts +0 -19
  80. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/about/+page.svelte +0 -2
  81. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/greetings/[slug]/+page.js +0 -6
  82. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/greetings/[slug]/+page.svelte +0 -5
  83. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/sample/+page.svelte +0 -37
  84. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/frontend/src/routes/sample/delete/[id]/+page.svelte +0 -1
  85. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/token_scheme.py +0 -11
  86. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/component/token_util.py +0 -17
  87. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/token_scheme/token_sheme.py +0 -5
  88. zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/token_util/token_util.py +0 -13
  89. /zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_scheme/__init__.py → access_token/_init_.py} +0 -0
  90. /zrb/builtin/generator/fastapp/template/src/kebab-app-name/src/module/auth/core/{token_util/__init__.py → refresh_token/_init_.py} +0 -0
  91. {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/LICENSE +0 -0
  92. {zrb-0.0.52.dist-info → zrb-0.0.53.dist-info}/WHEEL +0 -0
  93. {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.token_scheme.token_sheme import TokenScheme
8
- from module.auth.core.token_scheme.oauth2_bearer_token_scheme import (
9
- create_oauth2_bearer_token_scheme
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 TokenScheme
19
- assert create_oauth2_bearer_token_scheme
20
- assert TokenUtil
21
- assert JWTTokenUtil
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.core.token_util.token_util import TokenUtil
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
- def create_oauth2_bearer_token_scheme(
11
+
12
+ def create_oauth2_bearer_access_token_scheme(
12
13
  guest_user: User,
13
- token_util: TokenUtil,
14
+ access_token_util: AccessTokenUtil,
14
15
  token_url: str,
15
16
  token_cookie_key: str
16
- ) -> TokenScheme:
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
- ) -> TokenData:
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 TokenData(
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 token_util.decode(token)
36
+ return access_token_util.decode(token, parse_expired_token=False)
37
37
 
38
38
  return oauth2_bearer_token_scheme
@@ -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, *permission_names: 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, user_id, *permission_names
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 TokenData
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 JWTTokenUtil(TokenUtil):
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: TokenData) -> str:
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) -> TokenData:
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 = TokenData.parse_obj(sub)
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()
@@ -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 TokenData
11
- from module.auth.component import token_scheme
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: TokenData = Depends(token_scheme),
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: TokenData = Depends(token_scheme)
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, user_token_data: TokenData = Depends(token_scheme)
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: TokenData = Depends(token_scheme)
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, user_token_data: TokenData = Depends(token_scheme)
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'
@@ -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 TokenData
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: TokenData = TokenData(**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: TokenData = TokenData(**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 = TokenData(**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()
@@ -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 TokenData
11
- from module.auth.component import token_scheme
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: TokenData = Depends(token_scheme)
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, user_token_data: TokenData = Depends(token_scheme)
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: TokenData = Depends(token_scheme)
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: TokenData = Depends(token_scheme)
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, user_token_data: TokenData = Depends(token_scheme)
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'
@@ -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 TokenData
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 = TokenData(**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 = TokenData(**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 = TokenData(**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()
@@ -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 TokenData, TokenResponse
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 token_scheme
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
- token = await rpc_caller.call(
42
+ token_response_dict = await rpc_caller.call(
43
43
  'auth_create_token', login_data=data.dict()
44
44
  )
45
- return TokenResponse(access_token=token, token_type='bearer')
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(data: RefreshTokenRequest) -> TokenResponse:
50
+ async def refresh_token(
51
+ data: RefreshTokenRequest,
52
+ refresh_token: str = Depends(bearer_token_scheme)
53
+ ) -> TokenResponse:
51
54
  try:
52
- token = await rpc_caller.call(
53
- 'auth_refresh_token', token=data.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(access_token=token, token_type='bearer')
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: TokenData = Depends(token_scheme)
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', id=user_id, *data.permission_names
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: TokenData = Depends(token_scheme)
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, user_token_data: TokenData = Depends(token_scheme)
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, user_token_data: TokenData = Depends(token_scheme)
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: TokenData = Depends(token_scheme)
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, user_token_data: TokenData = Depends(token_scheme)
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'
@@ -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 TokenData
8
- from module.auth.core import TokenUtil
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
- token_util: TokenUtil,
22
- expire_seconds: int,
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.token_util = token_util
30
- self.expire_seconds = expire_seconds
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 create_token(self, user_login: UserLogin) -> str:
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 self._get_token(user)
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 refresh_token(self, auth_token_str: str) -> str:
124
- user = await self._get_user_by_token(auth_token_str)
125
- return self._get_token(user)
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 _get_token(self, user: User) -> str:
128
- token_data = TokenData(
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.expire_seconds
153
+ expire_seconds=self.access_token_expire_seconds
132
154
  )
133
- return self.token_util.encode(token_data)
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)