forked from baron/baron-sso
Merge branch 'feature/user-group' into dev
This commit is contained in:
@@ -39,6 +39,74 @@ func (s *tenantService) GetTenant(ctx context.Context, id string) (*domain.Tenan
|
||||
return s.repo.FindByID(ctx, id)
|
||||
}
|
||||
|
||||
func (s *tenantService) ListManageableTenants(ctx context.Context, userID string) ([]domain.Tenant, error) {
|
||||
if s.keto == nil {
|
||||
return nil, errors.New("keto service not initialized")
|
||||
}
|
||||
|
||||
// 1. 직접 관리자인 테넌트 ID 목록 (Tenant:ID#admins@User:ID)
|
||||
directTenantIDs, err := s.keto.ListObjects(ctx, "Tenant", "admins", "User:"+userID)
|
||||
if err != nil {
|
||||
slog.Error("Failed to list direct tenants", "userID", userID, "error", err)
|
||||
}
|
||||
|
||||
// 2. 관리 권한이 있는 유저 그룹 목록 (UserGroup:ID#owners@User:ID)
|
||||
// 정책: 그룹장은 해당 그룹(테넌트)의 어드민이 된다.
|
||||
ownedGroupIDs, err := s.keto.ListObjects(ctx, "UserGroup", "owners", "User:"+userID)
|
||||
if err != nil {
|
||||
slog.Error("Failed to list owned groups", "userID", userID, "error", err)
|
||||
}
|
||||
|
||||
// 3. 멤버로 속한 유저 그룹 목록 (UserGroup:ID#members@User:ID)
|
||||
memberGroupIDs, err := s.keto.ListObjects(ctx, "UserGroup", "members", "User:"+userID)
|
||||
if err != nil {
|
||||
slog.Error("Failed to list group memberships", "userID", userID, "error", err)
|
||||
}
|
||||
|
||||
// 4. 유저 그룹을 통해 상속받은 테넌트 목록 조회 (Tenant:ID#manage@UserGroup:ID#members)
|
||||
var inheritedTenantIDs []string
|
||||
allMyGroups := append(ownedGroupIDs, memberGroupIDs...)
|
||||
for _, groupID := range allMyGroups {
|
||||
// 해당 그룹에 부여된 테넌트 관리 권한 역추적
|
||||
relations, err := s.keto.ListRelations(ctx, "Tenant", "", "manage", "UserGroup:"+groupID+"#members")
|
||||
if err == nil {
|
||||
for _, r := range relations {
|
||||
inheritedTenantIDs = append(inheritedTenantIDs, r.Object)
|
||||
}
|
||||
}
|
||||
// view 권한도 관리 가능 목록에 포함 (필요 시)
|
||||
relationsView, err := s.keto.ListRelations(ctx, "Tenant", "", "view", "UserGroup:"+groupID+"#members")
|
||||
if err == nil {
|
||||
for _, r := range relationsView {
|
||||
inheritedTenantIDs = append(inheritedTenantIDs, r.Object)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 합산 및 중복 제거
|
||||
allIDsMap := make(map[string]bool)
|
||||
for _, id := range directTenantIDs {
|
||||
allIDsMap[id] = true
|
||||
}
|
||||
for _, id := range ownedGroupIDs {
|
||||
allIDsMap[id] = true // 그룹 자체도 테넌트이므로 포함
|
||||
}
|
||||
for _, id := range inheritedTenantIDs {
|
||||
allIDsMap[id] = true
|
||||
}
|
||||
|
||||
allIDs := make([]string, 0, len(allIDsMap))
|
||||
for id := range allIDsMap {
|
||||
allIDs = append(allIDs, id)
|
||||
}
|
||||
|
||||
if len(allIDs) == 0 {
|
||||
return []domain.Tenant{}, nil
|
||||
}
|
||||
|
||||
return s.repo.FindByIDs(ctx, allIDs)
|
||||
}
|
||||
|
||||
func (s *tenantService) RegisterTenant(ctx context.Context, name, slug, description string, domains []string) (*domain.Tenant, error) {
|
||||
// Validate Slug
|
||||
if ok, msg := utils.ValidateSlug(slug); !ok {
|
||||
|
||||
Reference in New Issue
Block a user