package auth import ( "context" "local/dndex/storage" "net/http" "strings" ) type Scope struct { Namespace string EntityName string EntityID string } func GetScope(r *http.Request, gs ...storage.RateLimitedGraph) Scope { scope := Scope{} if ok := scope.fromCtx(r.Context()); ok { return scope } scope.fromToken(r) scope.fromPath(r.URL.Path) for _, g := range gs { scope.fromGraph(r.Context(), g) } reqWithContextValue(r, ScopeKey, scope) return scope } func reqWithContextValue(r *http.Request, k string, v interface{}) { *r = *(r.WithContext(context.WithValue(r.Context(), k, v))) } func (s *Scope) fromCtx(ctx context.Context) bool { var ok bool *s, ok = ctx.Value(ScopeKey).(Scope) return ok } func (s *Scope) fromToken(r *http.Request) bool { token, ok := getToken(r) if ok { s.Namespace = token.Namespace } return ok } func (s *Scope) fromPath(path string) bool { if !strings.HasPrefix(path, "/entities/") { return false } paths := strings.Split(path, "/") if len(paths) < 2 { return false } path = paths[2] path = strings.Split(path, "#")[0] if len(path) == 0 { return false } s.EntityID = path return true } func (s *Scope) fromGraph(ctx context.Context, g storage.RateLimitedGraph) bool { if s.EntityID == "" { return false } one, err := g.Get(ctx, s.Namespace, s.EntityID) ok := err == nil && one.Name != "" if ok { s.EntityName = one.Name } return ok }