forked from baron/baron-sso
feat: implement CSV-based organization chart import and enhance group hierarchy
This commit is contained in:
@@ -81,6 +81,11 @@ func (s *orgChartService) ImportCSV(ctx context.Context, tenantID string, r io.R
|
||||
orgPath := strings.TrimSpace(record[colMap["organization"]])
|
||||
position := strings.TrimSpace(record[colMap["position"]])
|
||||
jobTitle := strings.TrimSpace(record[colMap["jobtitle"]])
|
||||
isOwner := false
|
||||
if idx, ok := colMap["is_owner"]; ok && idx < len(record) {
|
||||
val := strings.ToLower(record[idx])
|
||||
isOwner = val == "true" || val == "y" || val == "1" || val == "yes"
|
||||
}
|
||||
|
||||
if email == "" || name == "" || orgPath == "" {
|
||||
continue
|
||||
@@ -125,13 +130,25 @@ func (s *orgChartService) ImportCSV(ctx context.Context, tenantID string, r io.R
|
||||
|
||||
// 3. Sync Membership to Keto via Outbox
|
||||
if s.ketoOutboxRepo != nil {
|
||||
// Add as member of UserGroup
|
||||
_ = s.ketoOutboxRepo.Create(ctx, &domain.KetoOutbox{
|
||||
Namespace: "Tenant",
|
||||
Namespace: "UserGroup",
|
||||
Object: leafID,
|
||||
Relation: "members",
|
||||
Subject: "User:" + kratosID,
|
||||
Action: domain.KetoOutboxActionCreate,
|
||||
})
|
||||
|
||||
// Add as owner if applicable
|
||||
if isOwner {
|
||||
_ = s.ketoOutboxRepo.Create(ctx, &domain.KetoOutbox{
|
||||
Namespace: "UserGroup",
|
||||
Object: leafID,
|
||||
Relation: "owners",
|
||||
Subject: "User:" + kratosID,
|
||||
Action: domain.KetoOutboxActionCreate,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,19 +178,19 @@ func (s *orgChartService) ensureOrgPath(ctx context.Context, rootTenantID string
|
||||
}
|
||||
|
||||
// Check DB if already exists
|
||||
// We search for a USER_GROUP tenant with this name and parent
|
||||
// Note: This logic assumes name is unique under a parent
|
||||
// For robustness, we should probably have a better lookup
|
||||
var existingID string
|
||||
// In a real implementation, Repo should have a FindByParentAndName method
|
||||
// For this implementation, we'll try to find by Name and ParentID in TenantRepo or UserGroupRepo
|
||||
// Since we're using Polymorphic Tenants, let's assume we can lookup
|
||||
|
||||
// For simplicity in this POC, let's just use Create logic if not in cache
|
||||
// In production, we MUST check DB first to avoid duplicates
|
||||
|
||||
// [Placeholder] Lookup in DB logic...
|
||||
// existingID = s.lookupOrgUnit(ctx, rootTenantID, currentParentID, part)
|
||||
if s.userGroupRepo != nil {
|
||||
groups, err := s.userGroupRepo.ListByTenantID(ctx, rootTenantID)
|
||||
if err == nil {
|
||||
for _, g := range groups {
|
||||
// Match by name and parent
|
||||
if g.Name == part && ((g.ParentID == nil && currentParentID == rootTenantID) || (g.ParentID != nil && *g.ParentID == currentParentID)) {
|
||||
existingID = g.ID
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if existingID == "" {
|
||||
// Create new unit
|
||||
|
||||
Reference in New Issue
Block a user