zrb 1.0.0b10__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- zrb/builtin/git.py +8 -8
- zrb/builtin/llm/llm_chat.py +3 -3
- zrb/builtin/project/add/fastapp/fastapp_input.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/add_column_task.py +99 -55
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/add_column_util.py +301 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +24 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +61 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/gateway/view/content/my-module/my-entity.html +297 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/gateway_subroute.py +24 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/navigation_config_file.py +8 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/input.py +3 -3
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_task.py +8 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +40 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/gateway/subroute/my_module.py +2 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/navigation_config_file.py +6 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/parser.py +2 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/view.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +18 -8
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/config/navigation.py +39 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/route.py +52 -11
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/schema/navigation.py +95 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +91 -8
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/auth.py +9 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/view.py +33 -8
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/auth/permission.html +311 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/auth/role.html +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/auth/user.html +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/error.html +4 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/login.html +67 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/logout.html +49 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/common/util.js +160 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/crud/style.css +14 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/crud/util.js +94 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/pico-style.css +23 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/script.js +44 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/style.css +102 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/template/default.html +73 -18
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_homepage.py +2 -4
- zrb/builtin/project/create/project_task.py +2 -2
- zrb/builtin/random.py +3 -3
- zrb/builtin/setup/common_input.py +5 -5
- zrb/builtin/setup/tmux/tmux.py +1 -1
- zrb/builtin/setup/zsh/zsh.py +1 -1
- zrb/builtin/todo.py +4 -4
- zrb/input/base_input.py +17 -12
- zrb/input/bool_input.py +12 -5
- zrb/input/float_input.py +12 -5
- zrb/input/int_input.py +12 -5
- zrb/input/option_input.py +5 -5
- zrb/input/password_input.py +5 -5
- zrb/input/text_input.py +4 -4
- zrb/runner/web_route/refresh_token_api_route.py +1 -1
- zrb/runner/web_route/static/refresh-token.template.js +9 -0
- zrb/runner/web_route/static/static_route.py +1 -1
- zrb/util/load.py +13 -7
- {zrb-1.0.0b10.dist-info → zrb-1.2.0.dist-info}/METADATA +2 -2
- {zrb-1.0.0b10.dist-info → zrb-1.2.0.dist-info}/RECORD +60 -44
- zrb/util/llm/tool.py +0 -87
- {zrb-1.0.0b10.dist-info → zrb-1.2.0.dist-info}/WHEEL +0 -0
- {zrb-1.0.0b10.dist-info → zrb-1.2.0.dist-info}/entry_points.txt +0 -0
@@ -1,18 +1,21 @@
|
|
1
|
-
import
|
1
|
+
from typing import Annotated
|
2
2
|
|
3
|
-
from fastapi import FastAPI, HTTPException, Request
|
3
|
+
from fastapi import Depends, FastAPI, HTTPException, Request
|
4
4
|
from fastapi.exception_handlers import http_exception_handler
|
5
|
-
from fastapi.responses import HTMLResponse
|
5
|
+
from fastapi.responses import HTMLResponse, RedirectResponse
|
6
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_AUTH_ACCESS_TOKEN_COOKIE_NAME,
|
10
10
|
APP_MAIN_MODULE,
|
11
11
|
APP_MODE,
|
12
12
|
APP_MODULES,
|
13
13
|
)
|
14
|
+
from my_app_name.module.auth.client.auth_client_factory import auth_client
|
14
15
|
from my_app_name.module.gateway.subroute.auth import serve_auth_route
|
15
|
-
from my_app_name.module.gateway.util.
|
16
|
+
from my_app_name.module.gateway.util.auth import get_current_user
|
17
|
+
from my_app_name.module.gateway.util.view import render_content, render_error
|
18
|
+
from my_app_name.schema.user import AuthUserResponse
|
16
19
|
|
17
20
|
|
18
21
|
def serve_route(app: FastAPI):
|
@@ -21,18 +24,48 @@ def serve_route(app: FastAPI):
|
|
21
24
|
if APP_MODE == "monolith" or APP_MAIN_MODULE == "gateway":
|
22
25
|
_serve_health_check(app)
|
23
26
|
_serve_readiness_check(app)
|
24
|
-
|
27
|
+
_serve_common_pages(app)
|
25
28
|
_handle_404(app)
|
26
29
|
|
27
30
|
# Serve auth routes
|
28
31
|
serve_auth_route(app)
|
29
32
|
|
30
33
|
|
31
|
-
def
|
34
|
+
def _serve_common_pages(app: FastAPI):
|
32
35
|
@app.get("/", include_in_schema=False)
|
33
|
-
def home_page(
|
34
|
-
|
35
|
-
|
36
|
+
def home_page(
|
37
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
38
|
+
):
|
39
|
+
return render_content(
|
40
|
+
view_path="homepage.html",
|
41
|
+
current_user=current_user,
|
42
|
+
page_name="gateway.home",
|
43
|
+
)
|
44
|
+
|
45
|
+
@app.get("/login", include_in_schema=False)
|
46
|
+
def login_page(
|
47
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
48
|
+
):
|
49
|
+
if not current_user.is_guest:
|
50
|
+
return RedirectResponse("/")
|
51
|
+
return render_content(
|
52
|
+
view_path="login.html",
|
53
|
+
current_user=current_user,
|
54
|
+
page_name="gateway.home",
|
55
|
+
partials={"show_user_info": False},
|
56
|
+
)
|
57
|
+
|
58
|
+
@app.get("/logout", include_in_schema=False)
|
59
|
+
def logout_page(
|
60
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
61
|
+
):
|
62
|
+
if current_user is None:
|
63
|
+
return RedirectResponse("/")
|
64
|
+
return render_content(
|
65
|
+
view_path="logout.html",
|
66
|
+
current_user=current_user,
|
67
|
+
page_name="gateway.home",
|
68
|
+
partials={"show_user_info": False},
|
36
69
|
)
|
37
70
|
|
38
71
|
|
@@ -60,7 +93,15 @@ def _handle_404(app: FastAPI):
|
|
60
93
|
if request.url.path.startswith("/api"):
|
61
94
|
# Re-raise the exception to let FastAPI handle it
|
62
95
|
return await http_exception_handler(request, exc)
|
63
|
-
|
96
|
+
# Get current user by cookies
|
97
|
+
current_user = None
|
98
|
+
cookie_access_token = request.cookies.get(APP_AUTH_ACCESS_TOKEN_COOKIE_NAME)
|
99
|
+
if cookie_access_token is not None and cookie_access_token != "":
|
100
|
+
current_user = await auth_client.get_current_user(cookie_access_token)
|
101
|
+
# Show error page
|
102
|
+
return render_error(
|
103
|
+
error_message="Not found", status_code=404, current_user=current_user
|
104
|
+
)
|
64
105
|
|
65
106
|
|
66
107
|
serve_route(app)
|
zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/schema/navigation.py
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
from my_app_name.schema.user import AuthUserResponse
|
2
|
+
from pydantic import BaseModel
|
3
|
+
|
4
|
+
|
5
|
+
class Page(BaseModel):
|
6
|
+
name: str
|
7
|
+
caption: str
|
8
|
+
url: str
|
9
|
+
permission: str | None = None
|
10
|
+
|
11
|
+
|
12
|
+
class AccessiblePage(BaseModel):
|
13
|
+
name: str
|
14
|
+
caption: str
|
15
|
+
url: str
|
16
|
+
active: bool
|
17
|
+
|
18
|
+
|
19
|
+
class PageGroup(BaseModel):
|
20
|
+
name: str
|
21
|
+
caption: str
|
22
|
+
pages: list[Page] = []
|
23
|
+
|
24
|
+
def append_page(self, submenu: Page) -> Page:
|
25
|
+
self.pages.append(submenu)
|
26
|
+
return submenu
|
27
|
+
|
28
|
+
def get_accessible_pages(
|
29
|
+
self, submenu_name: str | None = None, user: AuthUserResponse | None = None
|
30
|
+
) -> list[AccessiblePage]:
|
31
|
+
return [
|
32
|
+
AccessiblePage(
|
33
|
+
name=page.name,
|
34
|
+
caption=page.caption,
|
35
|
+
url=page.url,
|
36
|
+
active=page.name == submenu_name,
|
37
|
+
)
|
38
|
+
for page in self.pages
|
39
|
+
if _has_permission(user, page.permission)
|
40
|
+
]
|
41
|
+
|
42
|
+
|
43
|
+
class AccessiblePageGroup(BaseModel):
|
44
|
+
name: str
|
45
|
+
caption: str
|
46
|
+
pages: list[AccessiblePage]
|
47
|
+
active: bool
|
48
|
+
|
49
|
+
|
50
|
+
class Navigation(BaseModel):
|
51
|
+
items: list[PageGroup | Page] = []
|
52
|
+
|
53
|
+
def append_page_group(self, page_group: PageGroup) -> PageGroup:
|
54
|
+
self.items.append(page_group)
|
55
|
+
return page_group
|
56
|
+
|
57
|
+
def append_page(self, page: Page) -> Page:
|
58
|
+
self.items.append(page)
|
59
|
+
return page
|
60
|
+
|
61
|
+
def get_accessible_items(
|
62
|
+
self, page_name: str | None, user: AuthUserResponse | None
|
63
|
+
) -> list[AccessiblePageGroup | AccessiblePage]:
|
64
|
+
accessible_items = []
|
65
|
+
for item in self.items:
|
66
|
+
if isinstance(item, Page) and _has_permission(user, item.permission):
|
67
|
+
accessible_items.append(
|
68
|
+
AccessiblePage(
|
69
|
+
name=item.name,
|
70
|
+
caption=item.caption,
|
71
|
+
url=item.url,
|
72
|
+
active=item.name == page_name,
|
73
|
+
)
|
74
|
+
)
|
75
|
+
continue
|
76
|
+
accessible_submenus = item.get_accessible_pages(page_name, user)
|
77
|
+
if accessible_submenus:
|
78
|
+
active = any(submenu.active for submenu in accessible_submenus)
|
79
|
+
accessible_items.append(
|
80
|
+
AccessiblePageGroup(
|
81
|
+
name=item.name,
|
82
|
+
caption=item.caption,
|
83
|
+
pages=accessible_submenus,
|
84
|
+
active=active,
|
85
|
+
)
|
86
|
+
)
|
87
|
+
return accessible_items
|
88
|
+
|
89
|
+
|
90
|
+
def _has_permission(user: AuthUserResponse | None, permission: str | None):
|
91
|
+
if permission is None:
|
92
|
+
return True
|
93
|
+
if user is not None:
|
94
|
+
return user.has_permission(permission)
|
95
|
+
return False
|
zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py
CHANGED
@@ -1,14 +1,17 @@
|
|
1
|
+
import os
|
1
2
|
from typing import Annotated
|
2
3
|
|
3
|
-
from fastapi import Depends, FastAPI, Response
|
4
|
+
from fastapi import Depends, FastAPI, Request, Response
|
4
5
|
from fastapi.security import OAuth2PasswordRequestForm
|
5
|
-
from my_app_name.common.error import ForbiddenError
|
6
|
+
from my_app_name.common.error import ForbiddenError, NotFoundError
|
6
7
|
from my_app_name.module.auth.client.auth_client_factory import auth_client
|
7
8
|
from my_app_name.module.gateway.util.auth import (
|
8
9
|
get_current_user,
|
10
|
+
get_refresh_token,
|
9
11
|
set_user_session_cookie,
|
10
12
|
unset_user_session_cookie,
|
11
13
|
)
|
14
|
+
from my_app_name.module.gateway.util.view import render_content, render_error
|
12
15
|
from my_app_name.schema.permission import (
|
13
16
|
MultiplePermissionResponse,
|
14
17
|
PermissionCreate,
|
@@ -49,22 +52,56 @@ def serve_auth_route(app: FastAPI):
|
|
49
52
|
|
50
53
|
@app.put("/api/v1/user-sessions", response_model=UserSessionResponse)
|
51
54
|
async def update_user_session(
|
52
|
-
response: Response, refresh_token: str
|
55
|
+
request: Request, response: Response, refresh_token: str | None = None
|
53
56
|
) -> UserSessionResponse:
|
54
|
-
|
57
|
+
actual_refresh_token = get_refresh_token(request, refresh_token)
|
58
|
+
if actual_refresh_token is None:
|
59
|
+
raise ForbiddenError("Refresh token needed")
|
60
|
+
try:
|
61
|
+
user_session = await auth_client.update_user_session(actual_refresh_token)
|
62
|
+
except NotFoundError:
|
63
|
+
raise ForbiddenError("Session not found")
|
55
64
|
set_user_session_cookie(response, user_session)
|
56
65
|
return user_session
|
57
66
|
|
58
67
|
@app.delete("/api/v1/user-sessions", response_model=UserSessionResponse)
|
59
68
|
async def delete_user_session(
|
60
|
-
response: Response, refresh_token: str
|
69
|
+
request: Request, response: Response, refresh_token: str | None = None
|
61
70
|
) -> UserSessionResponse:
|
62
|
-
|
63
|
-
|
64
|
-
|
71
|
+
try:
|
72
|
+
actual_refresh_token = get_refresh_token(request, refresh_token)
|
73
|
+
if actual_refresh_token is None:
|
74
|
+
raise ForbiddenError("Refresh token needed")
|
75
|
+
user_session = await auth_client.delete_user_session(actual_refresh_token)
|
76
|
+
return user_session
|
77
|
+
finally:
|
78
|
+
unset_user_session_cookie(response)
|
65
79
|
|
66
80
|
# Permission routes
|
67
81
|
|
82
|
+
@app.get("/auth/permissions", include_in_schema=False)
|
83
|
+
def permissions_crud_ui(
|
84
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
85
|
+
page: int = 1,
|
86
|
+
page_size: int = 10,
|
87
|
+
sort: str | None = None,
|
88
|
+
filter: str | None = None,
|
89
|
+
):
|
90
|
+
if not current_user.has_permission("permission:read"):
|
91
|
+
return render_error(error_message="Access denied", status_code=403)
|
92
|
+
return render_content(
|
93
|
+
view_path=os.path.join("auth", "permission.html"),
|
94
|
+
current_user=current_user,
|
95
|
+
page_name="auth.permission",
|
96
|
+
page=page,
|
97
|
+
page_size=page_size,
|
98
|
+
sort=sort,
|
99
|
+
filter=filter,
|
100
|
+
allow_create=current_user.has_permission("permission:create"),
|
101
|
+
allow_update=current_user.has_permission("permission:update"),
|
102
|
+
allow_delete=current_user.has_permission("permission:delete"),
|
103
|
+
)
|
104
|
+
|
68
105
|
@app.get("/api/v1/permissions", response_model=MultiplePermissionResponse)
|
69
106
|
async def get_permissions(
|
70
107
|
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
@@ -176,6 +213,29 @@ def serve_auth_route(app: FastAPI):
|
|
176
213
|
|
177
214
|
# Role routes
|
178
215
|
|
216
|
+
@app.get("/auth/roles", include_in_schema=False)
|
217
|
+
def roles_crud_ui(
|
218
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
219
|
+
page: int = 1,
|
220
|
+
page_size: int = 10,
|
221
|
+
sort: str | None = None,
|
222
|
+
filter: str | None = None,
|
223
|
+
):
|
224
|
+
if not current_user.has_permission("role:read"):
|
225
|
+
return render_error(error_message="Access denied", status_code=403)
|
226
|
+
return render_content(
|
227
|
+
view_path=os.path.join("auth", "role.html"),
|
228
|
+
current_user=current_user,
|
229
|
+
page_name="auth.role",
|
230
|
+
page=page,
|
231
|
+
page_size=page_size,
|
232
|
+
sort=sort,
|
233
|
+
filter=filter,
|
234
|
+
allow_create=current_user.has_permission("role:create"),
|
235
|
+
allow_update=current_user.has_permission("role:update"),
|
236
|
+
allow_delete=current_user.has_permission("role:delete"),
|
237
|
+
)
|
238
|
+
|
179
239
|
@app.get("/api/v1/roles", response_model=MultipleRoleResponse)
|
180
240
|
async def get_roles(
|
181
241
|
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
@@ -283,6 +343,29 @@ def serve_auth_route(app: FastAPI):
|
|
283
343
|
|
284
344
|
# User routes
|
285
345
|
|
346
|
+
@app.get("/auth/users", include_in_schema=False)
|
347
|
+
def users_crud_ui(
|
348
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
349
|
+
page: int = 1,
|
350
|
+
page_size: int = 10,
|
351
|
+
sort: str | None = None,
|
352
|
+
filter: str | None = None,
|
353
|
+
):
|
354
|
+
if not current_user.has_permission("user:read"):
|
355
|
+
return render_error(error_message="Access denied", status_code=403)
|
356
|
+
return render_content(
|
357
|
+
view_path=os.path.join("auth", "user.html"),
|
358
|
+
current_user=current_user,
|
359
|
+
page_name="auth.user",
|
360
|
+
page=page,
|
361
|
+
page_size=page_size,
|
362
|
+
sort=sort,
|
363
|
+
filter=filter,
|
364
|
+
allow_create=current_user.has_permission("user:create"),
|
365
|
+
allow_update=current_user.has_permission("user:update"),
|
366
|
+
allow_delete=current_user.has_permission("user:delete"),
|
367
|
+
)
|
368
|
+
|
286
369
|
@app.get("/api/v1/users", response_model=MultipleUserResponse)
|
287
370
|
async def get_users(
|
288
371
|
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
@@ -15,6 +15,15 @@ from typing_extensions import Annotated
|
|
15
15
|
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/user-sessions", auto_error=False)
|
16
16
|
|
17
17
|
|
18
|
+
def get_refresh_token(request: Request, refresh_token: str | None) -> str | None:
|
19
|
+
if refresh_token is not None and refresh_token != "":
|
20
|
+
return refresh_token
|
21
|
+
cookie_refresh_token = request.cookies.get(APP_AUTH_REFRESH_TOKEN_COOKIE_NAME)
|
22
|
+
if cookie_refresh_token is not None and cookie_refresh_token != "":
|
23
|
+
return cookie_refresh_token
|
24
|
+
return None
|
25
|
+
|
26
|
+
|
18
27
|
async def get_current_user(
|
19
28
|
request: Request,
|
20
29
|
response: Response,
|
@@ -1,18 +1,24 @@
|
|
1
1
|
import os
|
2
2
|
from typing import Any
|
3
3
|
|
4
|
+
import my_app_name.config as CFG
|
4
5
|
from fastapi.responses import HTMLResponse
|
5
6
|
from my_app_name.common.util.view import render_page, render_str
|
6
7
|
from my_app_name.config import (
|
8
|
+
APP_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES,
|
7
9
|
APP_GATEWAY_CSS_PATH_LIST,
|
8
10
|
APP_GATEWAY_FAVICON_PATH,
|
11
|
+
APP_GATEWAY_FOOTER,
|
9
12
|
APP_GATEWAY_JS_PATH_LIST,
|
10
13
|
APP_GATEWAY_LOGO_PATH,
|
14
|
+
APP_GATEWAY_PICO_CSS_PATH,
|
11
15
|
APP_GATEWAY_SUBTITLE,
|
12
16
|
APP_GATEWAY_TITLE,
|
13
17
|
APP_GATEWAY_VIEW_DEFAULT_TEMPLATE_PATH,
|
14
18
|
APP_GATEWAY_VIEW_PATH,
|
15
19
|
)
|
20
|
+
from my_app_name.module.gateway.config.navigation import APP_NAVIGATION
|
21
|
+
from my_app_name.schema.user import AuthUserResponse
|
16
22
|
|
17
23
|
_DEFAULT_TEMPLATE_PATH = os.path.join(
|
18
24
|
APP_GATEWAY_VIEW_PATH, APP_GATEWAY_VIEW_DEFAULT_TEMPLATE_PATH
|
@@ -24,32 +30,47 @@ _DEFAULT_ERROR_TEMPLATE_PATH = os.path.join(
|
|
24
30
|
_DEFAULT_PARTIALS = {
|
25
31
|
"title": APP_GATEWAY_TITLE,
|
26
32
|
"subtitle": APP_GATEWAY_SUBTITLE,
|
33
|
+
"footer": APP_GATEWAY_FOOTER,
|
27
34
|
"logo_path": APP_GATEWAY_LOGO_PATH,
|
28
35
|
"favicon_path": APP_GATEWAY_FAVICON_PATH,
|
36
|
+
"pico_css_path": APP_GATEWAY_PICO_CSS_PATH,
|
29
37
|
"css_path_list": APP_GATEWAY_CSS_PATH_LIST,
|
30
38
|
"js_path_list": APP_GATEWAY_JS_PATH_LIST,
|
39
|
+
"show_user_info": True,
|
40
|
+
"should_refresh_session": True,
|
41
|
+
"refresh_session_interval_seconds": f"{APP_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES * 60 / 3}",
|
31
42
|
}
|
32
43
|
|
33
44
|
|
34
|
-
def
|
45
|
+
def render_content(
|
35
46
|
view_path: str,
|
36
47
|
template_path: str = _DEFAULT_TEMPLATE_PATH,
|
37
48
|
status_code: int = 200,
|
38
|
-
headers: dict[str, str] = None,
|
49
|
+
headers: dict[str, str] | None = None,
|
39
50
|
media_type: str | None = None,
|
51
|
+
current_user: AuthUserResponse | None = None,
|
52
|
+
page_name: str | None = None,
|
40
53
|
partials: dict[str, Any] = {},
|
41
|
-
**data: Any
|
54
|
+
**data: Any,
|
42
55
|
) -> HTMLResponse:
|
43
56
|
rendered_partials = {key: val for key, val in _DEFAULT_PARTIALS.items()}
|
44
57
|
for key, val in partials.items():
|
45
58
|
rendered_partials[key] = val
|
59
|
+
rendered_partials["page_name"] = page_name
|
60
|
+
rendered_partials["current_user"] = current_user
|
61
|
+
rendered_partials["navigations"] = APP_NAVIGATION.get_accessible_items(
|
62
|
+
page_name, current_user
|
63
|
+
)
|
46
64
|
return render_page(
|
47
65
|
template_path=template_path,
|
48
66
|
status_code=status_code,
|
49
67
|
headers=headers,
|
50
68
|
media_type=media_type,
|
51
|
-
|
52
|
-
|
69
|
+
content=render_str(
|
70
|
+
template_path=os.path.join(APP_GATEWAY_VIEW_PATH, "content", view_path),
|
71
|
+
**data,
|
72
|
+
),
|
73
|
+
**rendered_partials,
|
53
74
|
)
|
54
75
|
|
55
76
|
|
@@ -58,17 +79,21 @@ def render_error(
|
|
58
79
|
status_code: int = 500,
|
59
80
|
view_path: str = _DEFAULT_ERROR_TEMPLATE_PATH,
|
60
81
|
template_path: str = _DEFAULT_TEMPLATE_PATH,
|
61
|
-
headers: dict[str, str] = None,
|
82
|
+
headers: dict[str, str] | None = None,
|
62
83
|
media_type: str | None = None,
|
84
|
+
current_user: AuthUserResponse | None = None,
|
85
|
+
page_name: str | None = None,
|
63
86
|
partials: dict[str, Any] = {},
|
64
87
|
):
|
65
|
-
return
|
88
|
+
return render_content(
|
66
89
|
view_path=view_path,
|
67
90
|
template_path=template_path,
|
68
91
|
status_code=status_code,
|
69
92
|
headers=headers,
|
70
93
|
media_type=media_type,
|
71
|
-
|
94
|
+
current_user=current_user,
|
95
|
+
page_name=page_name,
|
96
|
+
partials={"show_user_info": False, **partials},
|
72
97
|
error_status_code=status_code,
|
73
98
|
error_message=error_message,
|
74
99
|
)
|