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
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ applyTo: '**'
## Documentation Directory
All new feature documentation should be placed in:
```
..\docs\features\
..\docs\explanation\features\
```

## File Naming Convention
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ applyTo: '**'
## Documentation Directory
All bug fixes and issue resolution documentation should be placed in:
```
..\docs\fixes\
..\docs\explanation\fixes\
```

## File Naming Convention
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ azd env select <environment>
This step will begin the deployment process.

```powershell
Use azd up
azd up
```

## Architecture
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 @@ -88,7 +88,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.235.003"
VERSION = "0.235.012"


SECRET_KEY = os.getenv('SECRET_KEY', 'dev-secret-key-change-in-production')
Expand Down
64 changes: 40 additions & 24 deletions application/single_app/functions_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,10 +731,17 @@ def control_center_required(access_level='admin'):
Args:
access_level: 'admin' for full admin access, 'dashboard' for dashboard-only access

Access logic:
Access logic when require_member_of_control_center_admin is ENABLED:
- ControlCenterAdmin role → Full access to everything (admin + dashboard)
- ControlCenterDashboardReader role → Dashboard access only
- Regular admins → Access when role requirements are disabled (default)
- ControlCenterDashboardReader role → Dashboard access only (if that setting is also enabled)
- Regular Admin role → NO access (must have ControlCenterAdmin)
- ControlCenterAdmin role is REQUIRED - having it without the setting enabled does nothing

