From d81684d8d12922901a450dc6ef757c9ac862ee19 Mon Sep 17 00:00:00 2001 From: GareArc Date: Thu, 5 Mar 2026 00:27:47 -0800 Subject: [PATCH] fix: expose license status to unauthenticated /system-features callers After force-logout due to license expiry, the login page calls /system-features without auth. The license block was gated behind is_authenticated, so the frontend always saw status='none' instead of the actual expiry status. Split the guard so license.status and expired_at are always returned while workspace usage details remain auth-gated. --- api/services/feature_service.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api/services/feature_service.py b/api/services/feature_service.py index d94ae49d91..6993bd610c 100644 --- a/api/services/feature_service.py +++ b/api/services/feature_service.py @@ -361,11 +361,14 @@ class FeatureService: ) features.webapp_auth.sso_config.protocol = enterprise_info.get("SSOEnforcedForWebProtocol", "") - if is_authenticated and (license_info := enterprise_info.get("License")): + # License status and expiry are always exposed so the login page can + # show the expiry UI after a force-logout (the user is unauthenticated + # at that point). Workspace usage details remain auth-gated. + if license_info := enterprise_info.get("License"): features.license.status = LicenseStatus(license_info.get("status", LicenseStatus.INACTIVE)) features.license.expired_at = license_info.get("expiredAt", "") - if workspaces_info := license_info.get("workspaces"): + if is_authenticated and (workspaces_info := license_info.get("workspaces")): features.license.workspaces.enabled = workspaces_info.get("enabled", False) features.license.workspaces.limit = workspaces_info.get("limit", 0) features.license.workspaces.size = workspaces_info.get("used", 0)