Skip to content

Commit 83f6ae5

Browse files
authored
Merge pull request #1011 from microsoft/bugfix/1009
Fix Control Center left nav endpoint check
2 parents f0ce8cc + ac684c2 commit 83f6ae5

5 files changed

Lines changed: 142 additions & 2 deletions

File tree

application/single_app/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
EXECUTOR_TYPE = 'thread'
9797
EXECUTOR_MAX_WORKERS = 30
9898
SESSION_TYPE = 'filesystem'
99-
VERSION = "0.250.051"
99+
VERSION = "0.250.052"
100100

101101
SESSION_COOKIE_SAMESITE = os.getenv('SESSION_COOKIE_SAMESITE', 'Lax')
102102
SESSION_COOKIE_HTTPONLY = os.getenv('SESSION_COOKIE_HTTPONLY', 'true').lower() != 'false'

application/single_app/templates/_sidebar_nav.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -844,7 +844,7 @@
844844
<!-- Access logic: When require_member_of_control_center_admin is ENABLED, only ControlCenterAdmin role grants access -->
845845
<!-- When DISABLED (default), only regular Admin role grants access (ControlCenterAdmin is ignored) -->
846846
<!-- DashboardReader role grants dashboard-only access when that setting is enabled -->
847-
{% if request.endpoint == 'control_center' and ((app_settings.require_member_of_control_center_admin and session.get('user') and 'ControlCenterAdmin' in session['user']['roles']) or (app_settings.require_member_of_control_center_dashboard_reader and session.get('user') and 'ControlCenterDashboardReader' in session['user']['roles']) or (not app_settings.require_member_of_control_center_admin and 'Admin' in session['user']['roles'])) %}
847+
{% if request.endpoint == 'frontend_control_center.control_center' and ((app_settings.require_member_of_control_center_admin and session.get('user') and 'ControlCenterAdmin' in session['user']['roles']) or (app_settings.require_member_of_control_center_dashboard_reader and session.get('user') and 'ControlCenterDashboardReader' in session['user']['roles']) or (not app_settings.require_member_of_control_center_admin and 'Admin' in session['user']['roles'])) %}
848848
{% set control_center_menu_expanded = sidebar_menu_state.get('controlCenter', true) %}
849849
<div class="overflow-auto">
850850
<div id="control-center-toggle" class="mt-2 mb-1 ps-3 pe-2 text-muted small d-flex align-items-center justify-content-between" style="font-weight: 500; letter-spacing: 0.02em; cursor: pointer; user-select: none;" role="button" tabindex="0" aria-controls="control-center-section" aria-expanded="{{ 'true' if control_center_menu_expanded else 'false' }}" data-sidebar-menu-key="controlCenter" data-sidebar-menu-target="control-center-section" data-sidebar-menu-caret="control-center-caret">
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Control Center Left Nav Endpoint Fix
2+
3+
Fixed/Implemented in version: **0.250.052**
4+
5+
## Issue Description
6+
7+
Admins could open Control Center while the left navigation Control Center section stayed hidden, even when the ControlCenterAdmin and ControlCenterDashboardReader app-role settings were disabled.
8+
9+
## Root Cause Analysis
10+
11+
The full sidebar template checked for the unqualified endpoint name `control_center`. The route is registered on the `frontend_control_center` Blueprint, so Flask exposes the endpoint as `frontend_control_center.control_center`. The mismatch prevented the page-local Control Center left-nav section from rendering.
12+
13+
## Technical Details
14+
15+
Files modified:
16+
17+
- `application/single_app/templates/_sidebar_nav.html`
18+
- `application/single_app/config.py`
19+
- `functional_tests/test_control_center_left_nav_endpoint.py`
20+
21+
Code changes summary:
22+
23+
- Updated the Control Center sidebar condition to match the blueprint-qualified endpoint.
24+
- Preserved the existing role fallback where regular `Admin` users get Control Center navigation when ControlCenterAdmin enforcement is disabled.
25+
- Added a regression test for the endpoint condition and version bump.
26+
27+
## Validation
28+
29+
Validation approach:
30+
31+
- Run `python functional_tests/test_control_center_left_nav_endpoint.py`.
32+
- Run `git -c core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol diff --check`.
33+
34+
Before: the Control Center page could load but the left nav section was not rendered because the endpoint check did not match.
35+
36+
After: the sidebar condition matches `frontend_control_center.control_center`, allowing authorized admins to see the Control Center left-nav section.
37+
38+
Related issue: Fixes #1009
39+
40+
Version reference: `application/single_app/config.py` version `0.250.052`.

