From cbddf409d5ce259d31efcb3b50751c26728be268 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Mon, 23 Feb 2026 21:38:05 +0100 Subject: [PATCH] Auto-promote tenant requester as TenantAdmin on preview approval When a Galactic Admin approves a tenant for Private Preview, the user who originally signed up (stored in TenantConfiguration.UpdatedBy) is automatically added as TenantAdmin. This avoids manual admin assignment after approval. Also fixes GitHub repository link in the portal footer. Co-Authored-By: Claude Sonnet 4.6 --- .../Functions/PreviewWhitelistFunction.cs | 50 ++++++++++++++++++- src/Web/autopilot-monitor-web/app/page.tsx | 2 +- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/PreviewWhitelistFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/PreviewWhitelistFunction.cs index cbb14a8f..cb31ea54 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/PreviewWhitelistFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/PreviewWhitelistFunction.cs @@ -18,15 +18,21 @@ public class PreviewWhitelistFunction private readonly ILogger _logger; private readonly PreviewWhitelistService _previewWhitelistService; private readonly GalacticAdminService _galacticAdminService; + private readonly TenantConfigurationService _tenantConfigurationService; + private readonly TenantAdminsService _tenantAdminsService; public PreviewWhitelistFunction( ILogger logger, PreviewWhitelistService previewWhitelistService, - GalacticAdminService galacticAdminService) + GalacticAdminService galacticAdminService, + TenantConfigurationService tenantConfigurationService, + TenantAdminsService tenantAdminsService) { _logger = logger; _previewWhitelistService = previewWhitelistService; _galacticAdminService = galacticAdminService; + _tenantConfigurationService = tenantConfigurationService; + _tenantAdminsService = tenantAdminsService; } /// @@ -92,6 +98,48 @@ public class PreviewWhitelistFunction _logger.LogInformation("Preview tenant approved: {TenantId} by {Upn}", tenantId, upn); + // Auto-promote the tenant requester (first user who triggered tenant config creation) + // as TenantAdmin if they are not already one. + // This ensures whoever signed up doesn't need manual admin assignment after approval. + try + { + var tenantConfig = await _tenantConfigurationService.GetConfigurationAsync(tenantId); + var requesterUpn = tenantConfig.UpdatedBy; + + if (!string.IsNullOrWhiteSpace(requesterUpn) + && !string.Equals(requesterUpn, "System", StringComparison.OrdinalIgnoreCase) + && !string.Equals(requesterUpn, "System (auto-re-enable)", StringComparison.OrdinalIgnoreCase)) + { + var isAlreadyAdmin = await _tenantAdminsService.IsTenantAdminAsync(tenantId, requesterUpn); + if (!isAlreadyAdmin) + { + await _tenantAdminsService.AddTenantAdminAsync(tenantId, requesterUpn, upn!); + _logger.LogInformation( + "Auto-promoted tenant requester {RequesterUpn} as TenantAdmin for tenant {TenantId} on preview approval by {ApprovedBy}", + requesterUpn, tenantId, upn); + } + else + { + _logger.LogInformation( + "Tenant requester {RequesterUpn} is already a TenantAdmin for tenant {TenantId} — skipping auto-promote", + requesterUpn, tenantId); + } + } + else + { + _logger.LogInformation( + "No valid tenant requester UPN found in TenantConfiguration for tenant {TenantId} (UpdatedBy: '{UpdatedBy}') — skipping auto-promote", + tenantId, requesterUpn ?? ""); + } + } + catch (Exception ex) + { + // Non-fatal: approval already succeeded, admin promotion is best-effort + _logger.LogWarning(ex, + "Failed to auto-promote tenant requester as TenantAdmin for tenant {TenantId} — approval still succeeded", + tenantId); + } + var response = req.CreateResponse(HttpStatusCode.Created); await response.WriteAsJsonAsync(new { message = "Tenant approved for preview", tenantId }); return response; diff --git a/src/Web/autopilot-monitor-web/app/page.tsx b/src/Web/autopilot-monitor-web/app/page.tsx index 328508db..40d72218 100644 --- a/src/Web/autopilot-monitor-web/app/page.tsx +++ b/src/Web/autopilot-monitor-web/app/page.tsx @@ -550,7 +550,7 @@ export default function Home() {