~bigbes/core-go

46a4ad6a4ded21294e5561d8094833674a21ec7d — Drew DeVault 1 year, 10 months ago 0d6031b
auth: add Grants.IsSubset

This is a little bit hacky. Previously DecodeGrants would only store the
list of grants associated with the current service. This minimizes API
breakage by storing all grants as $service/$grant in the map key and
stores the local service name in the grant object, and updates
Grants.Has() to accept "$grant" and infer that it refers to a local
service or accept the fully qualified "$service/$grant" to test against
grants for any service -- which IsSubset makes use of to test that one
Grant object is a subset of another with respect to all services it has
grants for.
1 files changed, 35 insertions(+), 3 deletions(-)

M auth/bearer.go
M auth/bearer.go => auth/bearer.go +35 -3
@@ 90,6 90,7 @@ type Grants struct {

	all     bool
	grants  map[string]string
	local   string
	encoded string
}



@@ 99,6 100,7 @@ func DecodeGrants(ctx context.Context, grants string) (Grants, error) {
		return Grants{
			all:     true,
			grants:  nil,
			local:   config.ServiceName(ctx),
			encoded: "",
		}, nil
	}


@@ 121,18 123,23 @@ func DecodeGrants(ctx context.Context, grants string) (Grants, error) {
		} 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")
	}


@@ 154,6 161,31 @@ func (g *Grants) Has(grant string, mode string) bool {
	}
}

// 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 {
	return g.encoded
}