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.
- zrb/__main__.py +0 -3
- zrb/builtin/__init__.py +3 -0
- zrb/builtin/group.py +1 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/config.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +66 -21
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +67 -41
- 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
- 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
- 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
- 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
- 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
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/schema/my_entity.py +16 -6
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/client_method.py +57 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/gateway_subroute.py +63 -28
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_task.py +1 -0
- 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
- 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
- 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
- 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
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/route.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/module_task_definition.py +2 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task.py +4 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/util.py +47 -20
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/app_factory.py +29 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_db_repository.py +185 -101
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_service.py +99 -108
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/{db_engine.py → db_engine_factory.py} +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/error.py +12 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/logger_factory.py +10 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/parser_factory.py +7 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/app.py +47 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/parser.py +105 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/user_agent.py +58 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/main.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_api_client.py +16 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client.py +163 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client_factory.py +9 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_direct_client.py +15 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_auth_tables.py +160 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration_metadata.py +18 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/route.py +5 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service.py +117 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/permission_service_factory.py +11 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_db_repository.py +26 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository.py +61 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission/repository/permission_repository_factory.py +13 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/__init__.py +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_db_repository.py +75 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository.py +59 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository_factory.py +13 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service.py +105 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/role_service_factory.py +7 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_db_repository.py +42 -13
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository.py +38 -17
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository_factory.py +2 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service.py +69 -17
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service_factory.py +2 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/route.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +198 -28
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/view.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/permission.py +17 -5
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/role.py +50 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/session.py +52 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/user.py +30 -5
- zrb/builtin/random.py +61 -0
- zrb/cmd/cmd_val.py +6 -5
- zrb/runner/cli.py +10 -1
- zrb/runner/web_util/token.py +7 -3
- zrb/task/base_task.py +24 -2
- zrb/task/cmd_task.py +7 -5
- zrb/util/cmd/command.py +1 -0
- zrb/util/file.py +7 -1
- {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/METADATA +1 -1
- {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/RECORD +80 -61
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/any_client_method.py +0 -27
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/api_client.py +0 -6
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/direct_client.py +0 -5
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/my_module/client/factory.py +0 -9
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/app.py +0 -57
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/any_client.py +0 -33
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/api_client.py +0 -7
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/direct_client.py +0 -6
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/factory.py +0 -9
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_user_table.py +0 -37
- /zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/{view.py → util/view.py} +0 -0
- {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/WHEEL +0 -0
- {zrb-1.0.0b1.dist-info → zrb-1.0.0b2.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
import os
|
2
|
+
from contextlib import asynccontextmanager
|
3
|
+
|
4
|
+
from fastapi import FastAPI, HTTPException
|
5
|
+
from fastapi.openapi.docs import get_swagger_ui_html
|
6
|
+
from fastapi.responses import FileResponse
|
7
|
+
from fastapi.staticfiles import StaticFiles
|
8
|
+
from sqlalchemy.engine import Engine
|
9
|
+
from sqlmodel import SQLModel
|
10
|
+
from starlette.types import Lifespan
|
11
|
+
|
12
|
+
|
13
|
+
def get_default_app_title(app_title: str, mode: str, modules: list[str] = []) -> str:
|
14
|
+
if mode == "monolith":
|
15
|
+
return app_title
|
16
|
+
return f"{app_title} - {', '.join(modules)}"
|
17
|
+
|
18
|
+
|
19
|
+
def create_default_app_lifespan(db_engine: Engine) -> Lifespan:
|
20
|
+
@asynccontextmanager
|
21
|
+
async def default_app_lifespan(app: FastAPI):
|
22
|
+
SQLModel.metadata.create_all(db_engine)
|
23
|
+
yield
|
24
|
+
|
25
|
+
return default_app_lifespan
|
26
|
+
|
27
|
+
|
28
|
+
def serve_static_dir(app: FastAPI, static_dir: str):
|
29
|
+
app.mount("/static", StaticFiles(directory=static_dir), name="static")
|
30
|
+
|
31
|
+
# Serve static files
|
32
|
+
@app.get("/static/{file_path:path}", include_in_schema=False)
|
33
|
+
async def static_files(file_path: str):
|
34
|
+
full_path = os.path.join(static_dir, file_path)
|
35
|
+
if os.path.isfile(full_path):
|
36
|
+
return FileResponse(full_path)
|
37
|
+
raise HTTPException(status_code=404, detail="File not found")
|
38
|
+
|
39
|
+
|
40
|
+
def serve_docs(app: FastAPI, app_title: str, favicon_url: str):
|
41
|
+
@app.get("/docs", include_in_schema=False)
|
42
|
+
async def swagger_ui_html():
|
43
|
+
return get_swagger_ui_html(
|
44
|
+
openapi_url="/openapi.json",
|
45
|
+
title=app_title,
|
46
|
+
swagger_favicon_url=favicon_url,
|
47
|
+
)
|
@@ -0,0 +1,105 @@
|
|
1
|
+
import re
|
2
|
+
from typing import Callable
|
3
|
+
|
4
|
+
from sqlalchemy import asc, desc
|
5
|
+
from sqlalchemy.sql import ClauseElement, ColumnElement
|
6
|
+
from sqlmodel import SQLModel
|
7
|
+
|
8
|
+
|
9
|
+
def create_default_sort_param_parser() -> (
|
10
|
+
Callable[[SQLModel, str], list[ColumnElement]]
|
11
|
+
):
|
12
|
+
def parse_sort_param(model: SQLModel, query: str) -> list[ColumnElement]:
|
13
|
+
"""
|
14
|
+
Parse the sort parameter and return a list of SQLAlchemy ColumnElement objects.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
model (Type[SQLModel]): The SQLModel class to be queried.
|
18
|
+
query (str): A comma-separated string of fields to sort by.
|
19
|
+
Prefix a field with '-' for descending order.
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
list[ColumnElement]: A list of SQLAlchemy ColumnElement objects representing the sort order.
|
23
|
+
|
24
|
+
Example:
|
25
|
+
parse_sort_param(UserModel, "name,-age")
|
26
|
+
# Returns [asc(UserModel.name), desc(UserModel.age)]
|
27
|
+
"""
|
28
|
+
sorts: list[ColumnElement] = []
|
29
|
+
sort_parts = query.split(",")
|
30
|
+
for part in sort_parts:
|
31
|
+
if part.startswith("-"):
|
32
|
+
key = part[1:]
|
33
|
+
order = desc
|
34
|
+
else:
|
35
|
+
key = part
|
36
|
+
order = asc
|
37
|
+
if hasattr(model, key):
|
38
|
+
sorts.append(order(getattr(model, key)))
|
39
|
+
return sorts
|
40
|
+
|
41
|
+
return parse_sort_param
|
42
|
+
|
43
|
+
|
44
|
+
def create_default_filter_param_parser() -> (
|
45
|
+
Callable[[SQLModel, str], list[ClauseElement]]
|
46
|
+
):
|
47
|
+
def parse_filter_param(model: SQLModel, query: str) -> list[ClauseElement]:
|
48
|
+
"""
|
49
|
+
Parse the filter parameter and return a list of SQLAlchemy ClauseElement objects.
|
50
|
+
|
51
|
+
Args:
|
52
|
+
model (Type[SQLModel]): The SQLModel class to be queried.
|
53
|
+
query (str): A comma-separated string of filters.
|
54
|
+
Each filter should be in the format "field:operator:value".
|
55
|
+
Use '\,' to escape commas within values.
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
list[ClauseElement]: A list of SQLAlchemy ClauseElement objects representing the filters.
|
59
|
+
|
60
|
+
Supported operators:
|
61
|
+
eq: Equal to
|
62
|
+
ne: Not equal to
|
63
|
+
gt: Greater than
|
64
|
+
gte: Greater than or equal to
|
65
|
+
lt: Less than
|
66
|
+
lte: Less than or equal to
|
67
|
+
like: SQL LIKE (use % for wildcards)
|
68
|
+
in: In a list of values (semicolon-separated)
|
69
|
+
|
70
|
+
Example:
|
71
|
+
parse_filter_param(UserModel, "age:gte:18,name:like:John%,role:in:admin;user,address:eq:123\, Main St.")
|
72
|
+
# Returns [UserModel.age >= 18, UserModel.name.like("John%"), UserModel.role.in_(["admin", "user"]), UserModel.address == "123, Main St."]
|
73
|
+
"""
|
74
|
+
filters: list[ClauseElement] = []
|
75
|
+
filter_parts = split_by_comma(query)
|
76
|
+
for part in filter_parts:
|
77
|
+
match = re.match(r"(.+):(.+):(.+)", part)
|
78
|
+
if match:
|
79
|
+
key, op, value = match.groups()
|
80
|
+
value = value.replace(r"\,", ",") # Unescape commas in the value
|
81
|
+
if hasattr(model, key):
|
82
|
+
column = getattr(model, key)
|
83
|
+
if op == "eq":
|
84
|
+
filters.append(column == value)
|
85
|
+
elif op == "ne":
|
86
|
+
filters.append(column != value)
|
87
|
+
elif op == "gt":
|
88
|
+
filters.append(column > value)
|
89
|
+
elif op == "gte":
|
90
|
+
filters.append(column >= value)
|
91
|
+
elif op == "lt":
|
92
|
+
filters.append(column < value)
|
93
|
+
elif op == "lte":
|
94
|
+
filters.append(column <= value)
|
95
|
+
elif op == "like":
|
96
|
+
filters.append(column.like(value))
|
97
|
+
elif op == "in":
|
98
|
+
filters.append(column.in_(value.split(";")))
|
99
|
+
return filters
|
100
|
+
|
101
|
+
return parse_filter_param
|
102
|
+
|
103
|
+
|
104
|
+
def split_by_comma(s: str, delimiter: str = ",") -> list[str]:
|
105
|
+
return re.split(r"(?<!\\)" + re.escape(delimiter), s)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import re
|
2
|
+
|
3
|
+
|
4
|
+
def get_os_from_user_agent(user_agent: str) -> str:
|
5
|
+
os_patterns = [
|
6
|
+
(r"Windows NT (\d+\.\d+)", "Windows"),
|
7
|
+
(r"Mac OS X (\d+[_\.]\d+)", "MacOS"),
|
8
|
+
(r"Android (\d+[\.\d]*)", "Android"),
|
9
|
+
(r"iPhone OS (\d+[_\.]\d+)", "iOS"),
|
10
|
+
(r"iPad.*OS (\d+[_\.]\d+)", "iPadOS"),
|
11
|
+
(r"Linux", "Linux"),
|
12
|
+
]
|
13
|
+
os = "Unknown OS"
|
14
|
+
# Match OS
|
15
|
+
for pattern, name in os_patterns:
|
16
|
+
match = re.search(pattern, user_agent)
|
17
|
+
if match:
|
18
|
+
os = (
|
19
|
+
f"{name} {match.group(1).replace('_', '.')}" if match.groups() else name
|
20
|
+
)
|
21
|
+
break
|
22
|
+
return os
|
23
|
+
|
24
|
+
|
25
|
+
def get_browser_from_user_agent(user_agent: str) -> str:
|
26
|
+
browser_patterns = [
|
27
|
+
(r"Chrome/([\d\.]+)", "Chrome"),
|
28
|
+
(r"Firefox/([\d\.]+)", "Firefox"),
|
29
|
+
(r"Edg/([\d\.]+)", "Edge"),
|
30
|
+
(r"Safari/([\d\.]+)", "Safari"),
|
31
|
+
]
|
32
|
+
browser = "Unknown Browser"
|
33
|
+
# Match Browser
|
34
|
+
for pattern, name in browser_patterns:
|
35
|
+
match = re.search(pattern, user_agent)
|
36
|
+
if match:
|
37
|
+
browser = f"{name} {match.group(1)}"
|
38
|
+
break
|
39
|
+
return browser
|
40
|
+
|
41
|
+
|
42
|
+
def get_device_from_user_agent(user_agent: str):
|
43
|
+
device_patterns = [
|
44
|
+
(r"iPhone", "iPhone"),
|
45
|
+
(r"iPad", "iPad"),
|
46
|
+
(r"Android.*Mobile", "Android Phone"),
|
47
|
+
(r"Android", "Android Tablet"),
|
48
|
+
(r"Macintosh", "Mac"),
|
49
|
+
(r"Windows NT", "Windows PC"),
|
50
|
+
(r"Linux", "Linux Device"),
|
51
|
+
]
|
52
|
+
device = "Unknown Device"
|
53
|
+
# Match Device
|
54
|
+
for pattern, name in device_patterns:
|
55
|
+
if re.search(pattern, user_agent):
|
56
|
+
device = name
|
57
|
+
break
|
58
|
+
return device
|
@@ -39,7 +39,7 @@ APP_COMMUNICATION = os.getenv(
|
|
39
39
|
)
|
40
40
|
APP_REPOSITORY_TYPE = os.getenv("APP_REPOSITORY_TYPE", "db")
|
41
41
|
APP_DB_URL = os.getenv(
|
42
|
-
"
|
42
|
+
"MY_APP_NAME_DB_URL",
|
43
43
|
(
|
44
44
|
f"sqlite:///{APP_PATH}/monolith.db"
|
45
45
|
if APP_MODE == "monolith" or len(APP_MODULES) == 0
|
zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_api_client.py
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
from my_app_name.config import APP_AUTH_BASE_URL
|
2
|
+
from my_app_name.module.auth.client.auth_client import AuthClient
|
3
|
+
from my_app_name.module.auth.service.permission.permission_service_factory import (
|
4
|
+
permission_service,
|
5
|
+
)
|
6
|
+
from my_app_name.module.auth.service.role.role_service_factory import role_service
|
7
|
+
from my_app_name.module.auth.service.user.user_service_factory import user_service
|
8
|
+
|
9
|
+
|
10
|
+
class AuthAPIClient(
|
11
|
+
permission_service.as_api_client(base_url=APP_AUTH_BASE_URL),
|
12
|
+
role_service.as_api_client(base_url=APP_AUTH_BASE_URL),
|
13
|
+
user_service.as_api_client(base_url=APP_AUTH_BASE_URL),
|
14
|
+
AuthClient,
|
15
|
+
):
|
16
|
+
pass
|
zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/client/auth_client.py
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
from abc import ABC, abstractmethod
|
2
|
+
|
3
|
+
from my_app_name.schema.permission import (
|
4
|
+
MultiplePermissionResponse,
|
5
|
+
PermissionCreateWithAudit,
|
6
|
+
PermissionResponse,
|
7
|
+
PermissionUpdateWithAudit,
|
8
|
+
)
|
9
|
+
from my_app_name.schema.role import (
|
10
|
+
MultipleRoleResponse,
|
11
|
+
RoleCreateWithAudit,
|
12
|
+
RoleResponse,
|
13
|
+
RoleUpdateWithAudit,
|
14
|
+
)
|
15
|
+
from my_app_name.schema.user import (
|
16
|
+
MultipleUserResponse,
|
17
|
+
UserCreateWithAudit,
|
18
|
+
UserResponse,
|
19
|
+
UserUpdateWithAudit,
|
20
|
+
)
|
21
|
+
|
22
|
+
|
23
|
+
class AuthClient(ABC):
|
24
|
+
|
25
|
+
# Permission related methods
|
26
|
+
|
27
|
+
@abstractmethod
|
28
|
+
async def get_permission_by_id(self, permission_id: str) -> PermissionResponse:
|
29
|
+
"""Get permission by id"""
|
30
|
+
|
31
|
+
@abstractmethod
|
32
|
+
async def get_permissions(
|
33
|
+
self,
|
34
|
+
page: int = 1,
|
35
|
+
page_size: int = 10,
|
36
|
+
sort: str | None = None,
|
37
|
+
filter: str | None = None,
|
38
|
+
) -> MultiplePermissionResponse:
|
39
|
+
"""Get permissions by filter and sort"""
|
40
|
+
|
41
|
+
@abstractmethod
|
42
|
+
async def create_permission(
|
43
|
+
self, data: PermissionCreateWithAudit
|
44
|
+
) -> PermissionResponse:
|
45
|
+
"""Create a new permission"""
|
46
|
+
|
47
|
+
@abstractmethod
|
48
|
+
async def create_permission(
|
49
|
+
self, data: list[PermissionCreateWithAudit]
|
50
|
+
) -> list[PermissionResponse]:
|
51
|
+
"""Create new permissions"""
|
52
|
+
|
53
|
+
@abstractmethod
|
54
|
+
async def update_permission_bulk(
|
55
|
+
self, permission_ids: list[str], data: PermissionUpdateWithAudit
|
56
|
+
) -> PermissionResponse:
|
57
|
+
"""Update some permissions"""
|
58
|
+
|
59
|
+
@abstractmethod
|
60
|
+
async def update_permission(
|
61
|
+
self, permission_id: str, data: PermissionUpdateWithAudit
|
62
|
+
) -> PermissionResponse:
|
63
|
+
"""Update a permission"""
|
64
|
+
|
65
|
+
@abstractmethod
|
66
|
+
async def delete_permission_bulk(
|
67
|
+
self, permission_ids: str, deleted_by: str
|
68
|
+
) -> PermissionResponse:
|
69
|
+
"""Delete some permissions"""
|
70
|
+
|
71
|
+
@abstractmethod
|
72
|
+
async def delete_permission(
|
73
|
+
self, permission_id: str, deleted_by: str
|
74
|
+
) -> PermissionResponse:
|
75
|
+
"""Delete a permission"""
|
76
|
+
|
77
|
+
# Role related methods
|
78
|
+
|
79
|
+
@abstractmethod
|
80
|
+
async def get_role_by_id(self, role_id: str) -> RoleResponse:
|
81
|
+
"""Get role by id"""
|
82
|
+
|
83
|
+
@abstractmethod
|
84
|
+
async def get_roles(
|
85
|
+
self,
|
86
|
+
page: int = 1,
|
87
|
+
page_size: int = 10,
|
88
|
+
sort: str | None = None,
|
89
|
+
filter: str | None = None,
|
90
|
+
) -> MultipleRoleResponse:
|
91
|
+
"""Get roles by filter and sort"""
|
92
|
+
|
93
|
+
@abstractmethod
|
94
|
+
async def create_role(self, data: RoleCreateWithAudit) -> RoleResponse:
|
95
|
+
"""Create a new role"""
|
96
|
+
|
97
|
+
@abstractmethod
|
98
|
+
async def create_role(self, data: list[RoleCreateWithAudit]) -> list[RoleResponse]:
|
99
|
+
"""Create new roles"""
|
100
|
+
|
101
|
+
@abstractmethod
|
102
|
+
async def update_role_bulk(
|
103
|
+
self, role_ids: list[str], data: RoleUpdateWithAudit
|
104
|
+
) -> RoleResponse:
|
105
|
+
"""Update some roles"""
|
106
|
+
|
107
|
+
@abstractmethod
|
108
|
+
async def update_role(
|
109
|
+
self, role_id: str, data: RoleUpdateWithAudit
|
110
|
+
) -> RoleResponse:
|
111
|
+
"""Update a role"""
|
112
|
+
|
113
|
+
@abstractmethod
|
114
|
+
async def delete_role_bulk(self, role_ids: str, deleted_by: str) -> RoleResponse:
|
115
|
+
"""Delete some roles"""
|
116
|
+
|
117
|
+
@abstractmethod
|
118
|
+
async def delete_role(self, role_id: str, deleted_by: str) -> RoleResponse:
|
119
|
+
"""Delete a role"""
|
120
|
+
|
121
|
+
# User related methods
|
122
|
+
|
123
|
+
@abstractmethod
|
124
|
+
async def get_user_by_id(self, user_id: str) -> UserResponse:
|
125
|
+
"""Get user by id"""
|
126
|
+
|
127
|
+
@abstractmethod
|
128
|
+
async def get_users(
|
129
|
+
self,
|
130
|
+
page: int = 1,
|
131
|
+
page_size: int = 10,
|
132
|
+
sort: str | None = None,
|
133
|
+
filter: str | None = None,
|
134
|
+
) -> MultipleUserResponse:
|
135
|
+
"""Get users by filter and sort"""
|
136
|
+
|
137
|
+
@abstractmethod
|
138
|
+
async def create_user(self, data: UserCreateWithAudit) -> UserResponse:
|
139
|
+
"""Create a new user"""
|
140
|
+
|
141
|
+
@abstractmethod
|
142
|
+
async def create_user(self, data: list[UserCreateWithAudit]) -> list[UserResponse]:
|
143
|
+
"""Create new users"""
|
144
|
+
|
145
|
+
@abstractmethod
|
146
|
+
async def update_user_bulk(
|
147
|
+
self, user_ids: list[str], data: UserUpdateWithAudit
|
148
|
+
) -> UserResponse:
|
149
|
+
"""Update some users"""
|
150
|
+
|
151
|
+
@abstractmethod
|
152
|
+
async def update_user(
|
153
|
+
self, user_id: str, data: UserUpdateWithAudit
|
154
|
+
) -> UserResponse:
|
155
|
+
"""Update a user"""
|
156
|
+
|
157
|
+
@abstractmethod
|
158
|
+
async def delete_user_bulk(self, user_ids: str, deleted_by: str) -> UserResponse:
|
159
|
+
"""Delete some users"""
|
160
|
+
|
161
|
+
@abstractmethod
|
162
|
+
async def delete_user(self, user_id: str, deleted_by: str) -> UserResponse:
|
163
|
+
"""Delete a user"""
|
@@ -0,0 +1,9 @@
|
|
1
|
+
from my_app_name.config import APP_COMMUNICATION
|
2
|
+
from my_app_name.module.auth.client.auth_api_client import AuthAPIClient
|
3
|
+
from my_app_name.module.auth.client.auth_client import AuthClient
|
4
|
+
from my_app_name.module.auth.client.auth_direct_client import AuthDirectClient
|
5
|
+
|
6
|
+
if APP_COMMUNICATION == "direct":
|
7
|
+
auth_client: AuthClient = AuthDirectClient()
|
8
|
+
elif APP_COMMUNICATION == "api":
|
9
|
+
auth_client: AuthClient = AuthAPIClient()
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from my_app_name.module.auth.client.auth_client import AuthClient
|
2
|
+
from my_app_name.module.auth.service.permission.permission_service_factory import (
|
3
|
+
permission_service,
|
4
|
+
)
|
5
|
+
from my_app_name.module.auth.service.role.role_service_factory import role_service
|
6
|
+
from my_app_name.module.auth.service.user.user_service_factory import user_service
|
7
|
+
|
8
|
+
|
9
|
+
class AuthDirectClient(
|
10
|
+
permission_service.as_direct_client(),
|
11
|
+
role_service.as_direct_client(),
|
12
|
+
user_service.as_direct_client(),
|
13
|
+
AuthClient,
|
14
|
+
):
|
15
|
+
pass
|
@@ -0,0 +1,160 @@
|
|
1
|
+
"""Add user table
|
2
|
+
|
3
|
+
Revision ID: 3093c7336477
|
4
|
+
Revises:
|
5
|
+
Create Date: 2024-11-20 05:57:01.684118
|
6
|
+
|
7
|
+
"""
|
8
|
+
|
9
|
+
from typing import Sequence, Union
|
10
|
+
|
11
|
+
import sqlalchemy as sa
|
12
|
+
import sqlmodel
|
13
|
+
from alembic import op
|
14
|
+
|
15
|
+
# revision identifiers, used by Alembic.
|
16
|
+
revision: str = "3093c7336477"
|
17
|
+
down_revision: Union[str, None] = None
|
18
|
+
branch_labels: Union[str, Sequence[str], None] = None
|
19
|
+
depends_on: Union[str, Sequence[str], None] = None
|
20
|
+
|
21
|
+
|
22
|
+
def upgrade() -> None:
|
23
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
24
|
+
op.create_table(
|
25
|
+
"permission",
|
26
|
+
sa.Column("id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
27
|
+
sa.Column("created_at", sa.DateTime(), nullable=True),
|
28
|
+
sa.Column("created_by", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
29
|
+
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
30
|
+
sa.Column("updated_by", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
31
|
+
sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
32
|
+
sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
33
|
+
sa.PrimaryKeyConstraint("id"),
|
34
|
+
)
|
35
|
+
op.create_index(op.f("ix_permission_name"), "permission", ["name"], unique=False)
|
36
|
+
op.create_index(
|
37
|
+
op.f("ix_permission_created_at"), "permission", ["created_at"], unique=False
|
38
|
+
)
|
39
|
+
op.create_index(
|
40
|
+
op.f("ix_permission_created_by"), "permission", ["created_by"], unique=False
|
41
|
+
)
|
42
|
+
op.create_index(
|
43
|
+
op.f("ix_permission_updated_at"), "permission", ["updated_at"], unique=False
|
44
|
+
)
|
45
|
+
op.create_index(
|
46
|
+
op.f("ix_permission_updated_by"), "permission", ["updated_by"], unique=False
|
47
|
+
)
|
48
|
+
|
49
|
+
op.create_table(
|
50
|
+
"role",
|
51
|
+
sa.Column("id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
52
|
+
sa.Column("created_at", sa.DateTime(), nullable=True),
|
53
|
+
sa.Column("created_by", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
54
|
+
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
55
|
+
sa.Column("updated_by", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
56
|
+
sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
57
|
+
sa.Column("description", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
58
|
+
sa.PrimaryKeyConstraint("id"),
|
59
|
+
)
|
60
|
+
op.create_index(op.f("ix_role_name"), "role", ["name"], unique=False)
|
61
|
+
op.create_index(op.f("ix_role_created_at"), "role", ["created_at"], unique=False)
|
62
|
+
op.create_index(op.f("ix_role_created_by"), "role", ["created_by"], unique=False)
|
63
|
+
op.create_index(op.f("ix_role_updated_at"), "role", ["updated_at"], unique=False)
|
64
|
+
op.create_index(op.f("ix_role_updated_by"), "role", ["updated_by"], unique=False)
|
65
|
+
|
66
|
+
op.create_table(
|
67
|
+
"rolepermission",
|
68
|
+
sa.Column("id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
69
|
+
sa.Column("role_id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
70
|
+
sa.Column("permission_id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
71
|
+
sa.Column("created_at", sa.DateTime(), nullable=True),
|
72
|
+
sa.Column("created_by", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
73
|
+
sa.PrimaryKeyConstraint("id"),
|
74
|
+
)
|
75
|
+
op.create_index(
|
76
|
+
op.f("ix_rolepermission_permission_id"),
|
77
|
+
"rolepermission",
|
78
|
+
["permission_id"],
|
79
|
+
unique=False,
|
80
|
+
)
|
81
|
+
op.create_index(
|
82
|
+
op.f("ix_rolepermission_role_id"), "rolepermission", ["role_id"], unique=False
|
83
|
+
)
|
84
|
+
|
85
|
+
op.create_table(
|
86
|
+
"user",
|
87
|
+
sa.Column("id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
88
|
+
sa.Column("username", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
89
|
+
sa.Column("password", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
90
|
+
sa.Column("created_at", sa.DateTime(), nullable=False),
|
91
|
+
sa.Column("created_by", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
92
|
+
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
93
|
+
sa.Column("updated_by", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
94
|
+
sa.PrimaryKeyConstraint("id"),
|
95
|
+
)
|
96
|
+
op.create_index(op.f("ix_user_username"), "user", ["username"], unique=False)
|
97
|
+
op.create_index(op.f("ix_user_created_at"), "user", ["created_at"], unique=False)
|
98
|
+
op.create_index(op.f("ix_user_created_by"), "user", ["created_by"], unique=False)
|
99
|
+
op.create_index(op.f("ix_user_updated_at"), "user", ["updated_at"], unique=False)
|
100
|
+
op.create_index(op.f("ix_user_updated_by"), "user", ["updated_by"], unique=False)
|
101
|
+
|
102
|
+
op.create_table(
|
103
|
+
"userrole",
|
104
|
+
sa.Column("id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
105
|
+
sa.Column("user_id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
106
|
+
sa.Column("role_id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
107
|
+
sa.Column("created_at", sa.DateTime(), nullable=True),
|
108
|
+
sa.Column("created_by", sqlmodel.sql.sqltypes.AutoString(), nullable=True),
|
109
|
+
sa.PrimaryKeyConstraint("id"),
|
110
|
+
)
|
111
|
+
op.create_index(op.f("ix_userrole_role_id"), "userrole", ["role_id"], unique=False)
|
112
|
+
op.create_index(op.f("ix_userrole_user_id"), "userrole", ["user_id"], unique=False)
|
113
|
+
|
114
|
+
op.create_table(
|
115
|
+
"session",
|
116
|
+
sa.Column("id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
117
|
+
sa.Column("user_id", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
118
|
+
sa.Column("device", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
119
|
+
sa.Column("os", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
120
|
+
sa.Column("browser", sqlmodel.sql.sqltypes.AutoString(), nullable=False),
|
121
|
+
sa.PrimaryKeyConstraint("id"),
|
122
|
+
)
|
123
|
+
op.create_index(op.f("ix_session_user_id"), "session", ["user_id"], unique=False)
|
124
|
+
# ### end Alembic commands ###
|
125
|
+
|
126
|
+
|
127
|
+
def downgrade() -> None:
|
128
|
+
# ### commands auto generated by Alembic - please adjust! ###
|
129
|
+
op.drop_index(op.f("ix_session_user_id"), table_name="session")
|
130
|
+
op.drop_table("session")
|
131
|
+
|
132
|
+
op.drop_index(op.f("ix_userrole_user_id"), table_name="userrole")
|
133
|
+
op.drop_index(op.f("ix_userrole_role_id"), table_name="userrole")
|
134
|
+
op.drop_table("userrole")
|
135
|
+
|
136
|
+
op.drop_index(op.f("ix_user_username"), table_name="user")
|
137
|
+
op.drop_index(op.f("ix_user_updated_by"), table_name="user")
|
138
|
+
op.drop_index(op.f("ix_user_updated_at"), table_name="user")
|
139
|
+
op.drop_index(op.f("ix_user_created_by"), table_name="user")
|
140
|
+
op.drop_index(op.f("ix_user_created_at"), table_name="user")
|
141
|
+
op.drop_table("user")
|
142
|
+
|
143
|
+
op.drop_index(op.f("ix_rolepermission_role_id"), table_name="rolepermission")
|
144
|
+
op.drop_index(op.f("ix_rolepermission_permission_id"), table_name="rolepermission")
|
145
|
+
op.drop_table("rolepermission")
|
146
|
+
|
147
|
+
op.drop_index(op.f("ix_role_name"), table_name="role")
|
148
|
+
op.drop_index(op.f("ix_role_updated_by"), table_name="role")
|
149
|
+
op.drop_index(op.f("ix_role_updated_at"), table_name="role")
|
150
|
+
op.drop_index(op.f("ix_role_created_by"), table_name="role")
|
151
|
+
op.drop_index(op.f("ix_role_created_at"), table_name="role")
|
152
|
+
op.drop_table("role")
|
153
|
+
|
154
|
+
op.drop_index(op.f("ix_permission_updated_by"), table_name="permission")
|
155
|
+
op.drop_index(op.f("ix_permission_updated_at"), table_name="permission")
|
156
|
+
op.drop_index(op.f("ix_permission_created_by"), table_name="permission")
|
157
|
+
op.drop_index(op.f("ix_permission_created_at"), table_name="permission")
|
158
|
+
op.drop_index(op.f("ix_permission_name"), table_name="permission")
|
159
|
+
op.drop_table("permission")
|
160
|
+
# ### end Alembic commands ###
|
zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration_metadata.py
CHANGED
@@ -1,6 +1,23 @@
|
|
1
|
-
from my_app_name.schema.
|
1
|
+
from my_app_name.schema.permission import Permission
|
2
|
+
from my_app_name.schema.role import Role, RolePermission
|
3
|
+
from my_app_name.schema.session import Session
|
4
|
+
from my_app_name.schema.user import User, UserRole
|
2
5
|
from sqlalchemy import MetaData
|
3
6
|
|
4
7
|
metadata = MetaData()
|
8
|
+
|
9
|
+
Permission.metadata = metadata
|
10
|
+
Permission.__table__.tometadata(metadata)
|
11
|
+
|
12
|
+
Role.metadata = metadata
|
13
|
+
Role.__table__.tometadata(metadata)
|
14
|
+
RolePermission.metadata = metadata
|
15
|
+
RolePermission.__table__.tometadata(metadata)
|
16
|
+
|
5
17
|
User.metadata = metadata
|
6
18
|
User.__table__.tometadata(metadata)
|
19
|
+
UserRole.metadata = metadata
|
20
|
+
UserRole.__table__.tometadata(metadata)
|
21
|
+
|
22
|
+
Session.metadata = metadata
|
23
|
+
Session.__table__.tometadata(metadata)
|
@@ -1,7 +1,10 @@
|
|
1
1
|
from fastapi import FastAPI
|
2
|
-
from my_app_name.common.
|
2
|
+
from my_app_name.common.app_factory import app
|
3
3
|
from my_app_name.common.schema import BasicResponse
|
4
4
|
from my_app_name.config import APP_MAIN_MODULE, APP_MODE, APP_MODULES
|
5
|
+
from my_app_name.module.auth.service.permission.permission_service_factory import (
|
6
|
+
permission_service,
|
7
|
+
)
|
5
8
|
from my_app_name.module.auth.service.user.user_service_factory import user_service
|
6
9
|
|
7
10
|
|
@@ -32,6 +35,7 @@ def serve_route(app: FastAPI):
|
|
32
35
|
|
33
36
|
# Serve user endpoints for APIClient
|
34
37
|
user_service.serve_route(app)
|
38
|
+
permission_service.serve_route(app)
|
35
39
|
|
36
40
|
|
37
41
|
serve_route(app)
|
File without changes
|