zrb 1.0.0b1__py3-none-any.whl → 1.0.0b2__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 (90) hide show
  1. zrb/__main__.py +0 -3
  2. zrb/builtin/__init__.py +3 -0
  3. zrb/builtin/group.py +1 -0
  4. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/config.py +1 -1
  5. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +66 -21
  6. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +67 -41
  7. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/my_entity_service.py +69 -15
  8. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/my_entity_service_factory.py +2 -1
  9. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_db_repository.py +0 -10
  10. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_repository.py +37 -16
  11. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/my_module/service/my_entity/repository/my_entity_repository_factory.py +2 -2
  12. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/schema/my_entity.py +16 -6
  13. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/client_method.py +57 -0
  14. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/gateway_subroute.py +63 -28
  15. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_task.py +1 -0
  16. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_api_client.py +6 -0
  17. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/{any_client.py → my_module_client.py} +1 -1
  18. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_client_factory.py +11 -0
  19. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/my_module_direct_client.py +5 -0
  20. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/route.py +1 -1
  21. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/module_task_definition.py +2 -2
  22. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task.py +4 -4
  23. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/util.py +47 -20
  24. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/app_factory.py +29 -0
  25. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_db_repository.py +185 -101
  26. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_service.py +99 -108
  27. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/{db_engine.py → db_engine_factory.py} +1 -1
  28. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/error.py +12 -0
  29. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/logger_factory.py +10 -0
  30. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/parser_factory.py +7 -0
  31. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/app.py +47 -0
  32. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/parser.py +105 -0
  33. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/user_agent.py +58 -0
  34. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +1 -1
  35. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/main.py +1 -1
  36. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_api_client.py +16 -0
  37. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client.py +163 -0
  38. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client_factory.py +9 -0
  39. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_direct_client.py +15 -0
  40. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_auth_tables.py +160 -0
  41. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration_metadata.py +18 -1
  42. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/route.py +5 -1
  43. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/__init__.py +0 -0
  44. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service.py +117 -0
  45. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service_factory.py +11 -0
  46. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_db_repository.py +26 -0
  47. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository.py +61 -0
  48. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository_factory.py +13 -0
  49. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/__init__.py +0 -0
  50. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_db_repository.py +75 -0
  51. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository.py +59 -0
  52. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository_factory.py +13 -0
  53. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service.py +105 -0
  54. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service_factory.py +7 -0
  55. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_db_repository.py +42 -13
  56. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository.py +38 -17
  57. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository_factory.py +2 -2
  58. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service.py +69 -17
  59. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service_factory.py +2 -1
  60. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/route.py +1 -1
  61. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +198 -28
  62. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/view.py +1 -1
  63. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +1 -1
  64. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/permission.py +17 -5
  65. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/role.py +50 -4
  66. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/session.py +52 -0
  67. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/user.py +30 -5
  68. zrb/builtin/random.py +61 -0
  69. zrb/cmd/cmd_val.py +6 -5
  70. zrb/runner/cli.py +10 -1
  71. zrb/runner/web_util/token.py +7 -3
  72. zrb/task/base_task.py +24 -2
  73. zrb/task/cmd_task.py +7 -5
  74. zrb/util/cmd/command.py +1 -0
  75. zrb/util/file.py +7 -1
  76. {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/METADATA +1 -1
  77. {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/RECORD +80 -61
  78. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/any_client_method.py +0 -27
  79. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/api_client.py +0 -6
  80. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/direct_client.py +0 -5
  81. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/factory.py +0 -9
  82. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/app.py +0 -57
  83. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/any_client.py +0 -33
  84. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/api_client.py +0 -7
  85. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/direct_client.py +0 -6
  86. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/factory.py +0 -9
  87. zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_user_table.py +0 -37
  88. /zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/{view.py → util/view.py} +0 -0
  89. {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/WHEEL +0 -0
  90. {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/entry_points.txt +0 -0
@@ -1,8 +1,11 @@
1
+ from logging import Logger
2
+
1
3
  from my_app_name.common.base_service import BaseService
2
4
  from my_app_name.module.auth.service.user.repository.user_repository import (
3
5
  UserRepository,
4
6
  )
5
7
  from my_app_name.schema.user import (
8
+ MultipleUserResponse,
6
9
  UserCreateWithAudit,
7
10
  UserResponse,
8
11
  UserUpdateWithAudit,
@@ -10,44 +13,93 @@ from my_app_name.schema.user import (
10
13
 
11
14
 
12
15
  class UserService(BaseService):
13
- def __init__(self, user_repository: UserRepository):
14
- super().__init__()
16
+
17
+ def __init__(self, logger: Logger, user_repository: UserRepository):
18
+ super().__init__(logger)
15
19
  self.user_repository = user_repository
16
20
 
17
21
  @BaseService.route(
18
- "/api/v1/users/{user_id}", methods=["get"], response_model=UserResponse
22
+ "/api/v1/users/{user_id}",
23
+ methods=["get"],
24
+ response_model=UserResponse,
19
25
  )
20
26
  async def get_user_by_id(self, user_id: str) -> UserResponse:
21
27
  return await self.user_repository.get_by_id(user_id)
22
28
 
23
29
  @BaseService.route(
24
- "/api/v1/users", methods=["get"], response_model=list[UserResponse]
30
+ "/api/v1/users",
31
+ methods=["get"],
32
+ response_model=MultipleUserResponse,
25
33
  )
26
- async def get_all_users(self) -> list[UserResponse]:
27
- return await self.user_repository.get_all()
34
+ async def get_users(
35
+ self,
36
+ page: int = 1,
37
+ page_size: int = 10,
38
+ sort: str | None = None,
39
+ filter: str | None = None,
40
+ ) -> MultipleUserResponse:
41
+ users = await self.user_repository.get(page, page_size, filter, sort)
42
+ count = await self.user_repository.count(filter)
43
+ return MultipleUserResponse(data=users, count=count)
28
44
 
29
45
  @BaseService.route(
30
46
  "/api/v1/users",
31
47
  methods=["post"],
32
- response_model=UserResponse | list[UserResponse],
48
+ response_model=UserResponse,
49
+ )
50
+ async def create_user(self, data: UserCreateWithAudit) -> UserResponse:
51
+ user = await self.user_repository.create(data)
52
+ return await self.user_repository.get_by_id(user.id)
53
+
54
+ @BaseService.route(
55
+ "/api/v1/users/bulk",
56
+ methods=["post"],
57
+ response_model=list[UserResponse],
33
58
  )
34
- async def create_user(
35
- self, data: UserCreateWithAudit | list[UserCreateWithAudit]
36
- ) -> UserResponse | list[UserResponse]:
37
- if isinstance(data, UserCreateWithAudit):
38
- return await self.user_repository.create(data)
39
- return await self.user_repository.create_bulk(data)
59
+ async def create_user_bulk(
60
+ self, data: list[UserCreateWithAudit]
61
+ ) -> list[UserResponse]:
62
+ users = await self.user_repository.create_bulk(data)
63
+ return await self.user_repository.get_by_ids([user.id for user in users])
40
64
 
41
65
  @BaseService.route(
42
- "/api/v1/users/{user_id}", methods=["put"], response_model=UserResponse
66
+ "/api/v1/users/bulk",
67
+ methods=["put"],
68
+ response_model=UserResponse,
69
+ )
70
+ async def update_user_bulk(
71
+ self, user_ids: list[str], data: UserUpdateWithAudit
72
+ ) -> UserResponse:
73
+ users = await self.user_repository.update_bulk(user_ids, data)
74
+ return await self.user_repository.get_by_ids([user.id for user in users])
75
+
76
+ @BaseService.route(
77
+ "/api/v1/users/{user_id}",
78
+ methods=["put"],
79
+ response_model=UserResponse,
43
80
  )
44
81
  async def update_user(
45
82
  self, user_id: str, data: UserUpdateWithAudit
46
83
  ) -> UserResponse:
47
- return await self.user_repository.update(user_id, data)
84
+ user = await self.user_repository.update(user_id, data)
85
+ return await self.user_repository.get_by_id(user.id)
86
+
87
+ @BaseService.route(
88
+ "/api/v1/users/{user_id}",
89
+ methods=["delete"],
90
+ response_model=UserResponse,
91
+ )
92
+ async def delete_user_bulk(
93
+ self, user_ids: list[str], deleted_by: str
94
+ ) -> UserResponse:
95
+ users = await self.user_repository.delete_bulk(user_ids)
96
+ return await self.user_repository.get_by_ids([user.id for user in users])
48
97
 
49
98
  @BaseService.route(
50
- "/api/v1/users/{user_id}", methods=["delete"], response_model=UserResponse
99
+ "/api/v1/users/{user_id}",
100
+ methods=["delete"],
101
+ response_model=UserResponse,
51
102
  )
52
103
  async def delete_user(self, user_id: str, deleted_by: str) -> UserResponse:
53
- return await self.user_repository.delete(user_id)
104
+ user = await self.user_repository.delete(user_id)
105
+ return await self.user_repository.get_by_id(user.id)
@@ -1,6 +1,7 @@
1
+ from my_app_name.common.logger_factory import logger
1
2
  from my_app_name.module.auth.service.user.repository.user_repository_factory import (
2
3
  user_repository,
3
4
  )
4
5
  from my_app_name.module.auth.service.user.user_service import UserService
5
6
 
6
- user_service = UserService(user_repository=user_repository)
7
+ user_service = UserService(logger, user_repository=user_repository)
@@ -3,7 +3,7 @@ import os
3
3
  from fastapi import FastAPI, HTTPException, Request
4
4
  from fastapi.exception_handlers import http_exception_handler
5
5
  from fastapi.responses import HTMLResponse
6
- from my_app_name.common.app import app
6
+ from my_app_name.common.app_factory import app
7
7
  from my_app_name.common.schema import BasicResponse
8
8
  from my_app_name.config import (
9
9
  APP_GATEWAY_VIEW_PATH,
@@ -1,44 +1,214 @@
1
1
  from fastapi import FastAPI
2
- from my_app_name.module.auth.client.factory import client as auth_client
2
+ from my_app_name.module.auth.client.auth_client_factory import auth_client
3
+ from my_app_name.schema.permission import (
4
+ MultiplePermissionResponse,
5
+ PermissionCreate,
6
+ PermissionResponse,
7
+ PermissionUpdate,
8
+ )
9
+ from my_app_name.schema.role import (
10
+ MultipleRoleResponse,
11
+ RoleCreate,
12
+ RoleResponse,
13
+ RoleUpdate,
14
+ )
3
15
  from my_app_name.schema.user import (
16
+ MultipleUserResponse,
4
17
  UserCreate,
5
- UserCreateWithAudit,
6
18
  UserResponse,
7
19
  UserUpdate,
8
- UserUpdateWithAudit,
9
20
  )
10
21
 
11
22
 
12
23
  def serve_auth_route(app: FastAPI):
13
24
 
14
- @app.get("/api/v1/users", response_model=list[UserResponse])
15
- async def get_all_users() -> UserResponse:
16
- return await auth_client.get_all_users()
25
+ # Permission routes
26
+
27
+ @app.get("/api/v1/permissions", response_model=MultiplePermissionResponse)
28
+ async def get_permissions(
29
+ page: int = 1,
30
+ page_size: int = 10,
31
+ sort: str | None = None,
32
+ filter: str | None = None,
33
+ ) -> MultiplePermissionResponse:
34
+ return await auth_client.get_permissions(
35
+ page=page, page_size=page_size, sort=sort, filter=filter
36
+ )
37
+
38
+ @app.get("/api/v1/permissions/{permission_id}", response_model=PermissionResponse)
39
+ async def get_permission_by_id(permission_id: str) -> PermissionResponse:
40
+ return await auth_client.get_permission_by_id(permission_id)
41
+
42
+ @app.post(
43
+ "/api/v1/permissions/bulk",
44
+ response_model=list[PermissionResponse],
45
+ )
46
+ async def create_permission_bulk(data: list[PermissionCreate]):
47
+ return await auth_client.create_permission(
48
+ [row.with_audit(created_by="system") for row in data]
49
+ )
50
+
51
+ @app.post(
52
+ "/api/v1/permissions",
53
+ response_model=PermissionResponse,
54
+ )
55
+ async def create_permission(data: PermissionCreate):
56
+ return await auth_client.create_permission(data.with_audit(created_by="system"))
57
+
58
+ @app.put(
59
+ "/api/v1/permissions/bulk",
60
+ response_model=list[PermissionResponse],
61
+ )
62
+ async def update_permission_bulk(permission_ids: list[str], data: PermissionUpdate):
63
+ return await auth_client.update_permission_bulk(
64
+ permission_ids, data.with_audit(updated_by="system")
65
+ )
66
+
67
+ @app.put(
68
+ "/api/v1/permissions/{permission_id}",
69
+ response_model=PermissionResponse,
70
+ )
71
+ async def update_permission(permission_id: str, data: PermissionUpdate):
72
+ return await auth_client.update_permission(data.with_audit(updated_by="system"))
73
+
74
+ @app.delete(
75
+ "/api/v1/permissions/bulk",
76
+ response_model=list[PermissionResponse],
77
+ )
78
+ async def delete_permission_bulk(permission_ids: list[str]):
79
+ return await auth_client.delete_permission_bulk(
80
+ permission_ids, deleted_by="system"
81
+ )
82
+
83
+ @app.delete(
84
+ "/api/v1/permissions/{permission_id}",
85
+ response_model=PermissionResponse,
86
+ )
87
+ async def delete_permission(permission_id: str):
88
+ return await auth_client.delete_permission(permission_id, deleted_by="system")
89
+
90
+ # Role routes
91
+
92
+ @app.get("/api/v1/roles", response_model=MultipleRoleResponse)
93
+ async def get_roles(
94
+ page: int = 1,
95
+ page_size: int = 10,
96
+ sort: str | None = None,
97
+ filter: str | None = None,
98
+ ) -> MultipleRoleResponse:
99
+ return await auth_client.get_roles(
100
+ page=page, page_size=page_size, sort=sort, filter=filter
101
+ )
102
+
103
+ @app.get("/api/v1/roles/{role_id}", response_model=RoleResponse)
104
+ async def get_role_by_id(role_id: str) -> RoleResponse:
105
+ return await auth_client.get_role_by_id(role_id)
106
+
107
+ @app.post(
108
+ "/api/v1/roles/bulk",
109
+ response_model=list[RoleResponse],
110
+ )
111
+ async def create_role_bulk(data: list[RoleCreate]):
112
+ return await auth_client.create_role(
113
+ [row.with_audit(created_by="system") for row in data]
114
+ )
115
+
116
+ @app.post(
117
+ "/api/v1/roles",
118
+ response_model=RoleResponse,
119
+ )
120
+ async def create_role(data: RoleCreate):
121
+ return await auth_client.create_role(data.with_audit(created_by="system"))
122
+
123
+ @app.put(
124
+ "/api/v1/roles/bulk",
125
+ response_model=list[RoleResponse],
126
+ )
127
+ async def update_role_bulk(role_ids: list[str], data: RoleUpdate):
128
+ return await auth_client.update_role_bulk(
129
+ role_ids, data.with_audit(updated_by="system")
130
+ )
131
+
132
+ @app.put(
133
+ "/api/v1/roles/{role_id}",
134
+ response_model=RoleResponse,
135
+ )
136
+ async def update_role(role_id: str, data: RoleUpdate):
137
+ return await auth_client.update_role(data.with_audit(updated_by="system"))
138
+
139
+ @app.delete(
140
+ "/api/v1/roles/bulk",
141
+ response_model=list[RoleResponse],
142
+ )
143
+ async def delete_role_bulk(role_ids: list[str]):
144
+ return await auth_client.delete_role_bulk(role_ids, deleted_by="system")
145
+
146
+ @app.delete(
147
+ "/api/v1/roles/{role_id}",
148
+ response_model=RoleResponse,
149
+ )
150
+ async def delete_role(role_id: str):
151
+ return await auth_client.delete_role(role_id, deleted_by="system")
152
+
153
+ # User routes
154
+
155
+ @app.get("/api/v1/users", response_model=MultipleUserResponse)
156
+ async def get_users(
157
+ page: int = 1,
158
+ page_size: int = 10,
159
+ sort: str | None = None,
160
+ filter: str | None = None,
161
+ ) -> MultipleUserResponse:
162
+ return await auth_client.get_users(
163
+ page=page, page_size=page_size, sort=sort, filter=filter
164
+ )
17
165
 
18
166
  @app.get("/api/v1/users/{user_id}", response_model=UserResponse)
19
167
  async def get_user_by_id(user_id: str) -> UserResponse:
20
168
  return await auth_client.get_user_by_id(user_id)
21
169
 
22
- @app.post("/api/v1/users", response_model=UserResponse | list[UserResponse])
23
- async def create_user(data: UserCreate | list[UserCreate]):
24
- if isinstance(data, UserCreate):
25
- data_dict = data.model_dump(exclude_unset=True)
26
- audited_data = UserCreateWithAudit(**data_dict, created_by="system")
27
- return await auth_client.create_user(audited_data)
28
- audited_data = [
29
- UserCreateWithAudit(
30
- **row.model_dump(exclude_unset=True), created_by="system"
31
- )
32
- for row in data
33
- ]
34
- return await auth_client.create_user(audited_data)
35
-
36
- @app.put("/api/v1/users/{user_id}", response_model=UserResponse)
37
- async def update_user(user_id: str, data: UserUpdate) -> UserResponse:
38
- data_dict = data.model_dump(exclude_unset=True)
39
- audited_data = UserUpdateWithAudit(**data_dict, updated_by="system")
40
- return await auth_client.update_user(user_id, audited_data)
41
-
42
- @app.delete("/api/v1/users/{user_id}", response_model=UserResponse)
43
- async def delete_user(user_id: str) -> UserResponse:
170
+ @app.post(
171
+ "/api/v1/users/bulk",
172
+ response_model=list[UserResponse],
173
+ )
174
+ async def create_user_bulk(data: list[UserCreate]):
175
+ return await auth_client.create_user(
176
+ [row.with_audit(created_by="system") for row in data]
177
+ )
178
+
179
+ @app.post(
180
+ "/api/v1/users",
181
+ response_model=UserResponse,
182
+ )
183
+ async def create_user(data: UserCreate):
184
+ return await auth_client.create_user(data.with_audit(created_by="system"))
185
+
186
+ @app.put(
187
+ "/api/v1/users/bulk",
188
+ response_model=list[UserResponse],
189
+ )
190
+ async def update_user_bulk(user_ids: list[str], data: UserUpdate):
191
+ return await auth_client.update_user_bulk(
192
+ user_ids, data.with_audit(updated_by="system")
193
+ )
194
+
195
+ @app.put(
196
+ "/api/v1/users/{user_id}",
197
+ response_model=UserResponse,
198
+ )
199
+ async def update_user(user_id: str, data: UserUpdate):
200
+ return await auth_client.update_user(data.with_audit(updated_by="system"))
201
+
202
+ @app.delete(
203
+ "/api/v1/users/bulk",
204
+ response_model=list[UserResponse],
205
+ )
206
+ async def delete_user_bulk(user_ids: list[str]):
207
+ return await auth_client.delete_user_bulk(user_ids, deleted_by="system")
208
+
209
+ @app.delete(
210
+ "/api/v1/users/{user_id}",
211
+ response_model=UserResponse,
212
+ )
213
+ async def delete_user(user_id: str):
44
214
  return await auth_client.delete_user(user_id, deleted_by="system")
@@ -2,7 +2,7 @@ import os
2
2
  from typing import Any
3
3
 
4
4
  from fastapi.responses import HTMLResponse
5
- from my_app_name.common.view import render_page, render_str
5
+ from my_app_name.common.util.view import render_page, render_str
6
6
  from my_app_name.config import (
7
7
  APP_GATEWAY_CSS_PATH_LIST,
8
8
  APP_GATEWAY_FAVICON_PATH,
@@ -3,4 +3,4 @@ alembic~=1.14.0
3
3
  sqlmodel~=0.0.22
4
4
  ulid-py~=1.1.0
5
5
  passlib~=1.7.4
6
- Jinja2==3.1.4
6
+ Jinja2==3.1.5
@@ -1,6 +1,7 @@
1
1
  import datetime
2
2
 
3
3
  import ulid
4
+ from pydantic import BaseModel
4
5
  from sqlmodel import Field, SQLModel
5
6
 
6
7
 
@@ -11,6 +12,9 @@ class PermissionBase(SQLModel):
11
12
  class PermissionCreate(PermissionBase):
12
13
  description: str
13
14
 
15
+ def with_audit(self, created_by: str) -> "PermissionCreateWithAudit":
16
+ return PermissionCreateWithAudit(**self.model_dump(), created_by=created_by)
17
+
14
18
 
15
19
  class PermissionCreateWithAudit(PermissionCreate):
16
20
  created_by: str
@@ -20,6 +24,9 @@ class PermissionUpdate(SQLModel):
20
24
  name: str | None = None
21
25
  description: str | None = None
22
26
 
27
+ def with_audit(self, updated_by: str) -> "PermissionUpdateWithAudit":
28
+ return PermissionUpdateWithAudit(**self.model_dump(), updated_by=updated_by)
29
+
23
30
 
24
31
  class PermissionUpdateWithAudit(PermissionUpdate):
25
32
  updated_by: str
@@ -29,11 +36,16 @@ class PermissionResponse(PermissionBase):
29
36
  id: str
30
37
 
31
38
 
39
+ class MultiplePermissionResponse(BaseModel):
40
+ data: list[PermissionResponse]
41
+ count: int
42
+
43
+
32
44
  class Permission(SQLModel, table=True):
33
45
  id: str = Field(default_factory=lambda: ulid.new().str, primary_key=True)
34
- created_at: datetime.datetime | None
35
- created_by: str | None
36
- updated_at: datetime.datetime | None
37
- updated_by: str | None
38
- name: str
46
+ created_at: datetime.datetime | None = Field(index=True)
47
+ created_by: str | None = Field(index=True)
48
+ updated_at: datetime.datetime | None = Field(index=True)
49
+ updated_by: str | None = Field(index=True)
50
+ name: str = Field(index=True)
39
51
  description: str
@@ -1,6 +1,8 @@
1
1
  import datetime
2
2
 
3
3
  import ulid
4
+ from my_app_name.schema.permission import Permission
5
+ from pydantic import BaseModel
4
6
  from sqlmodel import Field, SQLModel
5
7
 
6
8
 
@@ -11,15 +13,45 @@ class RoleBase(SQLModel):
11
13
  class RoleCreate(RoleBase):
12
14
  description: str
13
15
 
16
+ def with_audit(self, created_by: str) -> "RoleCreateWithAudit":
17
+ return RoleCreateWithAudit(**self.model_dump(), created_by=created_by)
18
+
14
19
 
15
20
  class RoleCreateWithAudit(RoleCreate):
16
21
  created_by: str
17
22
 
18
23
 
24
+ class RoleCreateWithPermissions(RoleCreate):
25
+ permissions: list[str] | None = None
26
+
27
+ def with_audit(self, created_by: str) -> "RoleCreateWithPermissionsAndAudit":
28
+ return RoleCreateWithPermissionsAndAudit(
29
+ **self.model_dump(), created_by=created_by
30
+ )
31
+
32
+
33
+ class RoleCreateWithPermissionsAndAudit(RoleCreateWithPermissions):
34
+ created_by: str
35
+
36
+ def get_role_create_with_audit(self) -> RoleCreateWithAudit:
37
+ data = {
38
+ key: val for key, val in self.model_dump().items() if key != "permissions"
39
+ }
40
+ return RoleCreateWithAudit(**data)
41
+
42
+ def get_permission_names(self) -> list[str]:
43
+ if self.permissions is None:
44
+ return []
45
+ return self.permissions
46
+
47
+
19
48
  class RoleUpdate(SQLModel):
20
49
  name: str | None = None
21
50
  description: str | None = None
22
51
 
52
+ def with_audit(self, updated_by: str) -> "RoleUpdateWithAudit":
53
+ return RoleUpdateWithAudit(**self.model_dump(), updated_by=updated_by)
54
+
23
55
 
24
56
  class RoleUpdateWithAudit(RoleUpdate):
25
57
  updated_by: str
@@ -27,13 +59,27 @@ class RoleUpdateWithAudit(RoleUpdate):
27
59
 
28
60
  class RoleResponse(RoleBase):
29
61
  id: str
62
+ permissions: list[Permission]
63
+
64
+
65
+ class MultipleRoleResponse(BaseModel):
66
+ data: list[RoleResponse]
67
+ count: int
30
68
 
31
69
 
32
70
  class Role(SQLModel, table=True):
33
71
  id: str = Field(default_factory=lambda: ulid.new().str, primary_key=True)
72
+ created_at: datetime.datetime | None = Field(index=True)
73
+ created_by: str | None = Field(index=True)
74
+ updated_at: datetime.datetime | None = Field(index=True)
75
+ updated_by: str | None = Field(index=True)
76
+ name: str = Field(index=True)
77
+ description: str
78
+
79
+
80
+ class RolePermission(SQLModel, table=True):
81
+ id: str = Field(default_factory=lambda: ulid.new().str, primary_key=True)
82
+ role_id: str = Field(index=True)
83
+ permission_id: str = Field(index=True)
34
84
  created_at: datetime.datetime | None
35
85
  created_by: str | None
36
- updated_at: datetime.datetime | None
37
- updated_by: str | None
38
- name: str
39
- description: str
@@ -0,0 +1,52 @@
1
+ import datetime
2
+
3
+ import ulid
4
+ from pydantic import BaseModel
5
+ from sqlmodel import Field, SQLModel
6
+
7
+
8
+ class SessionBase(SQLModel):
9
+ user_id: str
10
+ device: str
11
+ os: str
12
+ browser: str
13
+ expired_at: datetime.datetime | None
14
+
15
+
16
+ class SessionCreate(SessionBase):
17
+
18
+ def with_audit(self, created_by: str) -> "SessionCreateWithAudit":
19
+ return SessionCreateWithAudit(**self.model_dump(), created_by=created_by)
20
+
21
+
22
+ class SessionCreateWithAudit(SessionCreate):
23
+ created_by: str
24
+
25
+
26
+ class SessionUpdate(SessionBase):
27
+
28
+ def with_audit(self, updated_by: str) -> "SessionUpdateWithAudit":
29
+ return SessionUpdateWithAudit(**self.model_dump(), updated_by=updated_by)
30
+
31
+
32
+ class SessionUpdateWithAudit(SessionUpdate):
33
+ updated_by: str
34
+
35
+
36
+ class SessionResponse(SessionBase):
37
+ id: str
38
+ created_at: datetime.datetime = Field(index=True)
39
+ updated_at: datetime.datetime | None = Field(index=True)
40
+
41
+
42
+ class MultipleSessionResponse(BaseModel):
43
+ data: list[SessionResponse]
44
+ count: int
45
+
46
+
47
+ class Session(SQLModel, table=True):
48
+ id: str = Field(default_factory=lambda: ulid.new().str, primary_key=True)
49
+ user_id: str = Field(index=True)
50
+ device: str
51
+ os: str
52
+ browser: str
@@ -1,6 +1,9 @@
1
1
  import datetime
2
2
 
3
3
  import ulid
4
+ from my_app_name.schema.permission import Permission
5
+ from my_app_name.schema.role import Role
6
+ from pydantic import BaseModel
4
7
  from sqlmodel import Field, SQLModel
5
8
 
6
9
 
@@ -10,6 +13,10 @@ class UserBase(SQLModel):
10
13
 
11
14
  class UserCreate(UserBase):
12
15
  password: str
16
+ roles: list[str] | None = None
17
+
18
+ def with_audit(self, created_by: str) -> "UserCreateWithAudit":
19
+ return UserCreateWithAudit(**self.model_dump(), created_by=created_by)
13
20
 
14
21
 
15
22
  class UserCreateWithAudit(UserCreate):
@@ -20,6 +27,9 @@ class UserUpdate(SQLModel):
20
27
  username: str | None = None
21
28
  password: str | None = None
22
29
 
30
+ def with_audit(self, updated_by: str) -> "UserUpdateWithAudit":
31
+ return UserUpdateWithAudit(**self.model_dump(), updated_by=updated_by)
32
+
23
33
 
24
34
  class UserUpdateWithAudit(UserUpdate):
25
35
  updated_by: str
@@ -27,13 +37,28 @@ class UserUpdateWithAudit(UserUpdate):
27
37
 
28
38
  class UserResponse(UserBase):
29
39
  id: str
40
+ roles: list[Role]
41
+ permissions: list[Permission]
42
+
43
+
44
+ class MultipleUserResponse(BaseModel):
45
+ data: list[UserResponse]
46
+ count: int
30
47
 
31
48
 
32
49
  class User(SQLModel, table=True):
33
50
  id: str = Field(default_factory=lambda: ulid.new().str, primary_key=True)
34
- created_at: datetime.datetime
35
- created_by: str
36
- updated_at: datetime.datetime
37
- updated_by: str
38
- username: str
51
+ created_at: datetime.datetime = Field(index=True)
52
+ created_by: str = Field(index=True)
53
+ updated_at: datetime.datetime | None = Field(index=True)
54
+ updated_by: str | None = Field(index=True)
55
+ username: str = Field(index=True)
39
56
  password: str
57
+
58
+
59
+ class UserRole(SQLModel, table=True):
60
+ id: str = Field(default_factory=lambda: ulid.new().str, primary_key=True)
61
+ user_id: str = Field(index=True)
62
+ role_id: str = Field(index=True)
63
+ created_at: datetime.datetime | None
64
+ created_by: str | None