func (ss ScopeSet) FilterAuthorized(authz keppel.Authorization, audience Service, db *keppel.DB) (ScopeSet, error) {
	result := make(ScopeSet, 0, len(ss))
	var additional ScopeSet
	var err error
	for _, scope := range ss {
		filtered := *scope
		switch scope.ResourceType {
		case "registry":
			if audience == AnycastService {
				filtered.Actions = nil
			} else if scope.ResourceName == "catalog" && containsString(scope.Actions, "*") {
				filtered.Actions = []string{"*"}
				err = additional.addCatalogAccess(authz, db)
				if err != nil {
					return nil, err
				}
			} else {
				filtered.Actions = nil
			}
		case "repository":
			if !strings.Contains(scope.ResourceName, "/") {
				filtered.Actions = nil
			} else {
				filtered.Actions, err = filterRepoActions(*scope, authz, db)
				if err != nil {
					return nil, err
				}
			}
		default:
			filtered.Actions = nil
		}
		result.Add(filtered)
	}
	return append(result, additional...), nil
}
FilterAuthorized produces a new ScopeSet containing only those scopes
that the given `authz` is permitted to access and only those actions therein
which this `authz` is permitted to perform.
package auth
import (
	"strings"
	"github.com/sapcc/keppel/internal/keppel"
)
type ScopeSet []*Scope
func (ss ScopeSet) Contains(s Scope) bool {
	for _, scope := range ss {
		if scope.Contains(s) {
			return true
		}
	}
	return false
}
func (ss *ScopeSet) Add(s Scope) {
	for _, other := range *ss {
		if s.ResourceType == other.ResourceType && s.ResourceName == other.ResourceName {
			other.Actions = mergeAndDedupActions(other.Actions, s.Actions)
			return
		}
	}
	*ss = append(*ss, &s)
}
func mergeAndDedupActions(lhs, rhs []string) (result []string) {
	seen := make(map[string]bool)
	for _, elem := range append(lhs, rhs...) {
		if seen[elem] {
			continue
		}
		result = append(result, elem)
		seen[elem] = true
	}
	return
}