generated from coulomb/repo-seed
Add directory group resolver adapters
This commit is contained in:
96
internal/adapters/directory/enrichment.go
Normal file
96
internal/adapters/directory/enrichment.go
Normal file
@@ -0,0 +1,96 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user