From 8c543671d934663c1405e24eb0d8065c082feb6a Mon Sep 17 00:00:00 2001 From: A R R R Associates Date: Fri, 10 Jul 2026 19:59:51 +0530 Subject: [PATCH] Fix invite domain URL and improve shared mobile header --- app/modules/firm_admin_dashboard/service.py | 29 ++++++- .../components/top_workspace_bar.html | 85 ++++++++++++++++--- .../components/workspace_switcher.html | 9 +- 3 files changed, 102 insertions(+), 21 deletions(-) diff --git a/app/modules/firm_admin_dashboard/service.py b/app/modules/firm_admin_dashboard/service.py index b15f3a1..6e7d802 100644 --- a/app/modules/firm_admin_dashboard/service.py +++ b/app/modules/firm_admin_dashboard/service.py @@ -286,8 +286,31 @@ ONBOARDING_ROLE_CONFIG: dict[str, dict[str, str]] = { } -def _public_invite_url(invite_token: str) -> str: - base = (get_settings().ERP_PUBLIC_BASE_URL or "").strip().rstrip("/") or "http://localhost:8000" +def _public_invite_url(request, invite_token: str) -> str: + """Build an invite URL for the domain currently used by the Firm Admin. + + Tenant custom domains must remain tenant-specific. Prefer the request host + (including trusted proxy headers) and retain ERP_PUBLIC_BASE_URL only as a + defensive fallback for non-HTTP callers. + """ + forwarded_proto = (request.headers.get("x-forwarded-proto") or "").split(",", 1)[0].strip().lower() + forwarded_host = (request.headers.get("x-forwarded-host") or "").split(",", 1)[0].strip() + request_host = (request.headers.get("host") or "").strip() + + scheme = forwarded_proto if forwarded_proto in {"http", "https"} else str(request.url.scheme or "https").lower() + host = forwarded_host or request_host or str(request.url.netloc or "").strip() + + # Reject header-control characters before using a host in a generated URL. + if host and not any(ch in host for ch in "\r\n/\\"): + base = f"{scheme}://{host}".rstrip("/") + else: + base = str(request.base_url).strip().rstrip("/") + + if not base: + base = (get_settings().ERP_PUBLIC_BASE_URL or "").strip().rstrip("/") + if not base: + raise ValueError("Unable to determine the public ERP URL for the invite link.") + return f"{base}/invite/accept?token={invite_token}" @@ -498,7 +521,7 @@ def create_firm_internal_user( db.refresh(user) invite_token = issue_invite_token(db, user) - invite_url = _public_invite_url(invite_token) + invite_url = _public_invite_url(request, invite_token) email_status = "not_attempted" email_error = None try: diff --git a/app/ui/templates/components/top_workspace_bar.html b/app/ui/templates/components/top_workspace_bar.html index a4aa317..493014b 100644 --- a/app/ui/templates/components/top_workspace_bar.html +++ b/app/ui/templates/components/top_workspace_bar.html @@ -1,20 +1,21 @@
-
-
-
- +
+
+
+ {% if firm_branding.logo_url %} - {{ current_firm_name }} logo + {{ current_firm_name }} logo {% else %} -
{{ (current_firm_name[:2] if current_firm_name else 'AF')|upper }}
+
{{ (current_firm_name[:2] if current_firm_name else 'AF')|upper }}
{% endif %}
{{ current_firm_name }}
-
{{ current_branch_name if active_branch_id else 'All Branches' }}{% if active_financial_year %} • FY {{ active_financial_year }}{% endif %}
+
{{ current_branch_name if active_branch_id else 'All Branches' }}{% if active_financial_year %} • FY {{ active_financial_year }}{% endif %}
-
+ -
- - Alerts - {% if unread_alert_count %}{{ unread_alert_count }}{% endif %} +
+ + + 🔔 + {% if unread_alert_count %}{{ unread_alert_count }}{% endif %} -
+ + +
+ +
+
+
+
Workspace & context
+
Change workspace, branch or financial year
+
+
+ + {% set workspace_switcher_id = 'workspace_switcher_mobile' %} + {% include "ui/templates/components/workspace_switcher.html" %} + + {% if full_auth and (can_switch_service_tenant(current_user, ui_perms, ui_roles) or can_switch_service_branch(current_user, ui_perms, ui_roles) or can_switch_employee_tenant(current_user, ui_perms, ui_roles) or can_switch_employee_branch(current_user, ui_perms, ui_roles) or can_view_settings(current_user, ui_perms, ui_roles)) %} +
+ {% if can_switch_service_tenant(current_user, ui_perms, ui_roles) or can_switch_employee_tenant(current_user, ui_perms, ui_roles) %} + {% set mobile_context_tenants = get_context_tenants(request, current_user, ui_perms, ui_roles) %} + + {% endif %} + {% if can_switch_service_branch(current_user, ui_perms, ui_roles) or can_switch_employee_branch(current_user, ui_perms, ui_roles) %} + {% set mobile_context_branches = get_context_branches(request, current_user, ui_perms, ui_roles) %} + + {% endif %} + {% if can_view_settings(current_user, ui_perms, ui_roles) %} + {% set mobile_context_financial_years = get_context_financial_years(request, current_user, ui_perms, ui_roles) %} + + {% endif %} +
+ {% endif %} + +
+
+ {% if current_user_photo_url %}Profile photo{% else %}
{{ current_user_initials }}
{% endif %} +
{{ current_user.full_name or current_user.email }}
{{ current_user.email }}
+
+ {% if "Consultant" in ui_roles %}My Profile{% elif "Client" in ui_roles %}My Profile{% else %}My Profile{% endif %} + Change Password + Logout +
+
+
diff --git a/app/ui/templates/components/workspace_switcher.html b/app/ui/templates/components/workspace_switcher.html index d172dc1..c517c6b 100644 --- a/app/ui/templates/components/workspace_switcher.html +++ b/app/ui/templates/components/workspace_switcher.html @@ -3,9 +3,10 @@ {% set perms = ui_perms if ui_perms is defined else [] %} {% set current = current_path if current_path is defined else request.url.path %} {% set can_employee = ('Staff' in roles) or ('Employee' in roles) or ('employees.ess.view' in perms) or ('employees.work.view_self' in perms) or ('employees.attendance.view_self' in perms) or ('employees.leave.view_self' in perms) or ('employees.documents.view_self' in perms) or ('employees.payroll.view_self' in perms) %} -
- - {% if 'System Admin' in roles %}{% endif %} {% if 'Partner' in roles %}{% endif %} @@ -15,6 +16,6 @@ {% if 'Client' in roles %}{% endif %} {% if 'Consultant' in roles %}{% endif %} - All workspaces + All workspaces
{% endif %}