From ef2190c68776da71216c1446d1997ecd88df7fa0 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Sat, 7 Feb 2026 21:34:56 +0100 Subject: [PATCH] fixed galactic admin check in signalrgroup join/leave --- .../Functions/SignalRAddToGroupFunction.cs | 28 +++++++++++++++++-- .../SignalRRemoveFromGroupFunction.cs | 28 +++++++++++++++++-- 2 files changed, 50 insertions(+), 6 deletions(-) diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/SignalRAddToGroupFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/SignalRAddToGroupFunction.cs index b26951e0..90b8bbed 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/SignalRAddToGroupFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/SignalRAddToGroupFunction.cs @@ -53,11 +53,33 @@ namespace AutopilotMonitor.Functions.Functions var userEmail = TenantHelper.GetUserIdentifier(req); // Validate tenant access - // Group names are in format: "tenant-{tenantId}" or "session-{tenantId}-{sessionId}" + // Group names are in format: "tenant-{tenantId}", "session-{tenantId}-{sessionId}", or "galactic-admins" // Users can only join groups for their own tenant (unless they are Galactic Admin) - var requestedTenantId = ExtractTenantIdFromGroupName(request.GroupName); - if (!string.IsNullOrEmpty(requestedTenantId)) + + // Explicit validation for the galactic-admins group + if (request.GroupName == "galactic-admins") { + var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userEmail); + if (!isGalacticAdmin) + { + _logger.LogWarning($"User {userEmail} (tenant {userTenantId}) attempted to join galactic-admins group without being a Galactic Admin"); + var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); + await forbiddenResponse.WriteAsJsonAsync(new { success = false, message = "Access denied: Only Galactic Admins can join this group" }); + return new AddToGroupOutput { HttpResponse = forbiddenResponse }; + } + _logger.LogInformation($"Galactic Admin {userEmail} joining galactic-admins group"); + } + else + { + var requestedTenantId = ExtractTenantIdFromGroupName(request.GroupName); + if (string.IsNullOrEmpty(requestedTenantId)) + { + _logger.LogWarning($"User {userEmail} attempted to join unrecognized group format: {request.GroupName}"); + var badRequestResponse = req.CreateResponse(HttpStatusCode.BadRequest); + await badRequestResponse.WriteAsJsonAsync(new { success = false, message = "Unrecognized group name format" }); + return new AddToGroupOutput { HttpResponse = badRequestResponse }; + } + // Check if user is allowed to join this tenant's group if (requestedTenantId != userTenantId) { diff --git a/src/Backend/AutopilotMonitor.Functions/Functions/SignalRRemoveFromGroupFunction.cs b/src/Backend/AutopilotMonitor.Functions/Functions/SignalRRemoveFromGroupFunction.cs index 414e55bd..d9b41398 100644 --- a/src/Backend/AutopilotMonitor.Functions/Functions/SignalRRemoveFromGroupFunction.cs +++ b/src/Backend/AutopilotMonitor.Functions/Functions/SignalRRemoveFromGroupFunction.cs @@ -53,11 +53,33 @@ namespace AutopilotMonitor.Functions.Functions var userEmail = TenantHelper.GetUserIdentifier(req); // Validate tenant access (same logic as AddToGroup) - // Group names are in format: "tenant-{tenantId}" or "session-{tenantId}-{sessionId}" + // Group names are in format: "tenant-{tenantId}", "session-{tenantId}-{sessionId}", or "galactic-admins" // Users can only leave groups for their own tenant (unless they are Galactic Admin) - var requestedTenantId = ExtractTenantIdFromGroupName(request.GroupName); - if (!string.IsNullOrEmpty(requestedTenantId)) + + // Explicit validation for the galactic-admins group + if (request.GroupName == "galactic-admins") { + var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userEmail); + if (!isGalacticAdmin) + { + _logger.LogWarning($"User {userEmail} (tenant {userTenantId}) attempted to leave galactic-admins group without being a Galactic Admin"); + var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden); + await forbiddenResponse.WriteAsJsonAsync(new { success = false, message = "Access denied: Only Galactic Admins can leave this group" }); + return new RemoveFromGroupOutput { HttpResponse = forbiddenResponse }; + } + _logger.LogInformation($"Galactic Admin {userEmail} leaving galactic-admins group"); + } + else + { + var requestedTenantId = ExtractTenantIdFromGroupName(request.GroupName); + if (string.IsNullOrEmpty(requestedTenantId)) + { + _logger.LogWarning($"User {userEmail} attempted to leave unrecognized group format: {request.GroupName}"); + var badRequestResponse = req.CreateResponse(HttpStatusCode.BadRequest); + await badRequestResponse.WriteAsJsonAsync(new { success = false, message = "Unrecognized group name format" }); + return new RemoveFromGroupOutput { HttpResponse = badRequestResponse }; + } + // Check if user is allowed to leave this tenant's group if (requestedTenantId != userTenantId) {