Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplified attributes #64

Merged
merged 3 commits into from
Oct 6, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions attributes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package bascule

import (
"time"
)

var nilTime = time.Time{}

type attributes map[string]interface{}

func (a attributes) Get(key string) (interface{}, bool) {
v, ok := a[key]
return v, ok
}

kristinapathak marked this conversation as resolved.
Show resolved Hide resolved
//NewAttributes builds an Attributes instance with
//the given map as datasource. Default AttributeOptions are used.
func NewAttributes(m map[string]interface{}) Attributes {
return attributes(m)
}

// GetNestedAttribute uses multiple keys in order to obtain an attribute.
func GetNestedAttribute(attributes Attributes, keys ...string) (interface{}, bool) {
// need at least one key.
if len(keys) == 0 {
return nil, false
}

var (
result interface{}
ok bool
)
result = attributes
for _, k := range keys {
a, ok := result.(Attributes)
if !ok {
return nil, false
}
result, ok = a.Get(k)
if !ok {
return nil, false
}
}
return result, ok
}
204 changes: 7 additions & 197 deletions token.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,203 +3,6 @@
// which can be used to validate are also provided.
package bascule

import (
"time"

"github.com/spf13/cast"
"github.com/spf13/viper"
)

//Attributes is the interface that wraps methods which dictate how to interact
//with a token's attributes. Getter functions return a boolean as second element
//which indicates that a value of the requested type exists at the given key path.
//Key path separators are configurable through AttributeOptions
type Attributes interface {
Get(key string) (interface{}, bool)
GetBool(key string) (bool, bool)
GetDuration(key string) (time.Duration, bool)
GetFloat64(key string) (float64, bool)
GetInt64(key string) (int64, bool)
GetIntSlice(key string) ([]int, bool)
GetString(key string) (string, bool)
GetStringMap(key string) (map[string]interface{}, bool)
GetStringSlice(key string) ([]string, bool)
GetTime(key string) (time.Time, bool)
IsSet(key string) bool
FullView() map[string]interface{}
}

var nilTime = time.Time{}

//AttributesOptions allows customizing Attributes initialization
type AttributesOptions struct {
//KeyDelimiter configures the separator for building key paths
//for the Attributes getter functions. Defaults to '.'
KeyDelimiter string

//AttributesMap is used as the initial attributes datasource
AttributesMap map[string]interface{}
}

type attributes struct {
v *viper.Viper

//Note: having m is superfluous given v. However, it's a caching
//optimization for FullView() since v.AllSettings() is a relatively
//expensive operation
m map[string]interface{}
}

func (a *attributes) Get(key string) (interface{}, bool) {
if !a.v.IsSet(key) {
return nil, false
}

return a.v.Get(key), true
}

func (a *attributes) GetBool(key string) (bool, bool) {
if !a.v.IsSet(key) {
return false, false
}
v, err := cast.ToBoolE(a.v.Get(key))
if err != nil {
return false, false
}
return v, true
}

func (a *attributes) GetDuration(key string) (time.Duration, bool) {
if !a.v.IsSet(key) {
return 0, false
}
v, err := cast.ToDurationE(a.v.Get(key))
if err != nil {
return 0, false
}

return v, true
}
func (a *attributes) GetFloat64(key string) (float64, bool) {
if !a.v.IsSet(key) {
return 0, false
}
v, err := cast.ToFloat64E(a.v.Get(key))
if err != nil {
return 0, false
}

return v, true
}

func (a *attributes) GetInt64(key string) (int64, bool) {
if !a.v.IsSet(key) {
return 0, false
}
v, err := cast.ToInt64E(a.v.Get(key))
if err != nil {
return 0, false
}
return v, true
}

func (a *attributes) GetIntSlice(key string) ([]int, bool) {
if !a.v.IsSet(key) {
return nil, false
}
v, err := cast.ToIntSliceE(a.v.Get(key))
if err != nil {
return nil, false
}
return v, true

}
func (a *attributes) GetString(key string) (string, bool) {
if !a.v.IsSet(key) {
return "", false
}
v, err := cast.ToStringE(a.v.Get(key))
if err != nil {
return "", false
}
return v, true
}
func (a *attributes) GetStringMap(key string) (map[string]interface{}, bool) {
if !a.v.IsSet(key) {
return nil, false
}
v, err := cast.ToStringMapE(a.v.Get(key))
if err != nil {
return nil, false
}
return v, true

}
func (a *attributes) GetStringSlice(key string) ([]string, bool) {
if !a.v.IsSet(key) {
return nil, false
}
v, err := cast.ToStringSliceE(a.v.Get(key))
if err != nil {
return nil, false
}
return v, true
}

func (a *attributes) GetTime(key string) (time.Time, bool) {
if !a.v.IsSet(key) {
return nilTime, false
}
v, err := cast.ToTimeE(a.v.Get(key))
if err != nil {
return nilTime, false
}
return v, true
}

func (a *attributes) IsSet(key string) bool {
return a.v.IsSet(key)
}

func (a *attributes) FullView() map[string]interface{} {
return a.m
}

//NewAttributes builds an empty Attributes instance.
func NewAttributes() Attributes {
return NewAttributesWithOptions(AttributesOptions{})
}

//NewAttributesFromMap builds an Attributes instance with
//the given map as datasource. Default AttributeOptions are used.
func NewAttributesFromMap(m map[string]interface{}) Attributes {
return NewAttributesWithOptions(AttributesOptions{
AttributesMap: m,
})
}

//NewAttributesWithOptions builds an Attributes instance from the given
//options. Zero value options are ok.
func NewAttributesWithOptions(o AttributesOptions) Attributes {
var (
options []viper.Option
v *viper.Viper
)

if o.KeyDelimiter != "" {
options = append(options, viper.KeyDelimiter(o.KeyDelimiter))
}

v = viper.NewWithOptions(options...)

v.MergeConfigMap(o.AttributesMap)

return &attributes{
v: v,
m: o.AttributesMap,
}
}

// Token is the behavior supplied by all secure tokens
type Token interface {
// Type is the custom token type assigned by plugin code
Expand All @@ -213,6 +16,13 @@ type Token interface {
Attributes() Attributes
}

//Attributes is the interface that wraps methods which dictate how to interact
//with a token's attributes. Getter functions return a boolean as second element
//which indicates that a value of the requested type exists at the given key path.
type Attributes interface {
Get(key string) (interface{}, bool)
}

// simpleToken is a very basic token type that can serve as the Token for many types of secure pipelines
type simpleToken struct {
tokenType string
Expand Down