forked from baron/baron-sso
fix(backend): prevent duplicate key constraint on empty login id when syncing users
This commit is contained in:
@@ -213,10 +213,52 @@ func (s *userGroupService) List(ctx context.Context, tenantID string) ([]domain.
|
||||
|
||||
func (s *userGroupService) AddMember(ctx context.Context, groupID, userID string) error {
|
||||
// Validate group exists
|
||||
if _, err := s.repo.FindByID(ctx, groupID); err != nil {
|
||||
group, err := s.repo.FindByID(ctx, groupID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("user group not found: %w", err)
|
||||
}
|
||||
|
||||
// [Fix] Sync Kratos Traits & Local DB when a user is added to an organization
|
||||
if s.kratos != nil && s.tenantRepo != nil {
|
||||
tenant, err := s.tenantRepo.FindByID(ctx, group.TenantID)
|
||||
if err == nil && tenant != nil {
|
||||
// Fetch Kratos Identity
|
||||
identity, err := s.kratos.GetIdentity(ctx, userID)
|
||||
if err == nil && identity != nil {
|
||||
traits := identity.Traits
|
||||
if traits == nil {
|
||||
traits = make(map[string]interface{})
|
||||
}
|
||||
traits["companyCode"] = tenant.Slug
|
||||
traits["tenant_id"] = tenant.ID
|
||||
traits["department"] = group.Name
|
||||
|
||||
// Update Kratos
|
||||
_, updateErr := s.kratos.UpdateIdentity(ctx, userID, traits, identity.State)
|
||||
if updateErr != nil {
|
||||
slog.Error("Failed to update identity traits during AddMember", "user", userID, "error", updateErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sync local user repo
|
||||
if s.userRepo != nil && s.tenantRepo != nil {
|
||||
tenant, _ := s.tenantRepo.FindByID(ctx, group.TenantID)
|
||||
if tenant != nil {
|
||||
localUser, err := s.userRepo.FindByID(ctx, userID)
|
||||
if err == nil && localUser != nil {
|
||||
localUser.CompanyCode = tenant.Slug
|
||||
localUser.TenantID = &tenant.ID
|
||||
localUser.Department = group.Name
|
||||
if localUser.LoginID == "" {
|
||||
localUser.LoginID = localUser.ID
|
||||
}
|
||||
_ = s.userRepo.Update(ctx, localUser)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Keto via Outbox: Tenant:<groupID>#members@User:<userID>
|
||||
if s.outboxRepo != nil {
|
||||
_ = s.outboxRepo.Create(ctx, &domain.KetoOutbox{
|
||||
@@ -226,6 +268,15 @@ func (s *userGroupService) AddMember(ctx context.Context, groupID, userID string
|
||||
Subject: "User:" + userID,
|
||||
Action: domain.KetoOutboxActionCreate,
|
||||
})
|
||||
|
||||
// Also add direct Tenant membership to Keto for member counting
|
||||
_ = s.outboxRepo.Create(ctx, &domain.KetoOutbox{
|
||||
Namespace: "Tenant",
|
||||
Object: group.TenantID,
|
||||
Relation: "members",
|
||||
Subject: "User:" + userID,
|
||||
Action: domain.KetoOutboxActionCreate,
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user