docs/explanation/release_notes.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
For feature-focused and fix-focused drill-downs by version, see [Features by Version](/explanation/features/) and [Fixes by Version](/explanation/fixes/).
44

5+
### **(v0.250.052)**
6+
7+
#### Bug Fixes
8+
9+
* **Control Center Left Nav Endpoint Fix**
10+
* Fixed an issue where admins could open Control Center while the left navigation Control Center section stayed hidden when ControlCenterAdmin enforcement was disabled.
11+
* Updated the sidebar endpoint check to use the blueprint-qualified `frontend_control_center.control_center` route and added regression coverage for the regular Admin fallback.
12+
* (Ref: microsoft/simplechat#1009, `_sidebar_nav.html`, `test_control_center_left_nav_endpoint.py`)
13+
514
### **(v0.250.051)**
615

716
#### User Interface Enhancements
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# test_control_center_left_nav_endpoint.py
2+
#!/usr/bin/env python3
3+
"""
4+
Functional test for Control Center left nav endpoint matching.
5+
Version: 0.250.052
6+
Implemented in: 0.250.052
7+
8+
This test ensures the Control Center sidebar section uses the blueprint-qualified
9+
endpoint so admins see the left nav when ControlCenterAdmin enforcement is disabled.
10+
"""
11+
12+
from pathlib import Path
13+
14+
15+
ROOT = Path(__file__).resolve().parents[1]
16+
17+
18+
def read_text(relative_path: str) -> str:
19+
"""Read a repository file as UTF-8 text."""
20+
return (ROOT / relative_path).read_text(encoding="utf-8")
21+
22+
23+
def test_control_center_sidebar_uses_blueprint_endpoint() -> bool:
24+
"""Validate the Control Center sidebar section matches the registered endpoint."""
25+
print("Testing Control Center sidebar endpoint match...")
26+
sidebar_template = read_text("application/single_app/templates/_sidebar_nav.html")
27+
28+
expected_endpoint_check = "request.endpoint == 'frontend_control_center.control_center'"
29+
stale_endpoint_check = "request.endpoint == 'control_center'"
30+
31+
if expected_endpoint_check not in sidebar_template:
32+
print("Control Center sidebar does not use the blueprint-qualified endpoint.")
33+
return False
34+
35+
if stale_endpoint_check in sidebar_template:
36+
print("Control Center sidebar still contains the stale unqualified endpoint check.")
37+
return False
38+
39+
print("Control Center sidebar endpoint match found.")
40+
return True
41+
42+
43+
def test_control_center_regular_admin_fallback_preserved() -> bool:
44+
"""Validate regular admins still get Control Center nav when app-role enforcement is disabled."""
45+
print("Testing Control Center regular Admin fallback...")
46+
sidebar_template = read_text("application/single_app/templates/_sidebar_nav.html")
47+
48+
required_snippets = [
49+
"not app_settings.require_member_of_control_center_admin and 'Admin' in session['user']['roles']",
50+
"app_settings.require_member_of_control_center_dashboard_reader",
51+
"ControlCenterDashboardReader",
52+
"ControlCenterAdmin",
53+
]
54+
55+
missing_snippets = [snippet for snippet in required_snippets if snippet not in sidebar_template]
56+
if missing_snippets:
57+
print(f"Missing Control Center role fallback snippets: {missing_snippets}")
58+
return False
59+
60+
print("Control Center regular Admin fallback preserved.")
61+
return True
62+
63+
64+
def test_config_version_bumped_for_control_center_left_nav_fix() -> bool:
65+
"""Validate the repository version bump for the Control Center left nav fix."""
66+
print("Testing config version bump for Control Center left nav fix...")
67+
config_content = read_text("application/single_app/config.py")
68+
69+
if 'VERSION = "0.250.052"' not in config_content:
70+
print("Config version was not bumped to 0.250.052")
71+
return False
72+
73+
print("Config version bump found.")
74+
return True
75+
76+
77+
if __name__ == "__main__":
78+
checks = [
79+
test_control_center_sidebar_uses_blueprint_endpoint,
80+
test_control_center_regular_admin_fallback_preserved,
81+
test_config_version_bumped_for_control_center_left_nav_fix,
82+
]
83+
84+
results = []
85+
for check in checks:
86+
print(f"\nRunning {check.__name__}...")
87+
results.append(check())
88+
89+
success = all(results)
90+
print(f"\nResults: {sum(results)}/{len(results)} checks passed")
91+
raise SystemExit(0 if success else 1)

0 commit comments

Comments
 (0)