forked from baron/baron-sso
feat(backend): auto-sync user group keto relation based on department in user update
This commit is contained in:
@@ -1042,9 +1042,11 @@ func (h *UserHandler) UpdateUser(c *fiber.Ctx) error {
|
|||||||
// Capture current local state for transition comparison
|
// Capture current local state for transition comparison
|
||||||
var oldRole string
|
var oldRole string
|
||||||
var oldTenantID string
|
var oldTenantID string
|
||||||
|
var oldDepartment string
|
||||||
if h.UserRepo != nil {
|
if h.UserRepo != nil {
|
||||||
if local, err := h.UserRepo.FindByID(c.Context(), userID); err == nil && local != nil {
|
if local, err := h.UserRepo.FindByID(c.Context(), userID); err == nil && local != nil {
|
||||||
oldRole = local.Role
|
oldRole = local.Role
|
||||||
|
oldDepartment = local.Department
|
||||||
if local.TenantID != nil {
|
if local.TenantID != nil {
|
||||||
oldTenantID = *local.TenantID
|
oldTenantID = *local.TenantID
|
||||||
}
|
}
|
||||||
@@ -1237,8 +1239,50 @@ func (h *UserHandler) UpdateUser(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// [Keto Sync] asynchronously as it's less critical for immediate UI count
|
// [Keto Sync] asynchronously as it's less critical for immediate UI count
|
||||||
go h.syncKetoRole(context.Background(), updatedLocalUser.ID,
|
go func() {
|
||||||
extractTraitString(updated.Traits, "grade"), oldRole, oldTenantID, updatedLocalUser.TenantID)
|
bgCtx := context.Background()
|
||||||
|
h.syncKetoRole(bgCtx, updatedLocalUser.ID,
|
||||||
|
extractTraitString(updated.Traits, "grade"), oldRole, oldTenantID, updatedLocalUser.TenantID)
|
||||||
|
|
||||||
|
// Try to automatically sync UserGroup membership based on Department
|
||||||
|
if h.UserGroupRepo != nil && h.KetoOutboxRepo != nil {
|
||||||
|
// 1. Remove from old group if department or tenant changed
|
||||||
|
if oldTenantID != "" && oldDepartment != "" && (oldTenantID != extractTraitString(updated.Traits, "tenant_id") || oldDepartment != updatedLocalUser.Department) {
|
||||||
|
if oldGroups, err := h.UserGroupRepo.ListByTenantID(bgCtx, oldTenantID); err == nil {
|
||||||
|
for _, g := range oldGroups {
|
||||||
|
if strings.EqualFold(g.Name, oldDepartment) {
|
||||||
|
_ = h.KetoOutboxRepo.Create(bgCtx, &domain.KetoOutbox{
|
||||||
|
Namespace: "Tenant",
|
||||||
|
Object: g.ID,
|
||||||
|
Relation: "members",
|
||||||
|
Subject: "User:" + updatedLocalUser.ID,
|
||||||
|
Action: domain.KetoOutboxActionDelete,
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Add to new group
|
||||||
|
if updatedLocalUser.TenantID != nil && updatedLocalUser.Department != "" {
|
||||||
|
if groups, err := h.UserGroupRepo.ListByTenantID(bgCtx, *updatedLocalUser.TenantID); err == nil {
|
||||||
|
for _, g := range groups {
|
||||||
|
if strings.EqualFold(g.Name, updatedLocalUser.Department) {
|
||||||
|
_ = h.KetoOutboxRepo.Create(bgCtx, &domain.KetoOutbox{
|
||||||
|
Namespace: "Tenant",
|
||||||
|
Object: g.ID,
|
||||||
|
Relation: "members",
|
||||||
|
Subject: "User:" + updatedLocalUser.ID,
|
||||||
|
Action: domain.KetoOutboxActionCreate,
|
||||||
|
})
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
if req.Password != nil && *req.Password != "" {
|
if req.Password != nil && *req.Password != "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user