feat(action): Add registrar for valid actions by resource

pull/4093/head
Timothy Messier 3 years ago
parent 8643d8e6c6
commit 3f4a723541
No known key found for this signature in database
GPG Key ID: EFD2F184F7600572

@ -0,0 +1,73 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package action
import (
"fmt"
"sync"
"github.com/hashicorp/boundary/internal/types/resource"
)
type resourceActionSets struct {
individual ActionSet
collection ActionSet
valid ActionSet
}
type byResource struct {
mu sync.RWMutex
m map[resource.Type]*resourceActionSets
}
func (b *byResource) add(r resource.Type, individual ActionSet, collection ActionSet) error {
b.mu.Lock()
defer b.mu.Unlock()
if b.m == nil {
b.m = make(map[resource.Type]*resourceActionSets)
}
_, ok := b.m[r]
if ok {
return fmt.Errorf("%s already registered", r)
}
b.m[r] = &resourceActionSets{
individual: individual,
collection: collection,
valid: Union(individual, collection),
}
return nil
}
func (b *byResource) get(r resource.Type) (*resourceActionSets, error) {
b.mu.RLock()
defer b.mu.RUnlock()
a, ok := b.m[r]
if !ok {
return nil, fmt.Errorf("resource not found: %s", r)
}
return a, nil
}
var byResourceRegistrar = &byResource{}
// RegisterResource registers ActionSets for r. If RegisterResource is called
// twice with the same resource, it panics.
func RegisterResource(r resource.Type, individual ActionSet, collection ActionSet) {
if err := byResourceRegistrar.add(r, individual, collection); err != nil {
panic(err)
}
}
// ActionSetForResource returns the ActionSet registered for r
// or an error if r has not been registered.
func ActionSetForResource(r resource.Type) (ActionSet, error) {
a, err := byResourceRegistrar.get(r)
if err != nil {
return nil, err
}
return a.valid, nil
}

@ -0,0 +1,71 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package action_test
import (
"errors"
"testing"
"github.com/hashicorp/boundary/internal/types/action"
"github.com/hashicorp/boundary/internal/types/resource"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRegisterResource(t *testing.T) {
t.Run("Pancis", func(t *testing.T) {
// Ensure the resource is not registered yet
_, err := action.ActionSetForResource(resource.Session)
require.EqualError(t, err, "resource not found: session")
// Now register the resource
action.RegisterResource(resource.Session, action.NewActionSet(action.Read, action.Create), action.NewActionSet(action.List))
got, err := action.ActionSetForResource(resource.Session)
require.NoError(t, err)
assert.Equal(t, action.NewActionSet(action.Read, action.Create, action.List), got)
// Attempting to register the same resource again should panic
require.Panics(
t,
func() {
action.RegisterResource(resource.Session, action.NewActionSet(action.Update, action.Read, action.Create), action.NewActionSet(action.List))
},
)
})
// Run these after the Pancis test rely on resource.Session already being registered.
t.Run("ActionSetForResource", func(t *testing.T) {
cases := []struct {
name string
res resource.Type
want action.ActionSet
wantErr error
}{
{
"NotRegistered",
resource.Target,
nil,
errors.New("resource not found: target"),
},
{
"Registered",
resource.Session,
action.NewActionSet(action.Read, action.Create, action.List),
nil,
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got, err := action.ActionSetForResource(tc.res)
if tc.wantErr != nil {
require.EqualError(t, err, tc.wantErr.Error())
return
}
require.NoError(t, err)
assert.Equal(t, tc.want, got)
})
}
})
}
Loading…
Cancel
Save