Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 67 additions & 18 deletions application/single_app/admin_settings_nav.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,35 @@
"icon": "bi-palette",
"tabs": [
{
"id": "general",
"label": "General",
"icon": "bi-gear",
"id": "branding",
"label": "Branding",
"icon": "bi-palette",
"sections": [
{"id": "branding-section", "label": "Branding", "icon": "bi-palette"},
{"id": "home-page-text-section", "label": "Home Page Text", "icon": "bi-house"},
{"id": "appearance-section", "label": "Appearance", "icon": "bi-brush"},
{"id": "health-check-section", "label": "Health Check", "icon": "bi-heart-pulse"},
{"id": "swagger-section", "label": "API Documentation", "icon": "bi-file-earmark-code"},
],
},
{
# Everything the app states to the user before or during use:
# banners, notices and the agreements they must accept.
"id": "notices",
"label": "Notices & Agreements",
"icon": "bi-megaphone",
"sections": [
{"id": "classification-banner-section", "label": "Classification Banner", "icon": "bi-shield-exclamation"},
{"id": "ai-notice-section", "label": "Chat AI Notice", "icon": "bi-robot"},
{"id": "terms-of-use-section", "label": "Terms of Use", "icon": "bi-door-open"},
{"id": "support-menu-section", "label": "Support", "icon": "bi-life-preserver"},
{"id": "external-links-section", "label": "External Links", "icon": "bi-box-arrow-up-right"},
{"id": "system-settings-section", "label": "System Settings", "icon": "bi-gear-fill"},
{"id": "user-agreement-section", "label": "User Agreement", "icon": "bi-file-earmark-check"},
],
},
{
"id": "custom-pages",
"label": "Custom Pages",
"label": "Pages & Links",
"icon": "bi-window-plus",
"sections": [
{"id": "custom-pages-section", "label": "Static Pages", "icon": "bi-file-earmark-richtext"},
{"id": "external-links-section", "label": "External Links", "icon": "bi-box-arrow-up-right"},
],
},
],
Expand Down Expand Up @@ -138,7 +144,6 @@
{"id": "file-sharing-section", "label": "File Sharing", "icon": "bi-share"},
{"id": "metadata-extraction-section", "label": "Metadata Extraction", "icon": "bi-file-earmark-code"},
{"id": "multimodal-vision-section", "label": "Multi-Modal Vision Analysis", "icon": "bi-eye"},
{"id": "user-agreement-section", "label": "User Agreement", "icon": "bi-file-earmark-check"},
],
},
{
Expand Down Expand Up @@ -189,20 +194,40 @@
"icon": "bi-shield-lock",
"tabs": [
{
"id": "security",
"label": "Security",
"icon": "bi-shield-lock",
# Who can get in and what role they need. Distinct from Content

Check warning on line 197 in application/single_app/admin_settings_nav.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
# Safety, which is about what may be said once you are in.
"id": "access-roles",

Check warning on line 199 in application/single_app/admin_settings_nav.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
"label": "Access & Roles",

Check warning on line 200 in application/single_app/admin_settings_nav.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
"icon": "bi-person-check",
"sections": [
{"id": "permissions-section", "label": "Permissions", "icon": "bi-person-check"},

Check warning on line 203 in application/single_app/admin_settings_nav.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
],
},
{
"id": "secrets",

Check warning on line 207 in application/single_app/admin_settings_nav.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
"label": "Secrets",

Check warning on line 208 in application/single_app/admin_settings_nav.py

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
"icon": "bi-safe",
"sections": [
{"id": "keyvault-section", "label": "Key Vault", "icon": "bi-safe"},
],
},
{
"id": "safety",
"label": "Safety",
"icon": "bi-shield-check",
"id": "content-safety",
"label": "Content Safety",
"icon": "bi-shield-exclamation",
"sections": [
{"id": "content-safety-section", "label": "Content Safety", "icon": "bi-shield-exclamation"},
{"id": "permissions-section", "label": "Permissions", "icon": "bi-person-check"},
],
},
{
# Interim home for the mixed System Settings card. Four of its
# eight fields are idle-timeout, which is the plurality; the
# rest are split out to their real homes in a later change.
"id": "session",
"label": "Session",
"icon": "bi-hourglass-split",
"sections": [
{"id": "system-settings-section", "label": "System Settings", "icon": "bi-sliders"},
],
},
{
Expand Down Expand Up @@ -348,12 +373,14 @@
},
{
"id": "logging",
"label": "Logging",
"label": "Logging & Health",
"icon": "bi-journal-text",
"sections": [
{"id": "application-insights-section", "label": "Application Insights", "icon": "bi-graph-up"},
{"id": "debug-logging-section", "label": "Debug Logging", "icon": "bi-bug"},
{"id": "file-processing-logs-section", "label": "File Process Logging", "icon": "bi-file-earmark-text"},
{"id": "health-check-section", "label": "Health Check", "icon": "bi-heart-pulse"},
{"id": "swagger-section", "label": "API Documentation", "icon": "bi-file-earmark-code"},
],
},
],
Expand All @@ -363,6 +390,16 @@
"label": "Help",
"icon": "bi-life-preserver",
"tabs": [
{
# Where an admin looks first when a user needs help, ahead of
# raising it with the project.
"id": "support-menu",
"label": "Support Menu",
"icon": "bi-life-preserver",
"sections": [
{"id": "support-menu-section", "label": "Support", "icon": "bi-life-preserver"},
],
},
{
"id": "send-feedback",
"label": "Send Feedback",
Expand Down Expand Up @@ -408,6 +445,18 @@
return None


def get_landing_tab_id():
"""Return the tab an admin lands on when no tab is requested.

This is the first tab of the first group rather than a fixed id, so the
landing pane follows the navigation map as cards are regrouped. Latest
Features is pinned last precisely so it can never win this.
"""
for _, tab in iter_tabs():
return tab["id"]
return None


def get_section_ids():
"""Return every section target declared across the navigation."""
return [
Expand Down
3 changes: 2 additions & 1 deletion application/single_app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from functions_content import *
from functions_documents import *
from functions_latest_features_nav import should_hide_latest_features_nav
from admin_settings_nav import ADMIN_NAV
from admin_settings_nav import ADMIN_NAV, get_landing_tab_id
from functions_search import *
from functions_settings import *
from functions_mcp_server_config import is_mcp_ui_enabled
Expand Down Expand Up @@ -600,6 +600,7 @@ def inject_settings():
user_settings=user_settings,
custom_pages_nav=custom_pages_nav,
admin_nav=ADMIN_NAV,
admin_landing_tab=get_landing_tab_id(),
latest_features_current_version=VERSION,
latest_features_nav_hidden=latest_features_nav_hidden,
latest_features_nav_hidden_by_development=IS_DEVELOPMENT,
Expand Down
2 changes: 1 addition & 1 deletion application/single_app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.260.012"
VERSION = "0.260.013"
IS_DEVELOPMENT = is_development_env_enabled()

SESSION_COOKIE_SAMESITE = os.getenv('SESSION_COOKIE_SAMESITE', 'Lax')
Expand Down
17 changes: 2 additions & 15 deletions application/single_app/static/js/admin/admin_data_management.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,8 @@ function bindEvents() {
pendingDataManagementBackupDelete = null;
});
elements.dataManagementConfirmBackupDeleteBtn?.addEventListener("click", deleteDataManagementBackup);
elements.dataManagementKeyVaultLink?.addEventListener("click", openKeyVaultSettings);
// The Key Vault link carries data-admin-link, so admin_card_links.js
// resolves the owning tab from the DOM and scrolls to the card.
elements.dataManagementCosmosEditorOpenDangerBtn?.addEventListener("click", showCosmosEditorDangerModal);
elements.datamanagementcosmoseditordangeraccept?.addEventListener("change", updateCosmosEditorDangerAcceptState);
elements.dataManagementCosmosEditorAcceptDangerBtn?.addEventListener("click", acceptCosmosEditorDanger);
Expand Down Expand Up @@ -909,20 +910,6 @@ function setKeyStorageAlert(variant, iconClass, title, message, linkText) {
setText(elements.dataManagementKeyVaultLink, linkText);
}

function openKeyVaultSettings(event) {
event?.preventDefault();
const securityTabButton = document.getElementById("security-tab");
if (securityTabButton && window.bootstrap?.Tab) {
window.bootstrap.Tab.getOrCreateInstance(securityTabButton).show();
} else if (securityTabButton) {
securityTabButton.click();
}
window.location.hash = "security";
window.setTimeout(() => {
document.getElementById("keyvault-section")?.scrollIntoView({ block: "start", behavior: "smooth" });
}, 100);
}

function collectSettings() {
const backupStorageAuthenticationType = getValue(elements.datamanagementstorageauth) || backupStorageAuthManagedIdentity;
return {
Expand Down
12 changes: 9 additions & 3 deletions application/single_app/static/js/admin/admin_sidebar_nav.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,12 +145,15 @@

// Set the initial active tab - but only if no tab is already active.
// Latest Features is deliberately excluded so it never opens by default.
// The landing tab is whichever tab the nav map renders first rather than a
// hardcoded id, so it stays correct as the information architecture moves.
const activeTab = document.querySelector('.admin-nav-tab.active, .admin-nav-section.active');
if (!activeTab) {
const firstTab = document.querySelector('.admin-nav-tab[data-tab="general"]');
if (firstTab) {
const firstTab = document.querySelector('.admin-nav-tab[data-tab]');
const firstTabId = firstTab ? firstTab.getAttribute('data-tab') : null;
if (firstTabId) {
firstTab.classList.add('active');
showAdminTab('general');
showAdminTab(firstTabId);
}
} else {
console.log('initAdminSidebarNav - Found existing active tab, preserving current state:', activeTab.getAttribute('data-tab'));
Expand Down Expand Up @@ -288,6 +291,9 @@
const LEGACY_TAB_REDIRECTS = {
'governance': 'feature-governance',
'scale': 'redis-caching',
'general': 'branding',
'safety': 'access-roles',

Check warning on line 295 in application/single_app/static/js/admin/admin_sidebar_nav.js

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
'security': 'secrets',

Check warning on line 296 in application/single_app/static/js/admin/admin_sidebar_nav.js

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains secret or sensitive data source marker. Recommendation%3A Pair this source with any nearby network, logging, serialization, or process execution sink before approving.
};

function resolveAdminTabId(tabId) {
Expand Down
49 changes: 49 additions & 0 deletions application/single_app/templates/admin/_panes/access-roles.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<div class="tab-pane fade{% if admin_landing_tab == 'access-roles' %} show active{% endif %}" id="access-roles" role="tabpanel" aria-labelledby="access-roles-tab">

Check warning on line 1 in application/single_app/templates/admin/_panes/access-roles.html

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
<div class="card p-3 mb-3" id="permissions-section"

Check warning on line 2 in application/single_app/templates/admin/_panes/access-roles.html

View workflow job for this annotation

GitHub Actions / malicious-pr-security-review

Important - Changed line contains security control, sanitization, or audit marker. Recommendation%3A Confirm the change does not weaken auth, CSRF, CSP, XSS defenses, settings sanitization, redaction, audit logging, or tests.
data-requires="enable_user_feedback"
data-requires-label="User Feedback"
data-requires-target="user-feedback-section"
data-requires-scope="#require_member_of_feedback_admin"
data-requires-description="The FeedbackAdmin role only controls access to the User Feedback report, so it does nothing until User Feedback is enabled.">
<h5>
<i class="bi bi-person-check me-2"></i>Permissions
</h5>
<p class="text-muted">Control which users can access specific administrative views related to safety and feedback.</p>


<div class="form-group form-check form-switch mb-2">
<input type="checkbox"
class="form-check-input"
id="require_member_of_safety_violation_admin"
name="require_member_of_safety_violation_admin"
{% if settings.require_member_of_safety_violation_admin %}checked{% endif %}>
<label class="form-check-label ms-2" for="require_member_of_safety_violation_admin">
Require SafetyViolationAdmin App Role
</label>
<i class="bi bi-info-circle ms-2" data-bs-toggle="tooltip" title="When enabled, only users assigned the SafetyViolationAdmin Enterprise App role can access safety violation reports."></i>
</div>
<p class="text-muted small mb-3">
Required app role value: <code>SafetyViolationAdmin</code>. Assign this role to users or groups in the Enterprise App before enabling the requirement. If disabled, any user with the general <code>Admin</code> app role can access the Safety Violations admin page.
</p>


<div class="form-group form-check form-switch mb-2">
<input type="checkbox"
class="form-check-input"
id="require_member_of_feedback_admin"
name="require_member_of_feedback_admin"
{% if settings.require_member_of_feedback_admin %}checked{% endif %}>
<label class="form-check-label ms-2" for="require_member_of_feedback_admin">
Require FeedbackAdmin App Role
</label>
<i class="bi bi-info-circle ms-2" data-bs-toggle="tooltip" title="When enabled, only users assigned the FeedbackAdmin Enterprise App role can access user feedback reports."></i>
</div>
<p class="text-muted small mb-0">
Required app role value: <code>FeedbackAdmin</code>. Assign this role to users or groups in the Enterprise App before enabling the requirement. If disabled, any user with the general <code>Admin</code> app role can access the User Feedback admin page. Requires <strong>Enable User Feedback</strong> to be active.
</p>
</div>




</div>
2 changes: 1 addition & 1 deletion application/single_app/templates/admin/_panes/agents.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="tab-pane fade" id="agents" role="tabpanel" aria-labelledby="agents-tab">
<div class="tab-pane fade{% if admin_landing_tab == 'agents' %} show active{% endif %}" id="agents" role="tabpanel" aria-labelledby="agents-tab">

<p class="text-muted">
Configure AI agents and actions for enhanced functionality. Agents provide AI-driven task automation while Actions extend functionality with custom tools and integrations.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="tab-pane fade" id="ai-models" role="tabpanel" aria-labelledby="ai-models-tab">
<div class="tab-pane fade{% if admin_landing_tab == 'ai-models' %} show active{% endif %}" id="ai-models" role="tabpanel" aria-labelledby="ai-models-tab">

<p class="text-muted">
Configure all AI model settings including GPT for text generation, embeddings for semantic search, and image generation capabilities.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="tab-pane fade" id="archiving" role="tabpanel" aria-labelledby="archiving-tab">
<div class="tab-pane fade{% if admin_landing_tab == 'archiving' %} show active{% endif %}" id="archiving" role="tabpanel" aria-labelledby="archiving-tab">
<div class="card p-3 mb-3" id="conversation-archiving-section">
<h5>
<i class="bi bi-archive me-2"></i>Conversation Archiving
Expand Down
Loading
Loading