mirror of https://github.com/hashicorp/boundary
parent
8643d8e6c6
commit
3f4a723541
@ -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…
Reference in new issue