* [COMPLIANCE] Update Copyright and License Headers * chore: make gen to generate files with copyright headers * chore: update missed copyright headers --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com> Co-authored-by: Justin Nguyen <justin.nguyen@hashicorp.com>
146 lines
4.1 KiB
Go
146 lines
4.1 KiB
Go
// Copyright IBM Corp. 2020, 2025
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
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]
|
|
}
|