package auth import ( "errors" "net/http" "github.com/FAU-CDI/wisski-distillery/internal/dis/component" ) var ( ErrUnknownScope = errors.New("unknown scope") ErrParamRequired = errors.New("scope requires parameter") ErrNoParam = errors.New("scope does not take parameter") ) // Scopes returns a map of all available scopes func (auth *Auth) Scopes() map[component.Scope]component.ScopeInfo { scopes := auth.getScopeMap() mp := make(map[component.Scope]component.ScopeInfo, len(scopes)) for scope, entry := range scopes { mp[scope] = entry.Info } return mp } // getScopeMap return a (cached version of) all scopes func (auth *Auth) getScopeMap() map[component.Scope]scopeMapEntry { return auth.scopeMap.Get(func() map[component.Scope]scopeMapEntry { mp := make(map[component.Scope]scopeMapEntry, len(auth.dependencies.ScopeProviders)) for _, p := range auth.dependencies.ScopeProviders { info := p.Scope() mp[info.Scope] = scopeMapEntry{ Provider: p, Info: info, } } return mp }) } // CheckScope checks if the given request is associated with the given request. // A request can be one of two types: // - A signed in user with an implicitly associated set of scopes // - A session authorized with a token only // If the request is denied a scope, the error will be of type AccessDeniedError. func (auth *Auth) CheckScope(param string, scope component.Scope, r *http.Request) error { // the empty scope is always permitted implicitly if scope == "" { return nil } entry, ok := auth.getScopeMap()[scope] if !ok { return ErrUnknownScope } // check that we take a parameter if entry.Info.TakesParam && param == "" { return ErrParamRequired } if !entry.Info.TakesParam && param != "" { return ErrNoParam } // call the checker and return an error ok, err := entry.Provider.HasScope(param, r) if err != nil { return entry.Info.CheckError(err) } if ok { return nil } return entry.Info.DeniedError() }