diff --git a/backend/internal/handler/user_handler.go b/backend/internal/handler/user_handler.go index 89d68177..40d101f1 100644 --- a/backend/internal/handler/user_handler.go +++ b/backend/internal/handler/user_handler.go @@ -1404,20 +1404,31 @@ func (h *UserHandler) syncKetoRole(ctx context.Context, userID, newRole, oldRole newRole = domain.NormalizeRole(newRole) oldRole = domain.NormalizeRole(oldRole) + newTID := "" + if newTenantID != nil { + newTID = *newTenantID + } + if h.KetoOutboxRepo == nil { return } + if oldRole == newRole && oldTenantID == newTID { + return // Nothing changed + } + // 1. Handle Role Changes - // Remove old roles if oldRole == domain.RoleSuperAdmin { - _ = h.KetoOutboxRepo.Create(ctx, &domain.KetoOutbox{ - Namespace: "System", - Object: "global", - Relation: "super_admins", - Subject: "User:" + userID, - Action: domain.KetoOutboxActionDelete, - }) + // Only remove super_admin if the role actually changed (tenant change doesn't matter for global roles) + if oldRole != newRole { + _ = h.KetoOutboxRepo.Create(ctx, &domain.KetoOutbox{ + Namespace: "System", + Object: "global", + Relation: "super_admins", + Subject: "User:" + userID, + Action: domain.KetoOutboxActionDelete, + }) + } } else if oldRole == domain.RoleTenantAdmin && oldTenantID != "" { _ = h.KetoOutboxRepo.Create(ctx, &domain.KetoOutbox{ Namespace: "Tenant", @@ -1430,17 +1441,19 @@ func (h *UserHandler) syncKetoRole(ctx context.Context, userID, newRole, oldRole // Add new roles if newRole == domain.RoleSuperAdmin { - _ = h.KetoOutboxRepo.Create(ctx, &domain.KetoOutbox{ - Namespace: "System", - Object: "global", - Relation: "super_admins", - Subject: "User:" + userID, - Action: domain.KetoOutboxActionCreate, - }) - } else if newRole == domain.RoleTenantAdmin && newTenantID != nil { + if oldRole != newRole { + _ = h.KetoOutboxRepo.Create(ctx, &domain.KetoOutbox{ + Namespace: "System", + Object: "global", + Relation: "super_admins", + Subject: "User:" + userID, + Action: domain.KetoOutboxActionCreate, + }) + } + } else if newRole == domain.RoleTenantAdmin && newTID != "" { _ = h.KetoOutboxRepo.Create(ctx, &domain.KetoOutbox{ Namespace: "Tenant", - Object: *newTenantID, + Object: newTID, Relation: "admins", Subject: "User:" + userID, Action: domain.KetoOutboxActionCreate, @@ -1448,11 +1461,6 @@ func (h *UserHandler) syncKetoRole(ctx context.Context, userID, newRole, oldRole } // 2. Handle Tenant Membership (for count) - newTID := "" - if newTenantID != nil { - newTID = *newTenantID - } - if oldTenantID != newTID { // Remove from old tenant if oldTenantID != "" {