Access logic when require_member_of_control_center_admin is DISABLED (default):
- Regular Admin role → Full access to dashboard + management + activity logs
- ControlCenterAdmin role → IGNORED (role feature not enabled)
- ControlCenterDashboardReader role → Dashboard access only (if that setting is enabled)
- Non-admins → NO access
"""
def decorator(f):
@wraps(f)
Expand All @@ -744,37 +751,46 @@ def decorated_function(*args, **kwargs):
require_member_of_control_center_admin = settings.get("require_member_of_control_center_admin", False)
require_member_of_control_center_dashboard_reader = settings.get("require_member_of_control_center_dashboard_reader", False)

has_admin_role = 'roles' in user and 'ControlCenterAdmin' in user['roles']
has_control_center_admin_role = 'roles' in user and 'ControlCenterAdmin' in user['roles']
has_dashboard_reader_role = 'roles' in user and 'ControlCenterDashboardReader' in user['roles']
has_regular_admin_role = 'roles' in user and 'Admin' in user['roles']

# ControlCenterAdmin always has full access
if has_admin_role:
return f(*args, **kwargs)

# For dashboard access, check if DashboardReader role grants access
if access_level == 'dashboard':
if require_member_of_control_center_dashboard_reader and has_dashboard_reader_role:
return f(*args, **kwargs)

# Check if role requirements are enforced
# Check if ControlCenterAdmin role requirement is enforced
if require_member_of_control_center_admin:
# Admin role required but user doesn't have it
# ControlCenterAdmin role is REQUIRED for access
# Only ControlCenterAdmin role grants full access
if has_control_center_admin_role:
return f(*args, **kwargs)

# For dashboard access, check if DashboardReader role grants access
if access_level == 'dashboard':
if require_member_of_control_center_dashboard_reader and has_dashboard_reader_role:
return f(*args, **kwargs)

# User doesn't have ControlCenterAdmin role, deny access
# Note: Regular Admin role does NOT grant access when this setting is enabled
is_api_request = (request.accept_mimetypes.accept_json and not request.accept_mimetypes.accept_html) or request.path.startswith('/api/')
if is_api_request:
return jsonify({"error": "Forbidden", "message": "Insufficient permissions (ControlCenterAdmin role required)"}), 403
else:
return "Forbidden: ControlCenterAdmin role required", 403

if access_level == 'dashboard' and require_member_of_control_center_dashboard_reader:
# Dashboard reader role required but user doesn't have it
is_api_request = (request.accept_mimetypes.accept_json and not request.accept_mimetypes.accept_html) or request.path.startswith('/api/')
if is_api_request:
return jsonify({"error": "Forbidden", "message": "Insufficient permissions (ControlCenterDashboardReader role required)"}), 403
else:
return "Forbidden: ControlCenterDashboardReader role required", 403
# ControlCenterAdmin requirement is NOT enforced (default behavior)
# Only regular Admin role grants access - ControlCenterAdmin role is IGNORED
if has_regular_admin_role:
return f(*args, **kwargs)

# No role requirements enabled → allow all admins (default behavior)
return f(*args, **kwargs)
# For dashboard-only access, check if DashboardReader role is enabled and user has it
if access_level == 'dashboard':
if require_member_of_control_center_dashboard_reader and has_dashboard_reader_role:
return f(*args, **kwargs)

# User is not an admin and doesn't have special roles - deny access
is_api_request = (request.accept_mimetypes.accept_json and not request.accept_mimetypes.accept_html) or request.path.startswith('/api/')
if is_api_request:
return jsonify({"error": "Forbidden", "message": "Insufficient permissions (Admin role required)"}), 403
else:
return "Forbidden: Admin role required", 403
return decorated_function
return decorator

Expand Down
3 changes: 2 additions & 1 deletion application/single_app/route_frontend_admin_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,8 @@ def is_valid_url(url):
# Workspaces
'enable_user_workspace': form_data.get('enable_user_workspace') == 'on',
'enable_group_workspaces': form_data.get('enable_group_workspaces') == 'on',
'enable_group_creation': form_data.get('enable_group_creation') == 'on',
# disable_group_creation is inverted: when checked (on), enable_group_creation = False
'enable_group_creation': form_data.get('disable_group_creation') != 'on',
'enable_public_workspaces': form_data.get('enable_public_workspaces') == 'on',
'enable_file_sharing': form_data.get('enable_file_sharing') == 'on',
'enable_file_processing_logs': enable_file_processing_logs,
Expand Down
20 changes: 18 additions & 2 deletions application/single_app/route_frontend_control_center.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,30 @@ def control_center():
stats = get_control_center_statistics()

# Check user's role for frontend conditional rendering
# Determine if user has full admin access (can see all tabs)
user = session.get('user', {})
has_admin_role = 'ControlCenterAdmin' in user.get('roles', [])
user_roles = user.get('roles', [])
require_member_of_control_center_admin = settings.get("require_member_of_control_center_admin", False)

# User has full admin access based on which role requirement is active:
# - When require_member_of_control_center_admin is ENABLED: Only ControlCenterAdmin role grants access
# - When require_member_of_control_center_admin is DISABLED: Only regular Admin role grants access
has_control_center_admin_role = 'ControlCenterAdmin' in user_roles
has_regular_admin_role = 'Admin' in user_roles

# Full admin access means they can see dashboard + management tabs + activity logs
if require_member_of_control_center_admin:
# ControlCenterAdmin role is required - only that role grants full access
has_full_admin_access = has_control_center_admin_role
else:
# ControlCenterAdmin requirement is disabled - only regular Admin role grants full access
has_full_admin_access = has_regular_admin_role

return render_template('control_center.html',
app_settings=public_settings,
settings=public_settings,
statistics=stats,
has_control_center_admin=has_admin_role)
has_control_center_admin=has_full_admin_access)
except Exception as e:
debug_print(f"Error loading control center: {e}")
flash(f"Error loading control center: {str(e)}", "error")
Expand Down
4 changes: 4 additions & 0 deletions application/single_app/static/js/group/manage_group.js
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,10 @@ function copyRawActivityToClipboard() {
});
}

// Make functions globally available for onclick handlers
window.showRawActivity = showRawActivity;
window.copyRawActivityToClipboard = copyRawActivityToClipboard;

function showCsvError(message) {
$("#csvErrorList").html(`<pre class="mb-0">${escapeHtml(message)}</pre>`);
$("#csvErrorDetails").show();
Expand Down
20 changes: 14 additions & 6 deletions application/single_app/templates/_sidebar_nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,11 @@
</div>
{% endif %}

<!-- Control Center Section - Show when on control center page for admins OR users with ControlCenter roles -->
{% if request.endpoint == 'control_center' 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 ('Admin' in session['user']['roles'] and not app_settings.require_member_of_control_center_admin and not app_settings.require_member_of_control_center_dashboard_reader)) %}
<!-- Control Center Section - Show when on control center page for users with proper access -->
<!-- Access logic: When require_member_of_control_center_admin is ENABLED, only ControlCenterAdmin role grants access -->
<!-- When DISABLED (default), only regular Admin role grants access (ControlCenterAdmin is ignored) -->
<!-- DashboardReader role grants dashboard-only access when that setting is enabled -->
{% 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'])) %}
<div class="overflow-auto">
<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;">
<div class="d-flex align-items-center">
Expand Down Expand Up @@ -513,8 +516,10 @@
<i class="bi bi-speedometer2 me-2"></i><span class="nav-text">Dashboard</span>
</a>
</li>
{# Only show admin tabs if user has ControlCenterAdmin role #}
{% if session.get('user') and 'ControlCenterAdmin' in session['user']['roles'] %}
{# Only show admin tabs if user has full admin access based on settings #}
{# When require_member_of_control_center_admin is ENABLED: need ControlCenterAdmin role #}
{# When DISABLED: need regular Admin role #}
{% if (app_settings.require_member_of_control_center_admin and session.get('user') and 'ControlCenterAdmin' in session['user']['roles']) or (not app_settings.require_member_of_control_center_admin and session.get('user') and 'Admin' in session['user']['roles']) %}
<li class="nav-item">
<a class="nav-link d-flex align-items-center control-center-nav-tab" href="#" data-tab="users">
<i class="bi bi-people me-2"></i><span class="nav-text">User Management</span>
Expand Down Expand Up @@ -687,8 +692,11 @@
<a class="dropdown-item" href="{{ url_for('admin_settings') }}">App Settings</a>
</li>
{% endif %}
{# Control Center - accessible to admins OR users with ControlCenter roles #}
{% if (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 ('Admin' in session['user']['roles'] and not app_settings.require_member_of_control_center_admin and not app_settings.require_member_of_control_center_dashboard_reader) %}
{# Control Center - access based on role requirements #}
{# When require_member_of_control_center_admin ENABLED: only ControlCenterAdmin role grants access #}
{# When DISABLED (default): only regular Admin role grants access #}
{# DashboardReader role grants dashboard-only access when that setting is enabled #}
{% if (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']) %}
<li>
<a class="dropdown-item" href="{{ url_for('control_center') }}">Control Center</a>
</li>
Expand Down
7 changes: 5 additions & 2 deletions application/single_app/templates/_top_nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,11 @@
<a class="dropdown-item" href="{{ url_for('admin_settings') }}">App Settings</a>
</li>
{% endif %}
{# Control Center - accessible to admins OR users with ControlCenter roles #}
{% if (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 ('Admin' in session['user']['roles'] and not app_settings.require_member_of_control_center_admin and not app_settings.require_member_of_control_center_dashboard_reader) %}
{# Control Center - access based on role requirements #}
{# When require_member_of_control_center_admin ENABLED: only ControlCenterAdmin role grants access #}
{# When DISABLED (default): only regular Admin role grants access #}
{# DashboardReader role grants dashboard-only access when that setting is enabled #}
{% if (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']) %}
<li>
<a class="dropdown-item" href="{{ url_for('control_center') }}">Control Center</a>
</li>
Expand Down
Loading