generated from coulomb/repo-seed
97 lines
2.6 KiB
Go
97 lines
2.6 KiB
Go
package directory
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"github.com/netkingdom/flex-auth/pkg/api"
|
|
)
|
|
|
|
// MergeResults combines resolver results while keeping source metadata.
|
|
func MergeResults(subject api.SubjectRef, results ...ResolveResult) SubjectEnrichment {
|
|
groups := map[string]struct{}{}
|
|
roles := map[api.CanonicalRole]struct{}{}
|
|
metadata := map[string]any{}
|
|
enrichment := SubjectEnrichment{
|
|
Subject: subject,
|
|
Metadata: metadata,
|
|
}
|
|
|
|
for _, result := range results {
|
|
for _, group := range result.Groups {
|
|
groups[group.ID] = struct{}{}
|
|
if group.Descriptor != nil {
|
|
enrichment.Descriptors = append(enrichment.Descriptors, *group.Descriptor)
|
|
}
|
|
}
|
|
for _, role := range result.Roles {
|
|
roles[role.Role] = struct{}{}
|
|
}
|
|
if !result.Freshness.RetrievedAt.IsZero() || result.Freshness.Source != "" {
|
|
enrichment.Freshness = append(enrichment.Freshness, result.Freshness)
|
|
}
|
|
if result.Overage.Detected {
|
|
enrichment.Overage = append(enrichment.Overage, result.Overage)
|
|
}
|
|
if result.Source != "" {
|
|
metadata["source:"+string(result.Source)] = true
|
|
}
|
|
}
|
|
|
|
enrichment.Groups = sortedStringKeys(groups)
|
|
enrichment.Roles = sortedRoleKeys(roles)
|
|
return enrichment
|
|
}
|
|
|
|
// ApplyToSubject returns a subject with resolved groups, roles, and metadata.
|
|
func ApplyToSubject(subject api.Subject, enrichment SubjectEnrichment) api.Subject {
|
|
out := subject
|
|
out.Groups = mergeStrings(out.Groups, enrichment.Groups)
|
|
out.Roles = mergeRoles(out.Roles, enrichment.Roles)
|
|
if out.Metadata == nil {
|
|
out.Metadata = map[string]any{}
|
|
}
|
|
out.Metadata["directory_freshness"] = enrichment.Freshness
|
|
out.Metadata["directory_overage"] = enrichment.Overage
|
|
return out
|
|
}
|
|
|
|
func mergeStrings(a, b []string) []string {
|
|
items := map[string]struct{}{}
|
|
for _, value := range a {
|
|
items[value] = struct{}{}
|
|
}
|
|
for _, value := range b {
|
|
items[value] = struct{}{}
|
|
}
|
|
return sortedStringKeys(items)
|
|
}
|
|
|
|
func mergeRoles(a, b []api.CanonicalRole) []api.CanonicalRole {
|
|
items := map[api.CanonicalRole]struct{}{}
|
|
for _, value := range a {
|
|
items[value] = struct{}{}
|
|
}
|
|
for _, value := range b {
|
|
items[value] = struct{}{}
|
|
}
|
|
return sortedRoleKeys(items)
|
|
}
|
|
|
|
func sortedStringKeys(items map[string]struct{}) []string {
|
|
keys := make([]string, 0, len(items))
|
|
for key := range items {
|
|
keys = append(keys, key)
|
|
}
|
|
sort.Strings(keys)
|
|
return keys
|
|
}
|
|
|
|
func sortedRoleKeys(items map[api.CanonicalRole]struct{}) []api.CanonicalRole {
|
|
keys := make([]api.CanonicalRole, 0, len(items))
|
|
for key := range items {
|
|
keys = append(keys, key)
|
|
}
|
|
sort.Slice(keys, func(i, j int) bool { return keys[i] < keys[j] })
|
|
return keys
|
|
}
|