legate 0.1.0
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +345 -0
- data/bin/legate +13 -0
- data/examples/00_quickstart.rb +51 -0
- data/examples/01_simple_agent.rb +105 -0
- data/examples/02_multi_tool_agent.rb +140 -0
- data/examples/03_custom_tool.rb +93 -0
- data/examples/04_agent_instructions.rb +84 -0
- data/examples/05_state_and_sessions.rb +91 -0
- data/examples/06_callbacks.rb +186 -0
- data/examples/07_async_jobs.rb +112 -0
- data/examples/08_loop_agent.rb +197 -0
- data/examples/09_sequential_workflow.rb +40 -0
- data/examples/10_parallel_workflow.rb +34 -0
- data/examples/11_agent_delegation.rb +24 -0
- data/examples/12_http_client_tool.rb +156 -0
- data/examples/13_authentication.rb +220 -0
- data/examples/14_mcp_client.rb +154 -0
- data/examples/15_mcp_server.rb +79 -0
- data/examples/16_webhooks.rb +91 -0
- data/examples/README_sequential_agents.md +164 -0
- data/examples/advanced/auth/cookie_auth_tool.rb +146 -0
- data/examples/advanced/auth/custom_auth_flows_example.rb +626 -0
- data/examples/advanced/auth/excon_middleware.rb +317 -0
- data/examples/advanced/auth/excon_middleware_auth.rb +399 -0
- data/examples/advanced/auth/fiber_auth_example.rb +281 -0
- data/examples/advanced/auth/fiber_oidc_example.rb +403 -0
- data/examples/advanced/auth/httpbin_bearer_tool.rb +159 -0
- data/examples/advanced/auth/oauth2_auth.rb +419 -0
- data/examples/advanced/auth/oidc_auth.rb +514 -0
- data/examples/advanced/auth/openweather_api.rb +251 -0
- data/examples/advanced/auth/openweather_tool.rb +153 -0
- data/examples/advanced/auth/query_param_middleware_test.rb +138 -0
- data/examples/advanced/auth/service_account.rb +135 -0
- data/examples/advanced/auth/test_with_httpbin.rb +202 -0
- data/examples/advanced/auth/token_lifecycle_example.rb +428 -0
- data/examples/advanced/callback_monitoring.rb +679 -0
- data/examples/advanced/mas/fixed_delegation_example.rb +191 -0
- data/examples/advanced/mas/loop_workflow.rb +28 -0
- data/examples/advanced/mas/mock_planner.rb +77 -0
- data/examples/advanced/mas/proper_delegation_example.rb +276 -0
- data/examples/advanced/mcp/legate_mcp_server_resource_example.rb +182 -0
- data/examples/advanced/mcp/mcp_resource_server_example.rb +309 -0
- data/examples/advanced/mcp/mcp_server_async.rb +76 -0
- data/examples/advanced/mcp/mcp_server_async_tools.rb +122 -0
- data/examples/advanced/mcp/mcp_server_legate_agent.rb +95 -0
- data/examples/advanced/mcp/mcp_server_rack.rb +89 -0
- data/examples/advanced/random_calculator.rb +104 -0
- data/examples/advanced/sleep_agent.rb +153 -0
- data/examples/advanced/webhooks/webhook_e2e_runner.rb +110 -0
- data/examples/advanced/webhooks/webhook_receiver_agent.rb +58 -0
- data/examples/advanced/workflows/task_refinement_loop_agent.rb +278 -0
- data/examples/advanced/workflows/travel_planner_auto_sequential.rb +444 -0
- data/examples/advanced/workflows/travel_planner_parallel.rb +656 -0
- data/examples/advanced/workflows/travel_planner_sequential.rb +512 -0
- data/examples/tools/oauth2_example.rb +136 -0
- data/examples/tools/sleepy_tool.rb +42 -0
- data/lib/legate/activity_log.rb +71 -0
- data/lib/legate/agent.rb +959 -0
- data/lib/legate/agent_code_generator.rb +185 -0
- data/lib/legate/agent_definition.rb +812 -0
- data/lib/legate/agentic/decision.rb +49 -0
- data/lib/legate/agentic/loop.rb +134 -0
- data/lib/legate/agentic.rb +5 -0
- data/lib/legate/agents/loop_agent.rb +248 -0
- data/lib/legate/agents/parallel_agent.rb +163 -0
- data/lib/legate/agents/sequential_agent.rb +190 -0
- data/lib/legate/agents.rb +14 -0
- data/lib/legate/auth/config.rb +148 -0
- data/lib/legate/auth/coordinator.rb +218 -0
- data/lib/legate/auth/coordinators/oauth2_coordinator.rb +99 -0
- data/lib/legate/auth/coordinators/oidc_coordinator.rb +68 -0
- data/lib/legate/auth/coordinators/service_account_coordinator.rb +122 -0
- data/lib/legate/auth/credential.rb +157 -0
- data/lib/legate/auth/encryption.rb +108 -0
- data/lib/legate/auth/error.rb +94 -0
- data/lib/legate/auth/exchanged_credential.rb +180 -0
- data/lib/legate/auth/excon_middleware.rb +285 -0
- data/lib/legate/auth/http_client_utils.rb +364 -0
- data/lib/legate/auth/manager.rb +531 -0
- data/lib/legate/auth/manager_store.rb +394 -0
- data/lib/legate/auth/middleware_factory.rb +290 -0
- data/lib/legate/auth/runner.rb +279 -0
- data/lib/legate/auth/scheme.rb +125 -0
- data/lib/legate/auth/schemes/api_key.rb +212 -0
- data/lib/legate/auth/schemes/google_service_account.rb +108 -0
- data/lib/legate/auth/schemes/http_bearer.rb +98 -0
- data/lib/legate/auth/schemes/oauth2.rb +396 -0
- data/lib/legate/auth/schemes/openid_connect.rb +346 -0
- data/lib/legate/auth/schemes/service_account.rb +388 -0
- data/lib/legate/auth/schemes.rb +40 -0
- data/lib/legate/auth/token_manager.rb +362 -0
- data/lib/legate/auth/token_store.rb +86 -0
- data/lib/legate/auth/tool_context_extension.rb +97 -0
- data/lib/legate/auth/tool_integration.rb +188 -0
- data/lib/legate/auth/url_guard.rb +81 -0
- data/lib/legate/auth.rb +453 -0
- data/lib/legate/callbacks/callback_context.rb +71 -0
- data/lib/legate/cli/agent_commands.rb +950 -0
- data/lib/legate/cli/auth_commands.rb +520 -0
- data/lib/legate/cli/base_command.rb +24 -0
- data/lib/legate/cli/deployment_commands.rb +934 -0
- data/lib/legate/cli/output_helper.rb +108 -0
- data/lib/legate/cli/session_commands.rb +138 -0
- data/lib/legate/cli/skaffold_commands.rb +223 -0
- data/lib/legate/cli/tool_commands.rb +261 -0
- data/lib/legate/cli/web_commands.rb +182 -0
- data/lib/legate/cli.rb +40 -0
- data/lib/legate/configuration/webhooks.rb +113 -0
- data/lib/legate/configuration.rb +39 -0
- data/lib/legate/definition_store.rb +23 -0
- data/lib/legate/errors.rb +118 -0
- data/lib/legate/event.rb +161 -0
- data/lib/legate/gemini_ai_beta_patch.rb +39 -0
- data/lib/legate/generators/agent_generator.rb +412 -0
- data/lib/legate/generators/code_validator.rb +48 -0
- data/lib/legate/generators/legate/install_generator.rb +35 -0
- data/lib/legate/generators/legate/templates/create_legate_tables.rb.tt +36 -0
- data/lib/legate/generators/legate/templates/initializer.rb +18 -0
- data/lib/legate/generators/runtime_tool_loader.rb +76 -0
- data/lib/legate/generators/tool_generator.rb +408 -0
- data/lib/legate/generators.rb +11 -0
- data/lib/legate/global_definition_registry.rb +506 -0
- data/lib/legate/global_tool_manager.rb +135 -0
- data/lib/legate/llm/adapter.rb +69 -0
- data/lib/legate/llm/gemini.rb +172 -0
- data/lib/legate/llm/ollama.rb +80 -0
- data/lib/legate/llm.rb +34 -0
- data/lib/legate/mcp/client.rb +320 -0
- data/lib/legate/mcp/connection/sse.rb +292 -0
- data/lib/legate/mcp/connection/stdio.rb +273 -0
- data/lib/legate/mcp/connection_manager.rb +103 -0
- data/lib/legate/mcp/server/legate_agent_adapter.rb +170 -0
- data/lib/legate/mcp/server/legate_direct_agent_adapter.rb +140 -0
- data/lib/legate/mcp/server/legate_tool_adapter.rb +119 -0
- data/lib/legate/mcp/tool_wrapper.rb +138 -0
- data/lib/legate/mcp/util/schema_converter.rb +134 -0
- data/lib/legate/mcp.rb +23 -0
- data/lib/legate/plan_executor.rb +375 -0
- data/lib/legate/planner.rb +839 -0
- data/lib/legate/rails/railtie.rb +43 -0
- data/lib/legate/rails.rb +9 -0
- data/lib/legate/redaction.rb +32 -0
- data/lib/legate/session.rb +299 -0
- data/lib/legate/session_service/active_record.rb +300 -0
- data/lib/legate/session_service/base.rb +68 -0
- data/lib/legate/session_service/event_broadcast.rb +74 -0
- data/lib/legate/session_service/in_memory.rb +188 -0
- data/lib/legate/tool/metadata_dsl.rb +122 -0
- data/lib/legate/tool.rb +276 -0
- data/lib/legate/tool_code_generator.rb +103 -0
- data/lib/legate/tool_context.rb +350 -0
- data/lib/legate/tool_loader.rb +39 -0
- data/lib/legate/tool_registry.rb +73 -0
- data/lib/legate/tool_result.rb +61 -0
- data/lib/legate/tools/agent_tool.rb +187 -0
- data/lib/legate/tools/base/http_client.rb +319 -0
- data/lib/legate/tools/base/safe_url.rb +56 -0
- data/lib/legate/tools/base_async_job_tool.rb +91 -0
- data/lib/legate/tools/calculator.rb +89 -0
- data/lib/legate/tools/cat_facts.rb +81 -0
- data/lib/legate/tools/check_job_status_tool.rb +48 -0
- data/lib/legate/tools/current_time_tool.rb +64 -0
- data/lib/legate/tools/echo.rb +43 -0
- data/lib/legate/tools/http_request_tool.rb +105 -0
- data/lib/legate/tools/random_number_tool.rb +64 -0
- data/lib/legate/tools/read_webpage_tool.rb +92 -0
- data/lib/legate/tools/sleepy_tool.rb +74 -0
- data/lib/legate/tools/webhook_tool.rb +146 -0
- data/lib/legate/version.rb +5 -0
- data/lib/legate/web/app.rb +984 -0
- data/lib/legate/web/public/css/main.css +4980 -0
- data/lib/legate/web/public/images/favicon-256.png +0 -0
- data/lib/legate/web/public/images/favicon-32.png +0 -0
- data/lib/legate/web/public/images/legate-logo-dark.png +0 -0
- data/lib/legate/web/public/images/legate-logo-light.png +0 -0
- data/lib/legate/web/public/js/legate.js +616 -0
- data/lib/legate/web/public/styles/main.scss +4402 -0
- data/lib/legate/web/routes/agent_authentication_routes.rb +530 -0
- data/lib/legate/web/routes/agent_definition_routes.rb +803 -0
- data/lib/legate/web/routes/agent_generator_routes.rb +80 -0
- data/lib/legate/web/routes/agent_interaction_routes.rb +734 -0
- data/lib/legate/web/routes/agent_runtime_routes.rb +323 -0
- data/lib/legate/web/routes/api_routes.rb +56 -0
- data/lib/legate/web/routes/authentication_routes.rb +1541 -0
- data/lib/legate/web/routes/core_routes.rb +111 -0
- data/lib/legate/web/routes/documentation_routes.rb +220 -0
- data/lib/legate/web/routes/tool_generator_routes.rb +81 -0
- data/lib/legate/web/routes/tools_ui_routes.rb +207 -0
- data/lib/legate/web/sass_compiler.rb +73 -0
- data/lib/legate/web/views/_active_session_info.slim +25 -0
- data/lib/legate/web/views/_activity_list.slim +55 -0
- data/lib/legate/web/views/_agent_card.slim +56 -0
- data/lib/legate/web/views/_agent_generator_modal.slim +382 -0
- data/lib/legate/web/views/_agent_status_controls.slim +71 -0
- data/lib/legate/web/views/_agent_tool_table.slim +74 -0
- data/lib/legate/web/views/_chat_message.slim +95 -0
- data/lib/legate/web/views/_display_agent_configuration.slim +26 -0
- data/lib/legate/web/views/_display_agent_description.slim +11 -0
- data/lib/legate/web/views/_display_agent_fallback.slim +15 -0
- data/lib/legate/web/views/_display_agent_hierarchy.slim +93 -0
- data/lib/legate/web/views/_display_agent_instruction.slim +17 -0
- data/lib/legate/web/views/_display_agent_mcp.slim +13 -0
- data/lib/legate/web/views/_display_agent_model.slim +17 -0
- data/lib/legate/web/views/_display_agent_name.slim +42 -0
- data/lib/legate/web/views/_display_agent_output_key.slim +26 -0
- data/lib/legate/web/views/_display_agent_type.slim +65 -0
- data/lib/legate/web/views/_edit_agent_configuration.slim +74 -0
- data/lib/legate/web/views/_edit_agent_description.slim +16 -0
- data/lib/legate/web/views/_edit_agent_fallback.slim +25 -0
- data/lib/legate/web/views/_edit_agent_hierarchy.slim +98 -0
- data/lib/legate/web/views/_edit_agent_instruction.slim +49 -0
- data/lib/legate/web/views/_edit_agent_mcp.slim +33 -0
- data/lib/legate/web/views/_edit_agent_model.slim +23 -0
- data/lib/legate/web/views/_edit_agent_output_key.slim +36 -0
- data/lib/legate/web/views/_edit_agent_tools.slim +40 -0
- data/lib/legate/web/views/_edit_agent_type.slim +67 -0
- data/lib/legate/web/views/_session_error.slim +4 -0
- data/lib/legate/web/views/_skeleton.slim +69 -0
- data/lib/legate/web/views/_tool_card.slim +9 -0
- data/lib/legate/web/views/_tool_generator_modal.slim +311 -0
- data/lib/legate/web/views/agent.slim +436 -0
- data/lib/legate/web/views/agent_auth.slim +562 -0
- data/lib/legate/web/views/agents.slim +369 -0
- data/lib/legate/web/views/auth.slim +112 -0
- data/lib/legate/web/views/auth_credential_detail.slim +327 -0
- data/lib/legate/web/views/auth_credentials.slim +261 -0
- data/lib/legate/web/views/auth_debug.slim +94 -0
- data/lib/legate/web/views/auth_mapping_detail.slim +151 -0
- data/lib/legate/web/views/auth_mapping_new.slim +123 -0
- data/lib/legate/web/views/auth_mappings.slim +120 -0
- data/lib/legate/web/views/auth_scheme_detail.slim +274 -0
- data/lib/legate/web/views/auth_schemes.slim +259 -0
- data/lib/legate/web/views/auth_test.slim +418 -0
- data/lib/legate/web/views/chat.slim +192 -0
- data/lib/legate/web/views/docs_index.slim +105 -0
- data/lib/legate/web/views/docs_show.slim +105 -0
- data/lib/legate/web/views/error_404.slim +5 -0
- data/lib/legate/web/views/index.slim +148 -0
- data/lib/legate/web/views/layout.slim +144 -0
- data/lib/legate/web/views/tool_detail.slim +87 -0
- data/lib/legate/web/views/tools.slim +50 -0
- data/lib/legate/web/webhook_listener.rb +367 -0
- data/lib/legate/web.rb +9 -0
- data/lib/legate.rb +220 -0
- data/public/docs/advanced/callbacks.md +828 -0
- data/public/docs/advanced/mcp_schema_conversion.md +59 -0
- data/public/docs/authentication/api_reference/config.md +210 -0
- data/public/docs/authentication/api_reference/credential.md +246 -0
- data/public/docs/authentication/api_reference/encryption.md +218 -0
- data/public/docs/authentication/api_reference/exchanged_credential.md +271 -0
- data/public/docs/authentication/api_reference/excon_middleware.md +175 -0
- data/public/docs/authentication/api_reference/index.md +30 -0
- data/public/docs/authentication/api_reference/scheme.md +250 -0
- data/public/docs/authentication/api_reference/schemes/api_key.md +175 -0
- data/public/docs/authentication/api_reference/schemes/google_service_account.md +221 -0
- data/public/docs/authentication/api_reference/schemes/http_bearer.md +169 -0
- data/public/docs/authentication/api_reference/schemes/oauth2.md +343 -0
- data/public/docs/authentication/api_reference/schemes/oidc.md +73 -0
- data/public/docs/authentication/api_reference/schemes/openid_connect.md +311 -0
- data/public/docs/authentication/api_reference/schemes/service_account.md +287 -0
- data/public/docs/authentication/api_reference/token_manager.md +221 -0
- data/public/docs/authentication/api_reference/token_store.md +146 -0
- data/public/docs/authentication/api_reference/tool_context_extension.md +166 -0
- data/public/docs/authentication/guides/api_key.md +190 -0
- data/public/docs/authentication/guides/bearer.md +172 -0
- data/public/docs/authentication/guides/configuration.md +255 -0
- data/public/docs/authentication/guides/custom_flow.md +523 -0
- data/public/docs/authentication/guides/index.md +24 -0
- data/public/docs/authentication/guides/migration.md +435 -0
- data/public/docs/authentication/guides/oauth2.md +252 -0
- data/public/docs/authentication/guides/oidc.md +241 -0
- data/public/docs/authentication/guides/overview.md +155 -0
- data/public/docs/authentication/guides/secure_storage.md +301 -0
- data/public/docs/authentication/guides/service_account.md +228 -0
- data/public/docs/authentication/guides/token_lifecycle.md +295 -0
- data/public/docs/authentication/guides/web_ui_integration.md +504 -0
- data/public/docs/authentication/index.md +58 -0
- data/public/docs/authentication/troubleshooting/credential_storage.md +550 -0
- data/public/docs/authentication/troubleshooting/environment_variables.md +540 -0
- data/public/docs/authentication/troubleshooting/index.md +11 -0
- data/public/docs/authentication/troubleshooting/oauth2_issues.md +220 -0
- data/public/docs/authentication/troubleshooting/oidc_issues.md +412 -0
- data/public/docs/authentication/troubleshooting/token_refresh.md +338 -0
- data/public/docs/cli/legate_cli_usage.md +363 -0
- data/public/docs/core_concepts/legate_agent_lifecycle.md +124 -0
- data/public/docs/core_concepts/legate_architecture_overview.md +110 -0
- data/public/docs/core_concepts/legate_configuration.md +116 -0
- data/public/docs/core_concepts/legate_definition_store.md +102 -0
- data/public/docs/core_concepts/legate_planner.md +94 -0
- data/public/docs/core_concepts/legate_session_service.md +104 -0
- data/public/docs/error_handling/legate_error_handling.md +122 -0
- data/public/docs/examples.md +199 -0
- data/public/docs/getting_started.md +111 -0
- data/public/docs/guides/agentic_agents.md +137 -0
- data/public/docs/guides/ai_code_generators.md +437 -0
- data/public/docs/guides/auto_loading.md +326 -0
- data/public/docs/guides/configuring_agent_webhooks.md +219 -0
- data/public/docs/guides/http_client_usage.md +264 -0
- data/public/docs/guides/llm_providers.md +137 -0
- data/public/docs/guides/mcp_client_integration.md +232 -0
- data/public/docs/guides/mcp_server_exposure.md +206 -0
- data/public/docs/guides/rails_integration.md +128 -0
- data/public/docs/guides/sending_outbound_webhooks.md +227 -0
- data/public/docs/guides/streaming.md +112 -0
- data/public/docs/guides/webhooks.md +288 -0
- data/public/docs/introduction.md +51 -0
- data/public/docs/multi_agent_systems/advanced_features.md +57 -0
- data/public/docs/multi_agent_systems/agent_delegation.md +190 -0
- data/public/docs/multi_agent_systems/agent_hierarchy.md +49 -0
- data/public/docs/multi_agent_systems/state_management.md +47 -0
- data/public/docs/multi_agent_systems/workflow_agents.md +72 -0
- data/public/docs/tools/legate_built_in_tools.md +332 -0
- data/public/docs/tools/legate_tools_and_registry.md +263 -0
- data/public/docs/web_ui/legate_web_ui.md +137 -0
- metadata +823 -0
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/ File: lib/legate/web/views/auth_credential_detail.slim
|
|
2
|
+
.content.mb-6
|
|
3
|
+
nav.breadcrumb(aria-label="breadcrumbs")
|
|
4
|
+
ul
|
|
5
|
+
li
|
|
6
|
+
a(href="/auth") Authentication
|
|
7
|
+
li
|
|
8
|
+
a(href="/auth/credentials") Credentials
|
|
9
|
+
li.is-active
|
|
10
|
+
a(href="/auth/credentials/#{@credential[:name]}" aria-current="page") = @credential[:name]
|
|
11
|
+
|
|
12
|
+
.level
|
|
13
|
+
.level-left
|
|
14
|
+
.level-item
|
|
15
|
+
div
|
|
16
|
+
h1.title.is-2 = @credential[:name]
|
|
17
|
+
p.subtitle.is-4 = @credential[:description]
|
|
18
|
+
.level-right
|
|
19
|
+
.level-item
|
|
20
|
+
.buttons
|
|
21
|
+
button.button.is-warning#edit-credential-btn
|
|
22
|
+
span.icon
|
|
23
|
+
i.fas.fa-edit
|
|
24
|
+
span Edit
|
|
25
|
+
button.button.is-info#test-credential-btn
|
|
26
|
+
span.icon
|
|
27
|
+
i.fas.fa-vial
|
|
28
|
+
span Test
|
|
29
|
+
button.button.is-danger.is-outlined#delete-credential-btn
|
|
30
|
+
span.icon
|
|
31
|
+
i.fas.fa-trash
|
|
32
|
+
span Delete
|
|
33
|
+
|
|
34
|
+
.columns
|
|
35
|
+
.column.is-half
|
|
36
|
+
.card
|
|
37
|
+
.card-header
|
|
38
|
+
p.card-header-title Credential Information
|
|
39
|
+
.card-content
|
|
40
|
+
.content
|
|
41
|
+
table.table.is-narrow.is-fullwidth
|
|
42
|
+
tbody
|
|
43
|
+
tr
|
|
44
|
+
td <strong>Name:</strong>
|
|
45
|
+
td
|
|
46
|
+
code = @credential[:name]
|
|
47
|
+
tr
|
|
48
|
+
td <strong>Type:</strong>
|
|
49
|
+
td
|
|
50
|
+
span.tag.is-info.is-light = @credential[:auth_type]
|
|
51
|
+
tr
|
|
52
|
+
td <strong>Compatible Schemes:</strong>
|
|
53
|
+
td
|
|
54
|
+
.tags
|
|
55
|
+
- @credential[:compatible_schemes].each do |scheme_name|
|
|
56
|
+
span.tag.is-success.is-light = scheme_name
|
|
57
|
+
|
|
58
|
+
.card.mt-4
|
|
59
|
+
.card-header
|
|
60
|
+
p.card-header-title Current Configuration
|
|
61
|
+
.card-content
|
|
62
|
+
.content
|
|
63
|
+
- if @credential[:current_config].any?
|
|
64
|
+
table.table.is-narrow.is-fullwidth
|
|
65
|
+
tbody
|
|
66
|
+
- @credential[:current_config].each do |key, value|
|
|
67
|
+
tr
|
|
68
|
+
td <strong>#{key.to_s.gsub('_', ' ').split.map(&:capitalize).join(' ')}:</strong>
|
|
69
|
+
td
|
|
70
|
+
- if key.include?('url') || key.include?('uri')
|
|
71
|
+
a(href="#{value}" target="_blank") = value
|
|
72
|
+
- elsif value.to_s.include?('***')
|
|
73
|
+
span.has-text-grey-light = value
|
|
74
|
+
- else
|
|
75
|
+
code = value
|
|
76
|
+
- else
|
|
77
|
+
p.has-text-grey No configuration data available
|
|
78
|
+
|
|
79
|
+
.column.is-half
|
|
80
|
+
.card
|
|
81
|
+
.card-header
|
|
82
|
+
p.card-header-title Usage Information
|
|
83
|
+
.card-content
|
|
84
|
+
.content
|
|
85
|
+
.columns.is-mobile.is-gapless.has-text-centered
|
|
86
|
+
.column
|
|
87
|
+
p.heading Compatible Schemes
|
|
88
|
+
p.title.is-4 = @credential[:compatible_schemes].size
|
|
89
|
+
.column
|
|
90
|
+
p.heading URL Mappings
|
|
91
|
+
p.title.is-4 = @credential[:url_mappings].size
|
|
92
|
+
|
|
93
|
+
- if @credential[:url_mappings].any?
|
|
94
|
+
.card.mt-4
|
|
95
|
+
.card-header
|
|
96
|
+
p.card-header-title URL Mappings
|
|
97
|
+
.card-content
|
|
98
|
+
.content
|
|
99
|
+
.table-container
|
|
100
|
+
table.table.is-fullwidth.is-striped
|
|
101
|
+
thead
|
|
102
|
+
tr
|
|
103
|
+
th Pattern
|
|
104
|
+
th Type
|
|
105
|
+
th Scheme
|
|
106
|
+
tbody
|
|
107
|
+
- @credential[:url_mappings].each do |mapping|
|
|
108
|
+
tr
|
|
109
|
+
td
|
|
110
|
+
code = mapping[:pattern]
|
|
111
|
+
td
|
|
112
|
+
span.tag class=("is-warning" if mapping[:pattern_type] == 'regex')
|
|
113
|
+
= mapping[:pattern_type] == 'regex' ? 'Regex' : 'String'
|
|
114
|
+
td
|
|
115
|
+
span.tag.is-primary.is-light = mapping[:scheme_name]
|
|
116
|
+
|
|
117
|
+
#test-results.card.mt-4.is-hidden
|
|
118
|
+
.card-header
|
|
119
|
+
p.card-header-title Test Results
|
|
120
|
+
.card-content
|
|
121
|
+
.content
|
|
122
|
+
#test-results-content
|
|
123
|
+
/! Test results will be inserted here
|
|
124
|
+
|
|
125
|
+
/! Edit Credential Modal
|
|
126
|
+
#edit-credential-modal.modal
|
|
127
|
+
.modal-background
|
|
128
|
+
.modal-card
|
|
129
|
+
header.modal-card-head
|
|
130
|
+
p.modal-card-title Edit #{@credential[:name]}
|
|
131
|
+
button.delete(aria-label="close")
|
|
132
|
+
section.modal-card-body
|
|
133
|
+
form#edit-credential-form
|
|
134
|
+
- @credential[:config_fields].each do |field|
|
|
135
|
+
.field
|
|
136
|
+
label.label = field[:label]
|
|
137
|
+
.control
|
|
138
|
+
- if field[:type] == 'select'
|
|
139
|
+
.select.is-fullwidth
|
|
140
|
+
select(name="#{field[:name]}" required=field[:required])
|
|
141
|
+
- field[:options].each do |option|
|
|
142
|
+
option(value="#{option}" selected=(@credential[:current_config][field[:name]] == option)) = option
|
|
143
|
+
- elsif field[:type] == 'textarea'
|
|
144
|
+
textarea.textarea(name="#{field[:name]}" placeholder="#{field[:placeholder] || ''}" required=field[:required]) = @credential[:current_config][field[:name]]
|
|
145
|
+
- elsif field[:type] == 'password'
|
|
146
|
+
input.input(type="password" name="#{field[:name]}" placeholder="#{field[:placeholder] || ''}" required=field[:required])
|
|
147
|
+
p.help.is-size-7 Leave blank to keep current value
|
|
148
|
+
- else
|
|
149
|
+
input.input(type="#{field[:type]}" name="#{field[:name]}" value="#{@credential[:current_config][field[:name]]}" placeholder="#{field[:placeholder] || ''}" required=field[:required])
|
|
150
|
+
|
|
151
|
+
footer.modal-card-foot
|
|
152
|
+
button.button.is-primary(type="submit" form="edit-credential-form") Update Credential
|
|
153
|
+
button.button Cancel
|
|
154
|
+
|
|
155
|
+
/! Delete Confirmation Modal
|
|
156
|
+
#delete-credential-modal.modal
|
|
157
|
+
.modal-background
|
|
158
|
+
.modal-card
|
|
159
|
+
header.modal-card-head
|
|
160
|
+
p.modal-card-title Delete Credential
|
|
161
|
+
button.delete(aria-label="close")
|
|
162
|
+
section.modal-card-body
|
|
163
|
+
.content
|
|
164
|
+
p Are you sure you want to delete the credential <strong>#{@credential[:name]}</strong>?
|
|
165
|
+
- if @credential[:url_mappings].any?
|
|
166
|
+
.notification.is-warning
|
|
167
|
+
p <strong>Warning:</strong> This credential is used by #{@credential[:url_mappings].size} URL mapping(s). You must remove these mappings first.
|
|
168
|
+
- else
|
|
169
|
+
p This action cannot be undone.
|
|
170
|
+
|
|
171
|
+
footer.modal-card-foot
|
|
172
|
+
button.button.is-danger#confirm-delete-btn Delete Credential
|
|
173
|
+
button.button Cancel
|
|
174
|
+
|
|
175
|
+
javascript:
|
|
176
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
177
|
+
const editCredentialBtn = document.getElementById('edit-credential-btn');
|
|
178
|
+
const editCredentialModal = document.getElementById('edit-credential-modal');
|
|
179
|
+
const editCredentialForm = document.getElementById('edit-credential-form');
|
|
180
|
+
const testCredentialBtn = document.getElementById('test-credential-btn');
|
|
181
|
+
const testResults = document.getElementById('test-results');
|
|
182
|
+
const testResultsContent = document.getElementById('test-results-content');
|
|
183
|
+
const deleteCredentialBtn = document.getElementById('delete-credential-btn');
|
|
184
|
+
const deleteCredentialModal = document.getElementById('delete-credential-modal');
|
|
185
|
+
const confirmDeleteBtn = document.getElementById('confirm-delete-btn');
|
|
186
|
+
|
|
187
|
+
// Show edit modal
|
|
188
|
+
editCredentialBtn.addEventListener('click', function() {
|
|
189
|
+
editCredentialModal.classList.add('is-active');
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Show delete modal
|
|
193
|
+
deleteCredentialBtn.addEventListener('click', function() {
|
|
194
|
+
deleteCredentialModal.classList.add('is-active');
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
// Hide modals
|
|
198
|
+
function hideModals() {
|
|
199
|
+
editCredentialModal.classList.remove('is-active');
|
|
200
|
+
deleteCredentialModal.classList.remove('is-active');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
document.querySelectorAll('.modal-background, .delete, .button:not(.is-primary):not(.is-danger)').forEach(function(element) {
|
|
204
|
+
element.addEventListener('click', hideModals);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
// Handle edit form submission
|
|
208
|
+
editCredentialForm.addEventListener('submit', function(e) {
|
|
209
|
+
e.preventDefault();
|
|
210
|
+
|
|
211
|
+
const formData = new FormData(this);
|
|
212
|
+
|
|
213
|
+
fetch(`/auth/credentials/#{@credential[:name]}`, {
|
|
214
|
+
method: 'PUT',
|
|
215
|
+
body: formData
|
|
216
|
+
})
|
|
217
|
+
.then(response => response.json())
|
|
218
|
+
.then(data => {
|
|
219
|
+
if (data.success) {
|
|
220
|
+
hideModals();
|
|
221
|
+
if (typeof showToast === 'function') {
|
|
222
|
+
showToast(data.message, 'is-success');
|
|
223
|
+
}
|
|
224
|
+
// Reload the page to show updated configuration
|
|
225
|
+
window.location.reload();
|
|
226
|
+
} else {
|
|
227
|
+
if (typeof showToast === 'function') {
|
|
228
|
+
showToast(data.error || 'Failed to update credential', 'is-danger');
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
})
|
|
232
|
+
.catch(error => {
|
|
233
|
+
console.error('Error:', error);
|
|
234
|
+
if (typeof showToast === 'function') {
|
|
235
|
+
showToast('Network error occurred', 'is-danger');
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Handle test credential
|
|
241
|
+
testCredentialBtn.addEventListener('click', function() {
|
|
242
|
+
testCredentialBtn.classList.add('is-loading');
|
|
243
|
+
testResults.classList.add('is-hidden');
|
|
244
|
+
|
|
245
|
+
Legate.apiRequest(`/auth/credentials/#{@credential[:name]}/test`, {
|
|
246
|
+
method: 'POST'
|
|
247
|
+
})
|
|
248
|
+
.then(data => {
|
|
249
|
+
testCredentialBtn.classList.remove('is-loading');
|
|
250
|
+
|
|
251
|
+
let resultsHTML = '';
|
|
252
|
+
if (data.tests && data.tests.length > 0) {
|
|
253
|
+
resultsHTML += '<div class="content">';
|
|
254
|
+
data.tests.forEach(function(test) {
|
|
255
|
+
const statusClass = test.status === 'passed' ? 'is-success' : 'is-danger';
|
|
256
|
+
const icon = test.status === 'passed' ? 'fa-check' : 'fa-times';
|
|
257
|
+
resultsHTML += `
|
|
258
|
+
<div class="notification ${statusClass} is-light">
|
|
259
|
+
<span class="icon-text">
|
|
260
|
+
<span class="icon">
|
|
261
|
+
<i class="fas ${icon}"></i>
|
|
262
|
+
</span>
|
|
263
|
+
<span><strong>${escapeHtml(test.name)}:</strong> ${escapeHtml(test.message)}</span>
|
|
264
|
+
</span>
|
|
265
|
+
</div>
|
|
266
|
+
`;
|
|
267
|
+
});
|
|
268
|
+
resultsHTML += '</div>';
|
|
269
|
+
|
|
270
|
+
const overallClass = data.success ? 'is-success' : 'is-danger';
|
|
271
|
+
const overallIcon = data.success ? 'fa-check-circle' : 'fa-exclamation-triangle';
|
|
272
|
+
const overallMessage = data.success ? 'All tests passed' : 'Some tests failed';
|
|
273
|
+
|
|
274
|
+
resultsHTML = `
|
|
275
|
+
<div class="notification ${overallClass}">
|
|
276
|
+
<span class="icon-text">
|
|
277
|
+
<span class="icon">
|
|
278
|
+
<i class="fas ${overallIcon}"></i>
|
|
279
|
+
</span>
|
|
280
|
+
<span><strong>${overallMessage}</strong></span>
|
|
281
|
+
</span>
|
|
282
|
+
</div>
|
|
283
|
+
` + resultsHTML;
|
|
284
|
+
} else {
|
|
285
|
+
resultsHTML = '<div class="notification is-info">No test results available</div>';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
testResultsContent.innerHTML = resultsHTML;
|
|
289
|
+
testResults.classList.remove('is-hidden');
|
|
290
|
+
})
|
|
291
|
+
.catch(error => {
|
|
292
|
+
testCredentialBtn.classList.remove('is-loading');
|
|
293
|
+
console.error('Error:', error);
|
|
294
|
+
Legate.renderError(testResultsContent, 'Error running tests: ' + error.message);
|
|
295
|
+
testResults.classList.remove('is-hidden');
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
// Handle delete confirmation
|
|
300
|
+
confirmDeleteBtn.addEventListener('click', function() {
|
|
301
|
+
fetch(`/auth/credentials/#{@credential[:name]}`, {
|
|
302
|
+
method: 'DELETE'
|
|
303
|
+
})
|
|
304
|
+
.then(response => response.json())
|
|
305
|
+
.then(data => {
|
|
306
|
+
if (data.success) {
|
|
307
|
+
if (typeof showToast === 'function') {
|
|
308
|
+
showToast(data.message, 'is-success');
|
|
309
|
+
}
|
|
310
|
+
// Redirect to credentials list
|
|
311
|
+
window.location.href = '/auth/credentials';
|
|
312
|
+
} else {
|
|
313
|
+
hideModals();
|
|
314
|
+
if (typeof showToast === 'function') {
|
|
315
|
+
showToast(data.error || 'Failed to delete credential', 'is-danger');
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
})
|
|
319
|
+
.catch(error => {
|
|
320
|
+
console.error('Error:', error);
|
|
321
|
+
hideModals();
|
|
322
|
+
if (typeof showToast === 'function') {
|
|
323
|
+
showToast('Network error occurred', 'is-danger');
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
});
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/ File: lib/legate/web/views/auth_credentials.slim
|
|
2
|
+
.content.mb-6
|
|
3
|
+
nav.breadcrumb(aria-label="breadcrumbs")
|
|
4
|
+
ul
|
|
5
|
+
li
|
|
6
|
+
a(href="/auth") Authentication
|
|
7
|
+
li.is-active
|
|
8
|
+
a(href="/auth/credentials" aria-current="page") Credentials
|
|
9
|
+
|
|
10
|
+
h1.title.is-2 Authentication Credentials
|
|
11
|
+
p.subtitle.is-4 Manage authentication credentials for external services
|
|
12
|
+
|
|
13
|
+
.buttons.mb-4
|
|
14
|
+
button.button.is-primary#add-credential-btn
|
|
15
|
+
span.icon
|
|
16
|
+
i.fas.fa-plus
|
|
17
|
+
span Add New Credential
|
|
18
|
+
|
|
19
|
+
- if @credentials && @credentials.any?
|
|
20
|
+
.columns.is-multiline
|
|
21
|
+
- @credentials.each do |credential|
|
|
22
|
+
.column.is-half
|
|
23
|
+
.card
|
|
24
|
+
.card-content
|
|
25
|
+
.media
|
|
26
|
+
.media-left
|
|
27
|
+
span.icon.is-large.has-text-info
|
|
28
|
+
- case credential[:auth_type]
|
|
29
|
+
- when :api_key
|
|
30
|
+
i.fas.fa-key.fa-2x
|
|
31
|
+
- when :oauth2, :oidc
|
|
32
|
+
i.fas.fa-shield-alt.fa-2x
|
|
33
|
+
- when :service_account, :google_service_account
|
|
34
|
+
i.fas.fa-robot.fa-2x
|
|
35
|
+
- when :http_bearer
|
|
36
|
+
i.fas.fa-ticket-alt.fa-2x
|
|
37
|
+
- else
|
|
38
|
+
i.fas.fa-id-card.fa-2x
|
|
39
|
+
.media-content
|
|
40
|
+
p.title.is-5 = credential[:name]
|
|
41
|
+
p.subtitle.is-6 = credential[:description]
|
|
42
|
+
.content
|
|
43
|
+
p.is-size-7 = credential[:masked_info]
|
|
44
|
+
.level.is-mobile.mt-3
|
|
45
|
+
.level-left
|
|
46
|
+
.level-item
|
|
47
|
+
.tags
|
|
48
|
+
span.tag.is-info.is-light = credential[:auth_type]
|
|
49
|
+
.level-right
|
|
50
|
+
.level-item
|
|
51
|
+
.buttons.are-small
|
|
52
|
+
a.button.is-primary.is-outlined(href="/auth/credentials/#{credential[:name]}")
|
|
53
|
+
span.icon.is-small
|
|
54
|
+
i.fas.fa-eye
|
|
55
|
+
span Details
|
|
56
|
+
|
|
57
|
+
.content.is-small.mt-3
|
|
58
|
+
.columns.is-mobile.is-gapless
|
|
59
|
+
.column
|
|
60
|
+
.has-text-centered
|
|
61
|
+
p.heading Compatible Schemes
|
|
62
|
+
p.title.is-6 = credential[:compatible_schemes_count]
|
|
63
|
+
.column
|
|
64
|
+
.has-text-centered
|
|
65
|
+
p.heading URL Mappings
|
|
66
|
+
p.title.is-6 = credential[:url_mappings_count]
|
|
67
|
+
|
|
68
|
+
- else
|
|
69
|
+
.columns.is-centered
|
|
70
|
+
.column.is-half
|
|
71
|
+
.notification.is-info
|
|
72
|
+
h3.title.is-4 No Credentials Configured
|
|
73
|
+
p No authentication credentials are currently configured.
|
|
74
|
+
p Add credentials to enable agents to authenticate with external services.
|
|
75
|
+
|
|
76
|
+
.content.mt-6
|
|
77
|
+
h2.title.is-4 Credential Security
|
|
78
|
+
.columns
|
|
79
|
+
.column.is-half
|
|
80
|
+
.content
|
|
81
|
+
h3.title.is-5
|
|
82
|
+
span.icon.has-text-success
|
|
83
|
+
i.fas.fa-shield-alt
|
|
84
|
+
span Secure Storage
|
|
85
|
+
p All sensitive credential data is securely stored and encrypted.
|
|
86
|
+
p Only masked versions are shown in the web interface for security.
|
|
87
|
+
|
|
88
|
+
.column.is-half
|
|
89
|
+
.content
|
|
90
|
+
h3.title.is-5
|
|
91
|
+
span.icon.has-text-warning
|
|
92
|
+
i.fas.fa-exclamation-triangle
|
|
93
|
+
span Important Notes
|
|
94
|
+
p Never share or expose full credential values.
|
|
95
|
+
p Credentials are automatically used by agents when making authenticated requests.
|
|
96
|
+
p Test credentials regularly to ensure they remain valid.
|
|
97
|
+
|
|
98
|
+
/! Add New Credential Modal
|
|
99
|
+
#add-credential-modal.modal
|
|
100
|
+
.modal-background
|
|
101
|
+
.modal-card
|
|
102
|
+
header.modal-card-head
|
|
103
|
+
p.modal-card-title Add New Authentication Credential
|
|
104
|
+
button.delete(aria-label="close")
|
|
105
|
+
section.modal-card-body
|
|
106
|
+
form#add-credential-form
|
|
107
|
+
.field
|
|
108
|
+
label.label Credential Type
|
|
109
|
+
.control
|
|
110
|
+
.select.is-fullwidth
|
|
111
|
+
select#credential-type-select(name="auth_type" required)
|
|
112
|
+
option(value="") Select credential type...
|
|
113
|
+
option(value="api_key") API Key
|
|
114
|
+
option(value="http_bearer") HTTP Bearer
|
|
115
|
+
option(value="oauth2") OAuth2
|
|
116
|
+
option(value="oidc") OpenID Connect
|
|
117
|
+
option(value="service_account") Service Account
|
|
118
|
+
option(value="google_service_account") Google Service Account
|
|
119
|
+
option(value="basic") Basic Auth
|
|
120
|
+
|
|
121
|
+
.field
|
|
122
|
+
label.label Credential Name
|
|
123
|
+
.control
|
|
124
|
+
input.input(type="text" name="credential_name" placeholder="Enter unique credential name" required)
|
|
125
|
+
p.help Give this credential a unique name (e.g., "github_oauth", "api_key_prod")
|
|
126
|
+
|
|
127
|
+
#credential-config-fields
|
|
128
|
+
/! Dynamic configuration fields will be inserted here
|
|
129
|
+
|
|
130
|
+
footer.modal-card-foot
|
|
131
|
+
button.button.is-primary(type="submit" form="add-credential-form") Add Credential
|
|
132
|
+
button.button Cancel
|
|
133
|
+
|
|
134
|
+
javascript:
|
|
135
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
136
|
+
const addCredentialBtn = document.getElementById('add-credential-btn');
|
|
137
|
+
const addCredentialModal = document.getElementById('add-credential-modal');
|
|
138
|
+
const credentialTypeSelect = document.getElementById('credential-type-select');
|
|
139
|
+
const credentialConfigFields = document.getElementById('credential-config-fields');
|
|
140
|
+
const addCredentialForm = document.getElementById('add-credential-form');
|
|
141
|
+
|
|
142
|
+
// Credential configuration templates
|
|
143
|
+
const credentialConfigs = {
|
|
144
|
+
api_key: [
|
|
145
|
+
{ name: 'api_key', type: 'password', required: true, label: 'API Key', placeholder: 'Enter your API key' },
|
|
146
|
+
{ name: 'location', type: 'select', required: false, label: 'Location', options: ['header', 'query', 'cookie'], default: 'header' },
|
|
147
|
+
{ name: 'name', type: 'text', required: false, label: 'Parameter Name', placeholder: 'X-API-Key' }
|
|
148
|
+
],
|
|
149
|
+
http_bearer: [
|
|
150
|
+
{ name: 'bearer_token', type: 'password', required: true, label: 'Bearer Token', placeholder: 'Enter bearer token' }
|
|
151
|
+
],
|
|
152
|
+
oauth2: [
|
|
153
|
+
{ name: 'client_id', type: 'text', required: true, label: 'Client ID', placeholder: 'Enter client ID' },
|
|
154
|
+
{ name: 'client_secret', type: 'password', required: true, label: 'Client Secret', placeholder: 'Enter client secret' },
|
|
155
|
+
{ name: 'redirect_uri', type: 'url', required: false, label: 'Redirect URI', placeholder: 'https://your-app.com/callback' },
|
|
156
|
+
{ name: 'scopes', type: 'text', required: false, label: 'Scopes (space-separated)', placeholder: 'read write' }
|
|
157
|
+
],
|
|
158
|
+
oidc: [
|
|
159
|
+
{ name: 'client_id', type: 'text', required: true, label: 'Client ID', placeholder: 'Enter client ID' },
|
|
160
|
+
{ name: 'client_secret', type: 'password', required: true, label: 'Client Secret', placeholder: 'Enter client secret' },
|
|
161
|
+
{ name: 'redirect_uri', type: 'url', required: false, label: 'Redirect URI', placeholder: 'https://your-app.com/callback' },
|
|
162
|
+
{ name: 'scopes', type: 'text', required: false, label: 'Scopes (space-separated)', placeholder: 'openid profile email' }
|
|
163
|
+
],
|
|
164
|
+
service_account: [
|
|
165
|
+
{ name: 'client_email', type: 'email', required: true, label: 'Client Email', placeholder: 'service-account@project.iam.gserviceaccount.com' },
|
|
166
|
+
{ name: 'private_key', type: 'textarea', required: true, label: 'Private Key', placeholder: '-----BEGIN PRIVATE KEY-----\\n...\\n-----END PRIVATE KEY-----' },
|
|
167
|
+
{ name: 'project_id', type: 'text', required: false, label: 'Project ID', placeholder: 'your-project-id' }
|
|
168
|
+
],
|
|
169
|
+
google_service_account: [
|
|
170
|
+
{ name: 'service_account_key', type: 'textarea', required: true, label: 'Service Account Key (JSON)', placeholder: '{"type": "service_account", "project_id": "..."}' }
|
|
171
|
+
],
|
|
172
|
+
basic: [
|
|
173
|
+
{ name: 'username', type: 'text', required: true, label: 'Username', placeholder: 'Enter username' },
|
|
174
|
+
{ name: 'password', type: 'password', required: true, label: 'Password', placeholder: 'Enter password' }
|
|
175
|
+
]
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
// Show modal
|
|
179
|
+
addCredentialBtn.addEventListener('click', function() {
|
|
180
|
+
addCredentialModal.classList.add('is-active');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
// Hide modal
|
|
184
|
+
function hideModal() {
|
|
185
|
+
addCredentialModal.classList.remove('is-active');
|
|
186
|
+
addCredentialForm.reset();
|
|
187
|
+
credentialConfigFields.innerHTML = '';
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
addCredentialModal.querySelectorAll('.modal-background, .delete, .button:not(.is-primary)').forEach(function(element) {
|
|
191
|
+
element.addEventListener('click', hideModal);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
// Update configuration fields when credential type changes
|
|
195
|
+
credentialTypeSelect.addEventListener('change', function() {
|
|
196
|
+
const credentialType = this.value;
|
|
197
|
+
credentialConfigFields.innerHTML = '';
|
|
198
|
+
|
|
199
|
+
if (credentialConfigs[credentialType]) {
|
|
200
|
+
credentialConfigs[credentialType].forEach(function(field) {
|
|
201
|
+
const fieldDiv = document.createElement('div');
|
|
202
|
+
fieldDiv.className = 'field';
|
|
203
|
+
|
|
204
|
+
let fieldHTML = `<label class="label">${field.label}</label><div class="control">`;
|
|
205
|
+
|
|
206
|
+
if (field.type === 'select') {
|
|
207
|
+
fieldHTML += `<div class="select is-fullwidth"><select name="${field.name}" ${field.required ? 'required' : ''}>`;
|
|
208
|
+
if (field.options) {
|
|
209
|
+
field.options.forEach(function(option) {
|
|
210
|
+
const selected = field.default === option ? 'selected' : '';
|
|
211
|
+
fieldHTML += `<option value="${option}" ${selected}>${option}</option>`;
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
fieldHTML += '</select></div>';
|
|
215
|
+
} else if (field.type === 'textarea') {
|
|
216
|
+
fieldHTML += `<textarea class="textarea" name="${field.name}" placeholder="${field.placeholder || ''}" ${field.required ? 'required' : ''}></textarea>`;
|
|
217
|
+
} else {
|
|
218
|
+
fieldHTML += `<input class="input" type="${field.type}" name="${field.name}"
|
|
219
|
+
placeholder="${field.placeholder || ''}" ${field.required ? 'required' : ''}>`;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
fieldHTML += '</div>';
|
|
223
|
+
fieldDiv.innerHTML = fieldHTML;
|
|
224
|
+
credentialConfigFields.appendChild(fieldDiv);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Handle form submission
|
|
230
|
+
addCredentialForm.addEventListener('submit', function(e) {
|
|
231
|
+
e.preventDefault();
|
|
232
|
+
|
|
233
|
+
const formData = new FormData(this);
|
|
234
|
+
|
|
235
|
+
fetch('/auth/credentials', {
|
|
236
|
+
method: 'POST',
|
|
237
|
+
body: formData
|
|
238
|
+
})
|
|
239
|
+
.then(response => response.json())
|
|
240
|
+
.then(data => {
|
|
241
|
+
if (data.success) {
|
|
242
|
+
hideModal();
|
|
243
|
+
if (typeof showToast === 'function') {
|
|
244
|
+
showToast(data.message, 'is-success');
|
|
245
|
+
}
|
|
246
|
+
// Reload the page to show the new credential
|
|
247
|
+
window.location.reload();
|
|
248
|
+
} else {
|
|
249
|
+
if (typeof showToast === 'function') {
|
|
250
|
+
showToast(data.error || 'Failed to add credential', 'is-danger');
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
})
|
|
254
|
+
.catch(error => {
|
|
255
|
+
console.error('Error:', error);
|
|
256
|
+
if (typeof showToast === 'function') {
|
|
257
|
+
showToast('Network error occurred', 'is-danger');
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
});
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/ File: lib/legate/web/views/auth_debug.slim
|
|
2
|
+
.content.mb-6
|
|
3
|
+
nav.breadcrumb(aria-label="breadcrumbs")
|
|
4
|
+
ul
|
|
5
|
+
li
|
|
6
|
+
a(href="/auth") Authentication
|
|
7
|
+
li.is-active
|
|
8
|
+
a(href="/auth/debug" aria-current="page") Debug
|
|
9
|
+
|
|
10
|
+
h1.title.is-2 Authentication Debug Information
|
|
11
|
+
p.subtitle.is-4 Detailed information about the authentication manager state
|
|
12
|
+
|
|
13
|
+
- if @debug_info
|
|
14
|
+
.columns
|
|
15
|
+
.column.is-half
|
|
16
|
+
.card
|
|
17
|
+
.card-header
|
|
18
|
+
p.card-header-title Authentication Manager
|
|
19
|
+
.card-content
|
|
20
|
+
.content
|
|
21
|
+
table.table.is-narrow
|
|
22
|
+
tbody
|
|
23
|
+
tr
|
|
24
|
+
td <strong>Class:</strong>
|
|
25
|
+
td
|
|
26
|
+
code = @debug_info[:manager_class]
|
|
27
|
+
tr
|
|
28
|
+
td <strong>Instance ID:</strong>
|
|
29
|
+
td
|
|
30
|
+
code = @debug_info[:manager_instance_id]
|
|
31
|
+
tr
|
|
32
|
+
td <strong>Schemes Registered:</strong>
|
|
33
|
+
td = @debug_info[:schemes_registered].size
|
|
34
|
+
tr
|
|
35
|
+
td <strong>Credentials Registered:</strong>
|
|
36
|
+
td = @debug_info[:credentials_registered].size
|
|
37
|
+
tr
|
|
38
|
+
td <strong>URL Mappings:</strong>
|
|
39
|
+
td = @debug_info[:url_mappings_count]
|
|
40
|
+
|
|
41
|
+
.column.is-half
|
|
42
|
+
.card
|
|
43
|
+
.card-header
|
|
44
|
+
p.card-header-title Registered Components
|
|
45
|
+
.card-content
|
|
46
|
+
.content
|
|
47
|
+
h4.title.is-6 Schemes
|
|
48
|
+
- if @debug_info[:schemes_registered].any?
|
|
49
|
+
.tags
|
|
50
|
+
- @debug_info[:schemes_registered].each do |scheme_name|
|
|
51
|
+
span.tag.is-primary.is-light = scheme_name
|
|
52
|
+
- else
|
|
53
|
+
p.has-text-grey No schemes registered
|
|
54
|
+
|
|
55
|
+
h4.title.is-6.mt-4 Credentials
|
|
56
|
+
- if @debug_info[:credentials_registered].any?
|
|
57
|
+
.tags
|
|
58
|
+
- @debug_info[:credentials_registered].each do |credential_name|
|
|
59
|
+
span.tag.is-info.is-light = credential_name
|
|
60
|
+
- else
|
|
61
|
+
p.has-text-grey No credentials registered
|
|
62
|
+
|
|
63
|
+
- else
|
|
64
|
+
.columns.is-centered
|
|
65
|
+
.column.is-half
|
|
66
|
+
.notification.is-danger
|
|
67
|
+
h3.title.is-4 Debug Information Unavailable
|
|
68
|
+
p Could not retrieve debug information from the authentication manager.
|
|
69
|
+
|
|
70
|
+
.content.mt-6
|
|
71
|
+
h2.title.is-4 Troubleshooting
|
|
72
|
+
.columns
|
|
73
|
+
.column.is-half
|
|
74
|
+
.content
|
|
75
|
+
h3.title.is-5
|
|
76
|
+
span.icon.has-text-warning
|
|
77
|
+
i.fas.fa-exclamation-triangle
|
|
78
|
+
span Common Issues
|
|
79
|
+
ul
|
|
80
|
+
li <strong>No schemes registered:</strong> Authentication system may not be properly initialized
|
|
81
|
+
li <strong>No credentials:</strong> Add credentials for the services your agents will use
|
|
82
|
+
li <strong>Manager unavailable:</strong> Check that the authentication system dependencies are loaded
|
|
83
|
+
|
|
84
|
+
.column.is-half
|
|
85
|
+
.content
|
|
86
|
+
h3.title.is-5
|
|
87
|
+
span.icon.has-text-info
|
|
88
|
+
i.fas.fa-lightbulb
|
|
89
|
+
span Expected State
|
|
90
|
+
p In a properly configured system, you should see:
|
|
91
|
+
ul
|
|
92
|
+
li Default schemes (api_key, http_bearer, oauth2, oidc, service_account, google_service_account)
|
|
93
|
+
li At least one credential for each service your agents use
|
|
94
|
+
li URL mappings for automatic authentication
|