zrb 1.0.0a21__py3-none-any.whl → 1.0.0b5__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/__init__.py +2 -1
- zrb/__main__.py +3 -3
- zrb/builtin/__init__.py +3 -0
- zrb/builtin/group.py +1 -0
- zrb/builtin/llm/llm_chat.py +87 -7
- zrb/builtin/llm/previous-session.js +21 -0
- zrb/builtin/llm/tool/api.py +29 -0
- zrb/builtin/llm/tool/cli.py +1 -1
- zrb/builtin/llm/tool/rag.py +108 -145
- zrb/builtin/llm/tool/web.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_task.py +2 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/config.py +5 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +80 -20
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +150 -42
- 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 +113 -0
- 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 +9 -0
- 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/{factory.py → 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 +74 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/format_task.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/input.py +13 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_task.py +23 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +42 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/gateway/subroute/my_module.py +7 -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 +11 -11
- 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 +8 -8
- 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 +230 -102
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_service.py +236 -0
- 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/common/util/view.py +37 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +37 -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 +169 -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 +7 -3
- 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/repository/role_db_repository.py +89 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role/repository/role_repository.py +67 -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 +137 -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 +179 -12
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_repository.py +67 -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 +127 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service_factory.py +7 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/route.py +43 -14
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +200 -30
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/view.py +74 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/error.html +6 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/homepage.html +6 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/images/android-chrome-192x192.png +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/images/android-chrome-512x512.png +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/images/favicon-32x32.png +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.amber.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.blue.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.cyan.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.fuchsia.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.green.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.grey.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.indigo.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.jade.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.lime.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.orange.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.pink.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.pumpkin.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.purple.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.red.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.sand.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.slate.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.violet.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.yellow.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/pico-css/pico.zinc.min.css +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/template/default.html +34 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +1 -0
- 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 +78 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/session.py +48 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/user.py +69 -5
- zrb/builtin/python.py +1 -1
- zrb/builtin/random.py +61 -0
- zrb/builtin/todo.py +1 -0
- zrb/cmd/cmd_val.py +6 -5
- zrb/config.py +15 -4
- zrb/content_transformer/any_content_transformer.py +7 -0
- zrb/content_transformer/content_transformer.py +6 -0
- zrb/input/any_input.py +5 -0
- zrb/input/base_input.py +6 -0
- zrb/input/bool_input.py +2 -0
- zrb/input/float_input.py +2 -0
- zrb/input/int_input.py +2 -0
- zrb/input/option_input.py +2 -0
- zrb/input/password_input.py +2 -0
- zrb/input/text_input.py +2 -0
- zrb/runner/cli.py +14 -7
- zrb/runner/common_util.py +1 -1
- zrb/runner/web_app.py +28 -280
- zrb/runner/web_config/config.py +91 -0
- zrb/runner/web_config/config_factory.py +26 -0
- zrb/runner/web_route/docs_route.py +17 -0
- zrb/runner/web_route/error_page/serve_default_404.py +28 -0
- zrb/runner/{web_controller/error_page/controller.py → web_route/error_page/show_error_page.py} +4 -3
- zrb/runner/{web_controller → web_route}/error_page/view.html +5 -0
- zrb/runner/web_route/home_page/home_page_route.py +51 -0
- zrb/runner/web_route/login_api_route.py +31 -0
- zrb/runner/web_route/login_page/login_page_route.py +39 -0
- zrb/runner/web_route/logout_api_route.py +18 -0
- zrb/runner/web_route/logout_page/logout_page_route.py +40 -0
- zrb/runner/{web_controller/group_info_page/controller.py → web_route/node_page/group/show_group_page.py} +3 -3
- zrb/runner/web_route/node_page/node_page_route.py +50 -0
- zrb/runner/{web_controller/session_page/controller.py → web_route/node_page/task/show_task_page.py} +3 -3
- zrb/runner/{web_controller/session_page → web_route/node_page/task}/view.html +1 -1
- zrb/runner/web_route/refresh_token_api_route.py +38 -0
- zrb/runner/{web_controller/static → web_route/static/resources}/session/current-session.js +12 -6
- zrb/runner/{web_controller/static → web_route/static/resources}/session/event.js +17 -2
- zrb/runner/web_route/static/static_route.py +44 -0
- zrb/runner/web_route/task_input_api_route.py +47 -0
- zrb/runner/web_route/task_session_api_route.py +147 -0
- zrb/runner/web_schema/session.py +5 -0
- zrb/runner/web_schema/token.py +11 -0
- zrb/runner/web_schema/user.py +32 -0
- zrb/runner/web_util/cookie.py +29 -0
- zrb/runner/{web_util.py → web_util/html.py} +1 -23
- zrb/runner/web_util/token.py +72 -0
- zrb/runner/web_util/user.py +63 -0
- zrb/session/session.py +6 -4
- zrb/session_state_logger/{default_session_state_logger.py → session_state_logger_factory.py} +1 -1
- zrb/task/base_task.py +56 -8
- zrb/task/base_trigger.py +2 -0
- zrb/task/cmd_task.py +9 -5
- zrb/task/http_check.py +2 -0
- zrb/task/llm_task.py +93 -110
- zrb/task/make_task.py +2 -0
- zrb/task/rsync_task.py +2 -0
- zrb/task/scaffolder.py +8 -5
- zrb/task/scheduler.py +2 -0
- zrb/task/tcp_check.py +2 -0
- zrb/task_status/task_status.py +4 -3
- zrb/util/cmd/command.py +1 -0
- zrb/util/file.py +7 -1
- zrb/util/llm/tool.py +36 -12
- {zrb-1.0.0a21.dist-info → zrb-1.0.0b5.dist-info}/METADATA +3 -2
- zrb-1.0.0b5.dist-info/RECORD +309 -0
- 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/entity/template/app_template/module/my_module/service/my_entity/my_entity_usecase.py +0 -65
- 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 -6
- 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 -20
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_usecase.py +0 -245
- 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/module/auth/service/user/user_usecase.py +0 -53
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_usecase_factory.py +0 -6
- zrb/runner/web_config.py +0 -274
- zrb/runner/web_controller/home_page/controller.py +0 -33
- zrb/runner/web_controller/login_page/controller.py +0 -25
- zrb/runner/web_controller/logout_page/controller.py +0 -26
- zrb-1.0.0a21.dist-info/RECORD +0 -244
- /zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/{create_column_task.py → add_column_task.py} +0 -0
- /zrb/{runner/web_controller → builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/permission}/__init__.py +0 -0
- /zrb/{runner/web_controller/group_info_page → builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/role}/__init__.py +0 -0
- /zrb/runner/{web_controller/home_page → web_route}/__init__.py +0 -0
- /zrb/runner/{web_controller/session_page → web_route/home_page}/__init__.py +0 -0
- /zrb/runner/{web_controller → web_route}/home_page/view.html +0 -0
- /zrb/runner/{web_controller → web_route}/login_page/view.html +0 -0
- /zrb/runner/{web_controller → web_route}/logout_page/view.html +0 -0
- /zrb/runner/{web_controller/group_info_page → web_route/node_page/group}/view.html +0 -0
- /zrb/runner/{web_controller/session_page → web_route/node_page/task}/partial/input.html +0 -0
- /zrb/runner/{refresh-token.template.js → web_route/static/refresh-token.template.js} +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/common.css +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/favicon-32x32.png +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/login/event.js +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/logout/event.js +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/pico.min.css +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/session/common-util.js +0 -0
- /zrb/runner/{web_controller/static → web_route/static/resources}/session/past-session.js +0 -0
- {zrb-1.0.0a21.dist-info → zrb-1.0.0b5.dist-info}/WHEEL +0 -0
- {zrb-1.0.0a21.dist-info → zrb-1.0.0b5.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,91 @@
|
|
1
|
+
from typing import Callable
|
2
|
+
|
3
|
+
from zrb.runner.web_schema.user import User
|
4
|
+
from zrb.task.any_task import AnyTask
|
5
|
+
|
6
|
+
|
7
|
+
class WebConfig:
|
8
|
+
def __init__(
|
9
|
+
self,
|
10
|
+
port: int,
|
11
|
+
secret_key: str,
|
12
|
+
access_token_expire_minutes: int,
|
13
|
+
refresh_token_expire_minutes: int,
|
14
|
+
access_token_cookie_name: str,
|
15
|
+
refresh_token_cookie_name: str,
|
16
|
+
enable_auth: bool,
|
17
|
+
super_admin_username: str,
|
18
|
+
super_admin_password: str,
|
19
|
+
guest_username: str,
|
20
|
+
guest_accessible_tasks: list[AnyTask | str] = [],
|
21
|
+
find_user_by_username: Callable[[str], User | None] | None = None,
|
22
|
+
):
|
23
|
+
self.secret_key = secret_key
|
24
|
+
self.access_token_expire_minutes = access_token_expire_minutes
|
25
|
+
self.refresh_token_expire_minutes = refresh_token_expire_minutes
|
26
|
+
self.access_token_cookie_name = access_token_cookie_name
|
27
|
+
self.refresh_token_cookie_name = refresh_token_cookie_name
|
28
|
+
self.enable_auth = enable_auth
|
29
|
+
self.port = port
|
30
|
+
self._user_list = []
|
31
|
+
self.super_admin_username = super_admin_username
|
32
|
+
self.super_admin_password = super_admin_password
|
33
|
+
self.guest_username = guest_username
|
34
|
+
self.guest_accessible_tasks = guest_accessible_tasks
|
35
|
+
self._find_user_by_username = find_user_by_username
|
36
|
+
|
37
|
+
@property
|
38
|
+
def default_user(self) -> User:
|
39
|
+
if self.enable_auth:
|
40
|
+
return User(
|
41
|
+
username=self.guest_username,
|
42
|
+
password="",
|
43
|
+
is_guest=True,
|
44
|
+
accessible_tasks=self.guest_accessible_tasks,
|
45
|
+
)
|
46
|
+
return User(
|
47
|
+
username=self.guest_username,
|
48
|
+
password="",
|
49
|
+
is_guest=True,
|
50
|
+
is_super_admin=True,
|
51
|
+
)
|
52
|
+
|
53
|
+
@property
|
54
|
+
def super_admin(self) -> User:
|
55
|
+
return User(
|
56
|
+
username=self.super_admin_username,
|
57
|
+
password=self.super_admin_password,
|
58
|
+
is_super_admin=True,
|
59
|
+
)
|
60
|
+
|
61
|
+
@property
|
62
|
+
def user_list(self) -> list[User]:
|
63
|
+
if not self.enable_auth:
|
64
|
+
return [self.default_user]
|
65
|
+
return self._user_list + [self.super_admin, self.default_user]
|
66
|
+
|
67
|
+
def set_guest_accessible_tasks(self, tasks: list[AnyTask | str]):
|
68
|
+
self.guest_accessible_tasks = tasks
|
69
|
+
|
70
|
+
def set_find_user_by_username(
|
71
|
+
self, find_user_by_username: Callable[[str], User | None]
|
72
|
+
):
|
73
|
+
self._find_user_by_username = find_user_by_username
|
74
|
+
|
75
|
+
def append_user(self, user: User):
|
76
|
+
duplicates = [
|
77
|
+
existing_user
|
78
|
+
for existing_user in self.user_list
|
79
|
+
if existing_user.username == user.username
|
80
|
+
]
|
81
|
+
if len(duplicates) > 0:
|
82
|
+
raise ValueError(f"User already exists {user.username}")
|
83
|
+
self._user_list.append(user)
|
84
|
+
|
85
|
+
def find_user_by_username(self, username: str) -> User | None:
|
86
|
+
user = None
|
87
|
+
if self._find_user_by_username is not None:
|
88
|
+
user = self._find_user_by_username(username)
|
89
|
+
if user is None:
|
90
|
+
user = next((u for u in self.user_list if u.username == username), None)
|
91
|
+
return user
|
@@ -0,0 +1,26 @@
|
|
1
|
+
from zrb.config import (
|
2
|
+
WEB_ACCESS_TOKEN_COOKIE_NAME,
|
3
|
+
WEB_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES,
|
4
|
+
WEB_AUTH_REFRESH_TOKEN_EXPIRE_MINUTES,
|
5
|
+
WEB_ENABLE_AUTH,
|
6
|
+
WEB_GUEST_USERNAME,
|
7
|
+
WEB_HTTP_PORT,
|
8
|
+
WEB_REFRESH_TOKEN_COOKIE_NAME,
|
9
|
+
WEB_SECRET_KEY,
|
10
|
+
WEB_SUPER_ADMIN_PASSWORD,
|
11
|
+
WEB_SUPER_ADMIN_USERNAME,
|
12
|
+
)
|
13
|
+
from zrb.runner.web_config.config import WebConfig
|
14
|
+
|
15
|
+
web_config = WebConfig(
|
16
|
+
port=WEB_HTTP_PORT,
|
17
|
+
secret_key=WEB_SECRET_KEY,
|
18
|
+
access_token_expire_minutes=WEB_AUTH_ACCESS_TOKEN_EXPIRE_MINUTES,
|
19
|
+
refresh_token_expire_minutes=WEB_AUTH_REFRESH_TOKEN_EXPIRE_MINUTES,
|
20
|
+
access_token_cookie_name=WEB_ACCESS_TOKEN_COOKIE_NAME,
|
21
|
+
refresh_token_cookie_name=WEB_REFRESH_TOKEN_COOKIE_NAME,
|
22
|
+
enable_auth=WEB_ENABLE_AUTH,
|
23
|
+
super_admin_username=WEB_SUPER_ADMIN_USERNAME,
|
24
|
+
super_admin_password=WEB_SUPER_ADMIN_PASSWORD,
|
25
|
+
guest_username=WEB_GUEST_USERNAME,
|
26
|
+
)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
if TYPE_CHECKING:
|
4
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
5
|
+
from fastapi import FastAPI
|
6
|
+
|
7
|
+
|
8
|
+
def serve_docs(app: "FastAPI") -> None:
|
9
|
+
from fastapi.openapi.docs import get_swagger_ui_html
|
10
|
+
|
11
|
+
@app.get("/docs", include_in_schema=False)
|
12
|
+
async def swagger_ui_html():
|
13
|
+
return get_swagger_ui_html(
|
14
|
+
openapi_url="/openapi.json",
|
15
|
+
title="Zrb",
|
16
|
+
swagger_favicon_url="/static/favicon-32x32.png",
|
17
|
+
)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from zrb.group.any_group import AnyGroup
|
4
|
+
from zrb.runner.web_config.config import WebConfig
|
5
|
+
from zrb.runner.web_route.error_page.show_error_page import show_error_page
|
6
|
+
from zrb.runner.web_util.user import get_user_from_request
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
10
|
+
from fastapi import FastAPI
|
11
|
+
|
12
|
+
|
13
|
+
def serve_default_404(
|
14
|
+
app: "FastAPI",
|
15
|
+
root_group: AnyGroup,
|
16
|
+
web_config: WebConfig,
|
17
|
+
) -> None:
|
18
|
+
from fastapi import Request
|
19
|
+
from fastapi.exception_handlers import http_exception_handler
|
20
|
+
from fastapi.responses import HTMLResponse
|
21
|
+
|
22
|
+
@app.exception_handler(404)
|
23
|
+
async def default_404(request: Request, exc: Exception) -> HTMLResponse:
|
24
|
+
if request.url.path.startswith("/api"):
|
25
|
+
# Re-raise the exception to let FastAPI handle it
|
26
|
+
return await http_exception_handler(request, exc)
|
27
|
+
user = await get_user_from_request(web_config, request)
|
28
|
+
return show_error_page(user, root_group, 404, "Not found")
|
zrb/runner/{web_controller/error_page/controller.py → web_route/error_page/show_error_page.py}
RENAMED
@@ -1,8 +1,8 @@
|
|
1
1
|
import os
|
2
2
|
|
3
3
|
from zrb.group.any_group import AnyGroup
|
4
|
-
from zrb.runner.
|
5
|
-
from zrb.runner.web_util import get_html_auth_link
|
4
|
+
from zrb.runner.web_schema.user import User
|
5
|
+
from zrb.runner.web_util.html import get_html_auth_link
|
6
6
|
from zrb.util.file import read_file
|
7
7
|
from zrb.util.string.format import fstring_format
|
8
8
|
|
@@ -23,5 +23,6 @@ def show_error_page(user: User, root_group: AnyGroup, status_code: int, message:
|
|
23
23
|
"error_status_code": status_code,
|
24
24
|
"error_message": message,
|
25
25
|
},
|
26
|
-
)
|
26
|
+
),
|
27
|
+
status_code=status_code,
|
27
28
|
)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
<!doctype html>
|
2
2
|
<html lang="en">
|
3
|
+
|
3
4
|
<head>
|
4
5
|
<meta charset="utf-8">
|
5
6
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
@@ -9,6 +10,7 @@
|
|
9
10
|
<title>Zrb</title>
|
10
11
|
<link rel="stylesheet" href="/static/common.css">
|
11
12
|
</head>
|
13
|
+
|
12
14
|
<body>
|
13
15
|
<header class="container">
|
14
16
|
<hgroup>
|
@@ -26,9 +28,12 @@
|
|
26
28
|
</hgroup>
|
27
29
|
</header>
|
28
30
|
<main class="container">
|
31
|
+
<article>
|
29
32
|
<h2>{error_status_code}</h2>
|
30
33
|
<p>{error_message}</p>
|
34
|
+
</article>
|
31
35
|
</main>
|
32
36
|
</body>
|
33
37
|
<script src="/refresh-token.js"></script>
|
38
|
+
|
34
39
|
</html>
|
@@ -0,0 +1,51 @@
|
|
1
|
+
import os
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from zrb.group.any_group import AnyGroup
|
5
|
+
from zrb.runner.web_config.config import WebConfig
|
6
|
+
from zrb.runner.web_util.html import (
|
7
|
+
get_html_auth_link,
|
8
|
+
get_html_subgroup_info,
|
9
|
+
get_html_subtask_info,
|
10
|
+
)
|
11
|
+
from zrb.runner.web_util.user import get_user_from_request
|
12
|
+
from zrb.util.file import read_file
|
13
|
+
from zrb.util.string.format import fstring_format
|
14
|
+
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
17
|
+
from fastapi import FastAPI
|
18
|
+
|
19
|
+
|
20
|
+
def serve_home_page(
|
21
|
+
app: "FastAPI",
|
22
|
+
root_group: AnyGroup,
|
23
|
+
web_config: WebConfig,
|
24
|
+
) -> None:
|
25
|
+
from fastapi import Request
|
26
|
+
from fastapi.responses import HTMLResponse
|
27
|
+
|
28
|
+
# Serve homepage
|
29
|
+
@app.get("/", response_class=HTMLResponse, include_in_schema=False)
|
30
|
+
@app.get("/ui", response_class=HTMLResponse, include_in_schema=False)
|
31
|
+
@app.get("/ui/", response_class=HTMLResponse, include_in_schema=False)
|
32
|
+
async def home_page_ui(request: Request) -> HTMLResponse:
|
33
|
+
|
34
|
+
_DIR = os.path.dirname(__file__)
|
35
|
+
_VIEW_TEMPLATE = read_file(os.path.join(_DIR, "view.html"))
|
36
|
+
user = await get_user_from_request(web_config, request)
|
37
|
+
group_info = get_html_subgroup_info(user, "/ui/", root_group)
|
38
|
+
task_info = get_html_subtask_info(user, "/ui/", root_group)
|
39
|
+
auth_link = get_html_auth_link(user)
|
40
|
+
return HTMLResponse(
|
41
|
+
fstring_format(
|
42
|
+
_VIEW_TEMPLATE,
|
43
|
+
{
|
44
|
+
"group_info": group_info,
|
45
|
+
"task_info": task_info,
|
46
|
+
"name": root_group.name,
|
47
|
+
"description": root_group.description,
|
48
|
+
"auth_link": auth_link,
|
49
|
+
},
|
50
|
+
)
|
51
|
+
)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Annotated
|
2
|
+
|
3
|
+
from zrb.runner.web_config.config import WebConfig
|
4
|
+
from zrb.runner.web_util.cookie import set_auth_cookie
|
5
|
+
from zrb.runner.web_util.token import generate_tokens_by_credentials
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
9
|
+
from fastapi import FastAPI
|
10
|
+
|
11
|
+
|
12
|
+
def serve_login_api(app: "FastAPI", web_config: WebConfig) -> None:
|
13
|
+
from fastapi import Depends, Response
|
14
|
+
from fastapi.responses import JSONResponse
|
15
|
+
from fastapi.security import OAuth2PasswordRequestForm
|
16
|
+
|
17
|
+
@app.post("/api/v1/login")
|
18
|
+
async def login_api(
|
19
|
+
response: Response, form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
|
20
|
+
):
|
21
|
+
token = generate_tokens_by_credentials(
|
22
|
+
web_config=web_config,
|
23
|
+
username=form_data.username,
|
24
|
+
password=form_data.password,
|
25
|
+
)
|
26
|
+
if token is None:
|
27
|
+
return JSONResponse(
|
28
|
+
content={"detail": "Incorrect username or password"}, status_code=400
|
29
|
+
)
|
30
|
+
set_auth_cookie(web_config, response, token)
|
31
|
+
return token
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import os
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from zrb.group.any_group import AnyGroup
|
5
|
+
from zrb.runner.web_config.config import WebConfig
|
6
|
+
from zrb.runner.web_util.html import get_html_auth_link
|
7
|
+
from zrb.runner.web_util.user import get_user_from_request
|
8
|
+
from zrb.util.file import read_file
|
9
|
+
from zrb.util.string.format import fstring_format
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
13
|
+
from fastapi import FastAPI
|
14
|
+
|
15
|
+
|
16
|
+
def serve_login_page(
|
17
|
+
app: "FastAPI",
|
18
|
+
root_group: AnyGroup,
|
19
|
+
web_config: WebConfig,
|
20
|
+
) -> None:
|
21
|
+
from fastapi import Request
|
22
|
+
from fastapi.responses import HTMLResponse
|
23
|
+
|
24
|
+
@app.get("/login", response_class=HTMLResponse, include_in_schema=False)
|
25
|
+
async def login(request: Request) -> HTMLResponse:
|
26
|
+
_DIR = os.path.dirname(__file__)
|
27
|
+
_VIEW_TEMPLATE = read_file(os.path.join(_DIR, "view.html"))
|
28
|
+
user = await get_user_from_request(web_config, request)
|
29
|
+
auth_link = get_html_auth_link(user)
|
30
|
+
return HTMLResponse(
|
31
|
+
fstring_format(
|
32
|
+
_VIEW_TEMPLATE,
|
33
|
+
{
|
34
|
+
"name": root_group.name,
|
35
|
+
"description": root_group.description,
|
36
|
+
"auth_link": auth_link,
|
37
|
+
},
|
38
|
+
)
|
39
|
+
)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from zrb.runner.web_config.config import WebConfig
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
7
|
+
from fastapi import FastAPI
|
8
|
+
|
9
|
+
|
10
|
+
def serve_logout_api(app: "FastAPI", web_config: WebConfig) -> None:
|
11
|
+
from fastapi import Response
|
12
|
+
|
13
|
+
@app.get("/api/v1/logout")
|
14
|
+
@app.post("/api/v1/logout")
|
15
|
+
async def logout_api(response: Response):
|
16
|
+
response.delete_cookie(web_config.access_token_cookie_name)
|
17
|
+
response.delete_cookie(web_config.refresh_token_cookie_name)
|
18
|
+
return {"message": "Logout successful"}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
import os
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from zrb.group.any_group import AnyGroup
|
5
|
+
from zrb.runner.web_config.config import WebConfig
|
6
|
+
from zrb.runner.web_util.html import get_html_auth_link
|
7
|
+
from zrb.runner.web_util.user import get_user_from_request
|
8
|
+
from zrb.util.file import read_file
|
9
|
+
from zrb.util.string.format import fstring_format
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
13
|
+
from fastapi import FastAPI
|
14
|
+
|
15
|
+
|
16
|
+
def serve_logout_page(
|
17
|
+
app: "FastAPI",
|
18
|
+
root_group: AnyGroup,
|
19
|
+
web_config: WebConfig,
|
20
|
+
) -> None:
|
21
|
+
from fastapi import Request
|
22
|
+
from fastapi.responses import HTMLResponse
|
23
|
+
|
24
|
+
@app.get("/logout", response_class=HTMLResponse, include_in_schema=False)
|
25
|
+
async def logout(request: Request) -> HTMLResponse:
|
26
|
+
_DIR = os.path.dirname(__file__)
|
27
|
+
_VIEW_TEMPLATE = read_file(os.path.join(_DIR, "view.html"))
|
28
|
+
user = await get_user_from_request(web_config, request)
|
29
|
+
auth_link = get_html_auth_link(user)
|
30
|
+
return HTMLResponse(
|
31
|
+
fstring_format(
|
32
|
+
_VIEW_TEMPLATE,
|
33
|
+
{
|
34
|
+
"name": root_group.name,
|
35
|
+
"description": root_group.description,
|
36
|
+
"auth_link": auth_link,
|
37
|
+
"user": user,
|
38
|
+
},
|
39
|
+
)
|
40
|
+
)
|
@@ -1,8 +1,8 @@
|
|
1
1
|
import os
|
2
2
|
|
3
3
|
from zrb.group.any_group import AnyGroup
|
4
|
-
from zrb.runner.
|
5
|
-
from zrb.runner.web_util import (
|
4
|
+
from zrb.runner.web_schema.user import User
|
5
|
+
from zrb.runner.web_util.html import (
|
6
6
|
get_html_auth_link,
|
7
7
|
get_html_subgroup_info,
|
8
8
|
get_html_subtask_info,
|
@@ -11,7 +11,7 @@ from zrb.util.file import read_file
|
|
11
11
|
from zrb.util.string.format import fstring_format
|
12
12
|
|
13
13
|
|
14
|
-
def
|
14
|
+
def show_group_page(user: User, root_group: AnyGroup, group: AnyGroup, url: str):
|
15
15
|
from fastapi.responses import HTMLResponse
|
16
16
|
|
17
17
|
_DIR = os.path.dirname(__file__)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import os
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from zrb.context.shared_context import SharedContext
|
5
|
+
from zrb.group.any_group import AnyGroup
|
6
|
+
from zrb.runner.web_config.config import WebConfig
|
7
|
+
from zrb.runner.web_route.error_page.show_error_page import show_error_page
|
8
|
+
from zrb.runner.web_route.node_page.group.show_group_page import show_group_page
|
9
|
+
from zrb.runner.web_route.node_page.task.show_task_page import show_task_page
|
10
|
+
from zrb.runner.web_util.user import get_user_from_request
|
11
|
+
from zrb.session.session import Session
|
12
|
+
from zrb.task.any_task import AnyTask
|
13
|
+
from zrb.util.group import NodeNotFoundError, extract_node_from_args
|
14
|
+
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
17
|
+
from fastapi import FastAPI
|
18
|
+
|
19
|
+
|
20
|
+
def serve_node_page(
|
21
|
+
app: "FastAPI",
|
22
|
+
root_group: AnyGroup,
|
23
|
+
web_config: WebConfig,
|
24
|
+
) -> None:
|
25
|
+
from fastapi import Request
|
26
|
+
from fastapi.responses import HTMLResponse
|
27
|
+
|
28
|
+
@app.get("/ui/{path:path}", response_class=HTMLResponse, include_in_schema=False)
|
29
|
+
async def ui_page(path: str, request: Request) -> HTMLResponse:
|
30
|
+
user = await get_user_from_request(web_config, request)
|
31
|
+
# Avoid capturing '/ui' itself
|
32
|
+
if not path:
|
33
|
+
return show_error_page(user, root_group, 422, "Undefined path")
|
34
|
+
args = path.strip("/").split("/")
|
35
|
+
try:
|
36
|
+
node, node_path, residual_args = extract_node_from_args(root_group, args)
|
37
|
+
except NodeNotFoundError as e:
|
38
|
+
return show_error_page(user, root_group, 404, str(e))
|
39
|
+
url = f"/ui/{'/'.join(node_path)}/"
|
40
|
+
if isinstance(node, AnyTask):
|
41
|
+
if not user.can_access_task(node):
|
42
|
+
return show_error_page(user, root_group, 403, "Forbidden")
|
43
|
+
shared_ctx = SharedContext(env=dict(os.environ))
|
44
|
+
session = Session(shared_ctx=shared_ctx, root_group=root_group)
|
45
|
+
return show_task_page(user, root_group, node, session, url, residual_args)
|
46
|
+
elif isinstance(node, AnyGroup):
|
47
|
+
if not user.can_access_group(node):
|
48
|
+
return show_error_page(user, root_group, 403, "Forbidden")
|
49
|
+
return show_group_page(user, root_group, node, url)
|
50
|
+
return show_error_page(user, root_group, 404, "Not found")
|
zrb/runner/{web_controller/session_page/controller.py → web_route/node_page/task/show_task_page.py}
RENAMED
@@ -2,15 +2,15 @@ import json
|
|
2
2
|
import os
|
3
3
|
|
4
4
|
from zrb.group.any_group import AnyGroup
|
5
|
-
from zrb.runner.
|
6
|
-
from zrb.runner.web_util import get_html_auth_link
|
5
|
+
from zrb.runner.web_schema.user import User
|
6
|
+
from zrb.runner.web_util.html import get_html_auth_link
|
7
7
|
from zrb.session.any_session import AnySession
|
8
8
|
from zrb.task.any_task import AnyTask
|
9
9
|
from zrb.util.file import read_file
|
10
10
|
from zrb.util.string.format import fstring_format
|
11
11
|
|
12
12
|
|
13
|
-
def
|
13
|
+
def show_task_page(
|
14
14
|
user: User,
|
15
15
|
root_group: AnyGroup,
|
16
16
|
task: AnyTask,
|
@@ -0,0 +1,38 @@
|
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
|
3
|
+
from zrb.runner.web_config.config import WebConfig
|
4
|
+
from zrb.runner.web_schema.token import RefreshTokenRequest
|
5
|
+
from zrb.runner.web_util.cookie import set_auth_cookie
|
6
|
+
from zrb.runner.web_util.token import regenerate_tokens
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
10
|
+
from fastapi import FastAPI
|
11
|
+
|
12
|
+
|
13
|
+
def serve_refresh_token_api(app: "FastAPI", web_config: WebConfig) -> None:
|
14
|
+
from fastapi import Cookie, Response
|
15
|
+
from fastapi.responses import JSONResponse
|
16
|
+
|
17
|
+
@app.post("/api/v1/refresh-token")
|
18
|
+
async def refresh_token_api(
|
19
|
+
response: Response,
|
20
|
+
body: RefreshTokenRequest = None,
|
21
|
+
refresh_token_cookie: str = Cookie(
|
22
|
+
None, alias=web_config.refresh_token_cookie_name
|
23
|
+
),
|
24
|
+
):
|
25
|
+
# Try to get the refresh token from the request body first
|
26
|
+
refresh_token = body.refresh_token if body else None
|
27
|
+
# If not in the body, try to get it from the cookie
|
28
|
+
if not refresh_token:
|
29
|
+
refresh_token = refresh_token_cookie
|
30
|
+
# If we still don't have a refresh token, raise an exception
|
31
|
+
if not refresh_token:
|
32
|
+
return JSONResponse(
|
33
|
+
content={"detail": "Refresh token not provided"}, status_code=400
|
34
|
+
)
|
35
|
+
# Get token
|
36
|
+
new_token = regenerate_tokens(web_config, refresh_token)
|
37
|
+
set_auth_cookie(web_config, response, new_token)
|
38
|
+
return new_token
|
@@ -4,23 +4,29 @@ const CURRENT_SESSION = {
|
|
4
4
|
const logTextarea = document.getElementById("log-textarea");
|
5
5
|
const submitTaskForm = document.getElementById("submit-task-form");
|
6
6
|
let isFinished = false;
|
7
|
+
let isInputUpdated = false;
|
7
8
|
let errorCount = 0;
|
8
9
|
while (!isFinished) {
|
9
10
|
try {
|
10
11
|
const data = await this.getCurrentSession();
|
11
12
|
// update inputs
|
12
|
-
|
13
|
-
|
14
|
-
const
|
15
|
-
|
16
|
-
|
13
|
+
if (!isInputUpdated) {
|
14
|
+
const dataInputs = data.input;
|
15
|
+
for (const inputName in dataInputs) {
|
16
|
+
const inputValue = dataInputs[inputName];
|
17
|
+
const input = submitTaskForm.querySelector(`[name="${inputName}"]`);
|
18
|
+
if (input) {
|
19
|
+
input.value = inputValue;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
isInputUpdated = true;
|
17
23
|
}
|
18
24
|
resultLineCount = data.final_result.split("\n").length;
|
19
25
|
resultTextarea.rows = resultLineCount <= 5 ? resultLineCount : 5;
|
20
26
|
// update text areas
|
21
27
|
resultTextarea.value = data.final_result;
|
22
28
|
logTextarea.value = data.log.join("\n");
|
23
|
-
logTextarea.scrollTop = logTextarea.scrollHeight;
|
29
|
+
// logTextarea.scrollTop = logTextarea.scrollHeight;
|
24
30
|
// visualize history
|
25
31
|
this.showCurrentSession(data.task_status, data.finished);
|
26
32
|
if (data.finished) {
|
@@ -20,9 +20,9 @@ window.addEventListener("load", async function () {
|
|
20
20
|
|
21
21
|
|
22
22
|
const submitTaskForm = document.getElementById("submit-task-form");
|
23
|
-
|
23
|
+
async function handleInputUpdate(event) {
|
24
24
|
const currentInput = event.target;
|
25
|
-
const inputs = Array.from(submitTaskForm.querySelectorAll("input[name]"));
|
25
|
+
const inputs = Array.from(submitTaskForm.querySelectorAll("input[name], textarea[name], select[name]"));
|
26
26
|
const inputMap = {};
|
27
27
|
const fixedInputNames = [];
|
28
28
|
for (const input of inputs) {
|
@@ -53,6 +53,13 @@ submitTaskForm.addEventListener("input", async function(event) {
|
|
53
53
|
return;
|
54
54
|
}
|
55
55
|
const input = submitTaskForm.querySelector(`[name="${key}"]`);
|
56
|
+
if (input === currentInput) {
|
57
|
+
return;
|
58
|
+
}
|
59
|
+
if (value === "") {
|
60
|
+
return;
|
61
|
+
}
|
62
|
+
console.log(input, data);
|
56
63
|
input.value = value;
|
57
64
|
});
|
58
65
|
} else {
|
@@ -61,6 +68,14 @@ submitTaskForm.addEventListener("input", async function(event) {
|
|
61
68
|
} catch (error) {
|
62
69
|
console.error("Error during fetch:", error);
|
63
70
|
}
|
71
|
+
}
|
72
|
+
|
73
|
+
submitTaskForm.querySelectorAll("input[name], textarea[name]").forEach((element) => {
|
74
|
+
element.addEventListener("input", handleInputUpdate);
|
75
|
+
element.addEventListener("keyup", handleInputUpdate);
|
76
|
+
});
|
77
|
+
submitTaskForm.querySelectorAll("select[name]").forEach((element) => {
|
78
|
+
element.addEventListener("change", handleInputUpdate);
|
64
79
|
});
|
65
80
|
|
66
81
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import os
|
2
|
+
from typing import TYPE_CHECKING
|
3
|
+
|
4
|
+
from zrb.runner.web_config.config import WebConfig
|
5
|
+
from zrb.util.file import read_file
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
# We want fastapi to only be loaded when necessary to decrease footprint
|
9
|
+
from fastapi import FastAPI
|
10
|
+
|
11
|
+
|
12
|
+
def serve_static_resources(app: "FastAPI", web_config: WebConfig) -> None:
|
13
|
+
from fastapi import HTTPException
|
14
|
+
from fastapi.responses import FileResponse, PlainTextResponse
|
15
|
+
from fastapi.staticfiles import StaticFiles
|
16
|
+
|
17
|
+
_STATIC_DIR = os.path.join(os.path.dirname(__file__), "resources")
|
18
|
+
|
19
|
+
app.mount("/static", StaticFiles(directory=_STATIC_DIR), name="static")
|
20
|
+
|
21
|
+
# Serve static files
|
22
|
+
@app.get("/static/{file_path:path}", include_in_schema=False)
|
23
|
+
async def static_files(file_path: str):
|
24
|
+
full_path = os.path.join(_STATIC_DIR, file_path)
|
25
|
+
if os.path.isfile(full_path):
|
26
|
+
return FileResponse(full_path)
|
27
|
+
raise HTTPException(status_code=404, detail="File not found")
|
28
|
+
|
29
|
+
@app.get("/refresh-token.js", include_in_schema=False)
|
30
|
+
async def refresh_token_js():
|
31
|
+
return PlainTextResponse(
|
32
|
+
content=_get_refresh_token_js(
|
33
|
+
60 * web_config.refresh_token_expire_minutes / 3
|
34
|
+
),
|
35
|
+
media_type="application/javascript",
|
36
|
+
)
|
37
|
+
|
38
|
+
|
39
|
+
def _get_refresh_token_js(refresh_interval_seconds: int):
|
40
|
+
_DIR = os.path.dirname(__file__)
|
41
|
+
return read_file(
|
42
|
+
os.path.join(_DIR, "refresh-token.template.js"),
|
43
|
+
{"refreshIntervalSeconds": f"{refresh_interval_seconds}"},
|
44
|
+
)
|