You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
boundary/internal/perms/output_fields.go

143 lines
4.0 KiB

package perms
import (
"sort"
"github.com/hashicorp/boundary/globals"
)
// OutputFields is used to store information about allowed output fields in
// grants
type OutputFields struct {
fields map[string]bool
}
// AddFields adds the given fields and returns the interface. It is safe to call
// this on a nil object, which will create a new object and add the fields to
// it; if relying on this make sure to assign to the output, e.g.:
//
// outFields = outFields.AddFields([]string{"foo", "bar"})
//
// Notes:
//
// - Adding non-nil but empty input will be construed as "no fields"
//
// - Fields compose, they do not overwrite; if you want to start over, create a
// new OutputFields struct
func (o *OutputFields) AddFields(input []string) *OutputFields {
ret := o
if ret == nil {
ret = new(OutputFields)
}
switch {
case input == nil:
// Do nothing
case len(input) == 0:
// Ensure we set to non-nil if it isn't already to capture that input is
// not empty but fields are not being added
if ret.fields == nil {
ret.fields = make(map[string]bool)
}
case len(ret.fields) == 1 && ret.fields["*"]:
// Again do nothing, there's nothing to add
default:
// Ensure the map is valid
if ret.fields == nil {
ret.fields = make(map[string]bool, len(input))
}
// Go through and add fields
for _, k := range input {
if k == "*" {
ret.fields = map[string]bool{k: true}
return ret
}
ret.fields[k] = true
}
}
return ret
}
// Fields returns an alphabetical string slice of the fields in the map. The
// return value will be nil with hasSetFields false if fields are unset (e.g.
// we'd use the defaults in SelfOrDefaults), and non-nil (but empty if no fields
// are allowed) with hasSetFields true if fields have been configured. It is
// safe to call this on a nil object; it will return a nil slice and false for
// hasSetFields.
func (o *OutputFields) Fields() (fields []string, hasSetFields bool) {
if o == nil || o.fields == nil {
return nil, false
}
if len(o.fields) == 0 {
return []string{}, true
}
ret := make([]string, 0, len(o.fields))
for f := range o.fields {
ret = append(ret, f)
}
sort.Strings(ret)
return ret, true
}
// SelfOrDefaults returns either the output fields itself or the defaults for
// the given user. It is safe to call this on a nil object (it will always
// return defaults for the given user ID); if relying on this make sure to
// assign to the output, e.g.:
//
// outFields = outFields.SelfOrDefaults("foo")
func (o *OutputFields) SelfOrDefaults(userId string) *OutputFields {
ret := o
if ret == nil {
ret = new(OutputFields)
}
switch {
case ret.fields != nil:
// We have values set (which may be empty) so use those
return ret
case userId == "":
// This shouldn't happen, and if it does, don't allow anything to be
// output -- keep map empty and set to not-default so we use the empty
// map
ret.fields = make(map[string]bool)
case userId == globals.AnonymousUserId:
ret.fields = map[string]bool{
globals.IdField: true,
globals.ScopeField: true,
globals.ScopeIdField: true,
globals.PluginIdField: true,
globals.PluginField: true,
globals.NameField: true,
globals.DescriptionField: true,
globals.TypeField: true,
globals.IsPrimaryField: true,
globals.PrimaryAuthMethodIdField: true,
globals.AuthorizedActionsField: true,
globals.AuthorizedCollectionActionsField: true,
}
default:
// Default behavior is to allow all fields
ret.fields = map[string]bool{
"*": true,
}
}
return ret
}
// Has returns true if the field should be allowed; that is, it is explicitly
// allowed, or the fields contains *. It is safe to call this on a nil object
// (it will always return false).
func (o *OutputFields) Has(in string) bool {
if o == nil || o.fields == nil {
return false
}
return o.fields["*"] || o.fields[in]
}