1
0
forked from baron/baron-sso

fix: ensure all manageable tenants are visible for tenant admin and refine overview UI

This commit is contained in:
2026-03-04 14:04:18 +09:00
parent 145b807ebf
commit 9da97554ce
3 changed files with 94 additions and 95 deletions

View File

@@ -4046,6 +4046,14 @@ func (h *AuthHandler) resolveCurrentProfile(c *fiber.Ctx) (*domain.UserProfileRe
}
}
// [New] Fetch manageable tenants for Tenant Admin
if profile.Role == domain.RoleTenantAdmin && h.TenantService != nil {
manageable, err := h.TenantService.ListManageableTenants(c.Context(), profile.ID)
if err == nil {
profile.ManageableTenants = manageable
}
}
// 4. Save to Redis Cache (Short TTL)
// IMPORTANT: In dev mode, if role was overridden, we should NOT cache it under the token key
// or we should include the mock role in the cache key.

View File

@@ -53,36 +53,25 @@ func (s *tenantService) ListManageableTenants(ctx context.Context, userID string
return nil, errors.New("keto service not initialized")
}
// 1. 직접 관리자인 테넌트 ID 목록 (Tenant:ID#admins@User:ID)
directAdminIDs, err := s.keto.ListObjects(ctx, "Tenant", "admins", "User:"+userID)
// [Keto] 'Tenant' 네임스페이스에서 'manage' 권한을 가진 모든 테넌트 ID 조회
// OPL(parents 상속 포함) 결과가 반영된 리스트를 가져옵니다.
allIDs, err := s.keto.ListObjects(ctx, "Tenant", "manage", "User:"+userID)
if err != nil {
slog.Error("Failed to list direct admin tenants", "userID", userID, "error", err)
slog.Error("Failed to list manageable tenants from Keto", "userID", userID, "error", err)
return []domain.Tenant{}, nil
}
// 2. 직접 소유자(조직장)인 테넌트 ID 목록 (Tenant:ID#owners@User:ID)
directOwnerIDs, err := s.keto.ListObjects(ctx, "Tenant", "owners", "User:"+userID)
if err != nil {
slog.Error("Failed to list owned tenants", "userID", userID, "error", err)
}
// 합산 및 중복 제거
allIDsMap := make(map[string]bool)
for _, id := range directAdminIDs {
allIDsMap[id] = true
}
for _, id := range directOwnerIDs {
allIDsMap[id] = true
}
// Note: 상속된 권한(부모의 어드민이 자식의 어드민)은 Keto의 OPL에서 처리되므로,
// 특정 유저가 'view' 또는 'manage' 권한을 가진 테넌트를 모두 찾으려면
// Keto의 'expand' 또는 'list objects' 기능을 더 고도화하거나,
// 여기서는 직접 할당된 부모 테넌트를 기준으로 하위 테넌트 정보를 추가 조회하는 로직이 필요할 수 있습니다.
// 우선 직접 할당된 테넌트들만 반환합니다.
allIDs := make([]string, 0, len(allIDsMap))
for id := range allIDsMap {
allIDs = append(allIDs, id)
if len(allIDs) == 0 {
// Fallback: Check direct membership if list objects didn't catch everything
directAdminIDs, _ := s.keto.ListObjects(ctx, "Tenant", "admins", "User:"+userID)
directOwnerIDs, _ := s.keto.ListObjects(ctx, "Tenant", "owners", "User:"+userID)
idMap := make(map[string]bool)
for _, id := range directAdminIDs { idMap[id] = true }
for _, id := range directOwnerIDs { idMap[id] = true }
allIDs = make([]string, 0, len(idMap))
for id := range idMap { allIDs = append(allIDs, id) }
}
if len(allIDs) == 0 {