diff --git a/auth/bearer.go b/auth/bearer.go index 15105847d59a39b720eb1b0b067bb55fdf54950c..a1bc435a4648bfd15c126d5c4e91865186088c97 100644 --- a/auth/bearer.go +++ b/auth/bearer.go @@ -90,6 +90,7 @@ ReadOnly bool all bool grants map[string]string + local string encoded string } @@ -99,6 +100,7 @@ // All permissions return Grants{ all: true, grants: nil, + local: config.ServiceName(ctx), encoded: "", }, nil } @@ -121,18 +123,23 @@ access = "RO" } else { access = parts[1] } - if service == config.ServiceName(ctx) { - accessMap[scope] = access - } + name := fmt.Sprintf("%s/%s", service, scope) + accessMap[name] = access } return Grants{ all: false, grants: accessMap, + local: config.ServiceName(ctx), encoded: grants, }, nil } +// Returns true if these grants include access to a specific OAuth grant. func (g *Grants) Has(grant string, mode string) bool { + if !strings.ContainsRune(grant, '/') { + grant = fmt.Sprintf("%s/%s", g.local, grant) + } + if mode != RO && mode != RW { panic("Invalid access mode") } @@ -152,6 +159,31 @@ return true } return mode == access } +} + +// Returns true if this is a universal grant. +func (g *Grants) HasAll() bool { + return g.all +} + +// Returns true of this grant object contains a subset of the permissions of +// another. +func (g *Grants) IsSubset(other *Grants) bool { + if g.all && !other.all { + return false + } + + if other.all { + return true + } + + for scope, access := range g.grants { + if !other.Has(scope, access) { + return false + } + } + + return true } func (g *Grants) Encode() string {