Усилить безопасность веб-интерфейса
CI / Rust Checks (push) Successful in 5m14s
CI / UI Checks (push) Successful in 4s
CI / Deployment Manifests (push) Successful in 2s
CI / Frontend E2E (push) Successful in 2m58s
CI / Deploy (push) Successful in 1m44s

This commit is contained in:
2026-07-11 17:12:50 +03:00
parent 8318e4b560
commit 46892ee61c
26 changed files with 250 additions and 60 deletions
+9 -9
View File
@@ -30,7 +30,7 @@
<!-- Searchable combobox -->
<div class="upstream-combobox" id="upstream-combobox">
<div class="upstream-combobox-trigger" id="upstream-combobox-trigger" onclick="toggleUpstreamDropdown(event)">
<div class="upstream-combobox-trigger" id="upstream-combobox-trigger" data-wizard-action="toggle-upstream">
<div class="upstream-combobox-value" id="upstream-combobox-value">
<span class="upstream-combobox-placeholder" data-i18n="wizard.step2.upstream_placeholder">Выберите API-хост…</span>
</div>
@@ -45,7 +45,7 @@
<svg width="13" height="13" viewBox="0 0 16 16" fill="none" stroke="var(--text-muted)" stroke-width="1.8" stroke-linecap="round">
<circle cx="7" cy="7" r="5"/><path d="M12 12l2.5 2.5"/>
</svg>
<input class="upstream-search-input" id="upstream-search" type="text" data-i18n-ph="wizard.step2.search_placeholder" placeholder="Поиск по имени или URL…" oninput="filterUpstreams(this.value)" autocomplete="off" spellcheck="false">
<input class="upstream-search-input" id="upstream-search" type="text" data-i18n-ph="wizard.step2.search_placeholder" placeholder="Поиск по имени или URL…" autocomplete="off" spellcheck="false">
</div>
<div class="upstream-dropdown-list" id="upstream-dropdown-list">
<!-- populated by JS -->
@@ -58,11 +58,11 @@
<div class="upstream-preview-name" id="upstream-preview-name"></div>
<div class="upstream-preview-url" id="upstream-preview-url"></div>
<span class="upstream-auth-badge" id="upstream-preview-badge"></span>
<button class="upstream-preview-change" onclick="beginEditSelectedUpstream(event)" data-i18n="wizard.step2.change">Изменить</button>
<button class="upstream-preview-change" data-wizard-action="edit-upstream" data-i18n="wizard.step2.change">Изменить</button>
</div>
<!-- Register new upstream trigger row -->
<div class="upstream-new-trigger" id="upstream-new-trigger" onclick="startNewUpstream()">
<div class="upstream-new-trigger" id="upstream-new-trigger" data-wizard-action="new-upstream">
<div class="upstream-new-trigger-radio" id="upstream-new-trigger-radio">
<div class="upstream-new-trigger-dot"></div>
</div>
@@ -89,7 +89,7 @@
</div>
<div class="form-group">
<label class="form-label" data-i18n="wizard.step2.auth_selector">Авторизация API-хоста</label>
<select class="form-select" id="new-upstream-auth-mode" data-testid="wizard-auth-mode-select" onchange="updateUpstreamAuthUi()">
<select class="form-select" id="new-upstream-auth-mode" data-testid="wizard-auth-mode-select">
<option value="none" data-i18n="wizard.step2.auth_mode.none">Без авторизации</option>
<option value="existing" data-i18n="wizard.step2.auth_mode.existing">Использовать существующий профиль авторизации</option>
<option value="create" data-i18n="wizard.step2.auth_mode.create">Создать профиль авторизации сейчас</option>
@@ -118,7 +118,7 @@
<div class="form-row" style="grid-template-columns: 1fr 1fr;">
<div class="form-group">
<label class="form-label"><span data-i18n="wizard.step2.profile_kind">Тип авторизации</span> <span class="form-label-required" data-i18n="workspace_setup.required">обязательно</span></label>
<select class="form-select" id="new-auth-profile-kind" data-testid="wizard-auth-profile-kind-select" onchange="updateAuthProfileCreateUi()">
<select class="form-select" id="new-auth-profile-kind" data-testid="wizard-auth-profile-kind-select">
<option value="bearer" data-i18n="wizard.step2.auth_kind.bearer">Bearer-токен</option>
<option value="basic" data-i18n="wizard.step2.auth_kind.basic">Логин и пароль</option>
<option value="api_key_header" data-i18n="wizard.step2.auth_kind.api_key_header">API-ключ в заголовке</option>
@@ -149,7 +149,7 @@
<select class="form-select" id="new-auth-profile-secret-id" data-testid="wizard-auth-secret-select"></select>
</div>
<div style="display:flex; gap:8px; align-items:center; flex-wrap:wrap;">
<button class="btn-ghost-sm" data-testid="wizard-open-quick-secret" onclick="openQuickSecretModal(event)" data-i18n="wizard.step2.quick_secret">Быстро создать секрет</button>
<button class="btn-ghost-sm" data-testid="wizard-open-quick-secret" data-wizard-action="quick-secret" data-i18n="wizard.step2.quick_secret">Быстро создать секрет</button>
<a class="btn-ghost-sm" href="/secrets" target="_blank" rel="noopener" data-i18n="wizard.step2.manage_secrets">Открыть страницу секретов</a>
</div>
</div>
@@ -168,8 +168,8 @@
<div class="form-hint" data-i18n="wizard.step2.static_headers_hint">Необязательные заголовки без секретных значений. Токены, пароли и ключи храните через профиль авторизации.</div>
</div>
<div style="display:flex; gap:8px; margin-top:4px;">
<button class="btn-primary-sm" onclick="saveNewUpstream(event)" data-i18n="wizard.step2.save_upstream">Сохранить API-хост</button>
<button class="btn-ghost-sm" onclick="cancelNewUpstream(event)" data-i18n="btn.cancel">Отмена</button>
<button class="btn-primary-sm" data-wizard-action="save-upstream" data-i18n="wizard.step2.save_upstream">Сохранить API-хост</button>
<button class="btn-ghost-sm" data-wizard-action="cancel-upstream" data-i18n="btn.cancel">Отмена</button>
</div>
</div>
</div>