1
0
forked from baron/baron-sso

fix: resolve tenant member removal and move aggregation bugs

- adminfront: Update removeMutation to correctly pass 'isRemoveTenant: true' and the specific tenant slug instead of empty string
- backend: Fix 'Move' operation (Normal Update) in UpdateUser to correctly remove the old primary company code from the 'companyCodes' array and sync the deletion to Keto, ensuring accurate member count aggregation
This commit is contained in:
2026-05-07 15:43:08 +09:00
parent 9e45313b5d
commit f6cf261fd5
2 changed files with 49 additions and 21 deletions

View File

@@ -229,7 +229,8 @@ const MemberTable: React.FC<{
}); });
const removeMutation = useMutation({ const removeMutation = useMutation({
mutationFn: (userId: string) => updateUser(userId, { tenantSlug: "" }), mutationFn: (userId: string) =>
updateUser(userId, { tenantSlug, isRemoveTenant: true }),
onSuccess: () => { onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["tenants-full-tree-v2"] }); queryClient.invalidateQueries({ queryKey: ["tenants-full-tree-v2"] });
toast.success(t("msg.info.saved_success", "조직에서 제외되었습니다.")); toast.success(t("msg.info.saved_success", "조직에서 제외되었습니다."));

View File

@@ -1588,27 +1588,54 @@ func (h *UserHandler) UpdateUser(c *fiber.Ctx) error {
} }
} }
} else { } else {
// Normal update: replace primary company code and ensure it's in existingCodes // Normal update (Move): replace primary company code and remove the old one from existingCodes
traits["companyCode"] = code currentPrimary := extractTraitString(traits, "companyCode")
// Resolve TenantID for Kratos Trait if currentPrimary != "" && currentPrimary != code {
if h.TenantService != nil && code != "" { // Remove old primary from existingCodes
if tenant, err := h.TenantService.GetTenantBySlug(c.Context(), code); err == nil && tenant != nil { var newCodes []string
traits["tenant_id"] = tenant.ID for _, existing := range existingCodes {
} if existing != currentPrimary {
} newCodes = append(newCodes, existing)
}
}
existingCodes = newCodes
found := false // [Keto Sync] Remove membership for the old tenant
for _, existing := range existingCodes { if h.TenantService != nil && h.KetoOutboxRepo != nil {
if existing == code { go func(removedSlug string) {
found = true bgCtx := context.Background()
break if t, err := h.TenantService.GetTenantBySlug(bgCtx, removedSlug); err == nil && t != nil {
} _ = h.KetoOutboxRepo.Create(bgCtx, &domain.KetoOutbox{
} Namespace: "Tenant",
if !found && code != "" { Object: t.ID,
existingCodes = append(existingCodes, code) Relation: "members",
} Subject: "User:" + userID,
} Action: domain.KetoOutboxActionDelete,
} })
}
}(currentPrimary)
}
}
traits["companyCode"] = code
// Resolve TenantID for Kratos Trait
if h.TenantService != nil && code != "" {
if tenant, err := h.TenantService.GetTenantBySlug(c.Context(), code); err == nil && tenant != nil {
traits["tenant_id"] = tenant.ID
}
}
found := false
for _, existing := range existingCodes {
if existing == code {
found = true
break
}
}
if !found && code != "" {
existingCodes = append(existingCodes, code)
}
} }
// Deduplicate and save back companyCodes // Deduplicate and save back companyCodes
var codesToSave []string var codesToSave []string