1
0
forked from baron/baron-sso

orgfront 권한 정리

This commit is contained in:
2026-06-10 08:37:27 +09:00
parent cad1162597
commit 28478309fa
20 changed files with 2271 additions and 7 deletions

View File

@@ -135,6 +135,130 @@ func clientTenantAccessAllowed(profile *domain.UserProfileResponse, client domai
return false
}
func clientTenantAccessAllowedForSubtree(c *fiber.Ctx, tenantSvc service.TenantService, profile *domain.UserProfileResponse, client domain.HydraClient) bool {
if clientTenantAccessAllowed(profile, client) {
return true
}
if tenantSvc == nil || profile == nil {
return false
}
allowedTenants := make([]domain.Tenant, 0)
for _, identifier := range clientAllowedTenants(client.Metadata) {
if tenant, ok := resolveTenantAccessTenant(c, tenantSvc, domain.Tenant{ID: identifier, Slug: identifier}); ok {
allowedTenants = append(allowedTenants, tenant)
}
}
if len(allowedTenants) == 0 {
return false
}
for _, candidate := range tenantAccessProfileTenants(profile) {
resolvedCandidate, ok := resolveTenantAccessTenant(c, tenantSvc, candidate)
if !ok {
continue
}
for _, allowed := range allowedTenants {
if tenantMatchesOrDescendsFrom(c, tenantSvc, resolvedCandidate, allowed) {
return true
}
}
}
return false
}
func tenantAccessProfileTenants(profile *domain.UserProfileResponse) []domain.Tenant {
if profile == nil {
return nil
}
seen := make(map[string]struct{})
tenants := make([]domain.Tenant, 0, len(profile.ManageableTenants)+len(profile.JoinedTenants)+2)
add := func(tenant domain.Tenant) {
key := strings.ToLower(firstNonEmptyString(tenant.ID, tenant.Slug, tenant.Name))
if key == "" {
return
}
if _, ok := seen[key]; ok {
return
}
seen[key] = struct{}{}
tenants = append(tenants, tenant)
}
if profile.Tenant != nil {
add(*profile.Tenant)
}
if profile.TenantID != nil {
add(domain.Tenant{ID: strings.TrimSpace(*profile.TenantID)})
}
for _, tenant := range profile.ManageableTenants {
add(tenant)
}
for _, tenant := range profile.JoinedTenants {
add(tenant)
}
return tenants
}
func resolveTenantAccessTenant(c *fiber.Ctx, tenantSvc service.TenantService, tenant domain.Tenant) (domain.Tenant, bool) {
if tenantSvc == nil {
return tenant, firstNonEmptyString(tenant.ID, tenant.Slug) != ""
}
if strings.TrimSpace(tenant.ID) != "" {
if resolved, err := tenantSvc.GetTenant(c.Context(), strings.TrimSpace(tenant.ID)); err == nil && resolved != nil {
return *resolved, true
}
}
if strings.TrimSpace(tenant.Slug) != "" {
if resolved, err := tenantSvc.GetTenantBySlug(c.Context(), strings.TrimSpace(tenant.Slug)); err == nil && resolved != nil {
return *resolved, true
}
}
return tenant, firstNonEmptyString(tenant.ID, tenant.Slug) != ""
}
func tenantMatchesOrDescendsFrom(c *fiber.Ctx, tenantSvc service.TenantService, tenant domain.Tenant, ancestor domain.Tenant) bool {
if tenantAccessTenantMatches(tenant, ancestor) {
return true
}
if tenantSvc == nil {
return false
}
visited := make(map[string]struct{})
current := tenant
for current.ParentID != nil && strings.TrimSpace(*current.ParentID) != "" {
parentID := strings.TrimSpace(*current.ParentID)
if _, ok := visited[parentID]; ok {
return false
}
visited[parentID] = struct{}{}
parent, err := tenantSvc.GetTenant(c.Context(), parentID)
if err != nil || parent == nil {
return false
}
if tenantAccessTenantMatches(*parent, ancestor) {
return true
}
current = *parent
}
return false
}
func tenantAccessTenantMatches(left, right domain.Tenant) bool {
leftID := strings.ToLower(strings.TrimSpace(left.ID))
rightID := strings.ToLower(strings.TrimSpace(right.ID))
if leftID != "" && rightID != "" && leftID == rightID {
return true
}
leftSlug := strings.ToLower(strings.TrimSpace(left.Slug))
rightSlug := strings.ToLower(strings.TrimSpace(right.Slug))
return leftSlug != "" && rightSlug != "" && leftSlug == rightSlug
}
type tenantAccessDeniedDetails struct {
Account tenantAccessDeniedAccount `json:"account"`
CurrentTenant tenantAccessDeniedTenant `json:"current_tenant"`
@@ -179,7 +303,7 @@ func enforceClientTenantAccess(c *fiber.Ctx, tenantSvc service.TenantService, cl
_ = tenantNotAllowedError(c, details)
return true
}
if !clientTenantAccessAllowed(profile, client) {
if !clientTenantAccessAllowedForSubtree(c, tenantSvc, profile, client) {
_ = tenantNotAllowedError(c, details)
return true
}