Add RBAC functions for workflow for check&grant
This commit is contained in:
@@ -17,6 +17,7 @@ type (
|
||||
|
||||
const (
|
||||
nsSep = "::"
|
||||
cmpSep = ":"
|
||||
pathSep = "/"
|
||||
wildcard = "*"
|
||||
)
|
||||
@@ -34,6 +35,21 @@ func ResourceType(r string) string {
|
||||
}
|
||||
}
|
||||
|
||||
func ResourceComponent(r string) string {
|
||||
var (
|
||||
t = ResourceType(r)
|
||||
ns = strings.Index(t, nsSep)
|
||||
c = strings.LastIndex(t, cmpSep)
|
||||
)
|
||||
|
||||
// make sure that we have both namespace + component separators
|
||||
if c > ns+1 && ns > -1 {
|
||||
return t[:c]
|
||||
} else {
|
||||
return t
|
||||
}
|
||||
}
|
||||
|
||||
func matchResource(matcher, resource string) (m bool) {
|
||||
if matcher == resource {
|
||||
// if resources match make sure no wildcards are resent
|
||||
|
||||
@@ -29,6 +29,27 @@ func TestResourceType(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceComponent(t *testing.T) {
|
||||
var (
|
||||
tcc = []struct {
|
||||
in string
|
||||
exp string
|
||||
}{
|
||||
{"ns::cmp:r/1/2/3", "ns::cmp"},
|
||||
{"ns::cmp:r", "ns::cmp"},
|
||||
{"ns::cmp/", "ns::cmp"},
|
||||
{"ns::cmp", "ns::cmp"},
|
||||
{"cmp", "cmp"},
|
||||
}
|
||||
)
|
||||
|
||||
for _, tc := range tcc {
|
||||
t.Run(tc.in, func(t *testing.T) {
|
||||
require.Equal(t, tc.exp, ResourceComponent(tc.in))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceMatch(t *testing.T) {
|
||||
var (
|
||||
tcc = []struct {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -30,7 +29,6 @@ func TestRuleSetSort(t *testing.T) {
|
||||
|
||||
req.NotNil(rr)
|
||||
sort.Sort(rr)
|
||||
spew.Dump(rr)
|
||||
c = i()
|
||||
req.Equal(":::/1/2/3", rr[i()].Resource)
|
||||
req.Equal(":::/1/*/3", rr[i()].Resource)
|
||||
|
||||
Generated
+40
@@ -11,7 +11,9 @@ package automation
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
. "github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
)
|
||||
|
||||
@@ -178,6 +180,44 @@ func assignToQueueMessage(res *types.QueueMessage, k string, val interface{}) er
|
||||
return fmt.Errorf("unknown field '%s'", k)
|
||||
}
|
||||
|
||||
// RbacResource is an expression type, wrapper for rbac.Resource type
|
||||
type RbacResource struct{ value rbac.Resource }
|
||||
|
||||
// NewRbacResource creates new instance of RbacResource expression type
|
||||
func NewRbacResource(val interface{}) (*RbacResource, error) {
|
||||
if c, err := CastToRbacResource(val); err != nil {
|
||||
return nil, fmt.Errorf("unable to create RbacResource: %w", err)
|
||||
} else {
|
||||
return &RbacResource{value: c}, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Return underlying value on RbacResource
|
||||
func (t RbacResource) Get() interface{} { return t.value }
|
||||
|
||||
// Return underlying value on RbacResource
|
||||
func (t RbacResource) GetValue() rbac.Resource { return t.value }
|
||||
|
||||
// Return type name
|
||||
func (RbacResource) Type() string { return "RbacResource" }
|
||||
|
||||
// Convert value to rbac.Resource
|
||||
func (RbacResource) Cast(val interface{}) (TypedValue, error) {
|
||||
return NewRbacResource(val)
|
||||
}
|
||||
|
||||
// Assign new value to RbacResource
|
||||
//
|
||||
// value is first passed through CastToRbacResource
|
||||
func (t *RbacResource) Assign(val interface{}) error {
|
||||
if c, err := CastToRbacResource(val); err != nil {
|
||||
return err
|
||||
} else {
|
||||
t.value = c
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// RenderOptions is an expression type, wrapper for map[string]string type
|
||||
type RenderOptions struct{ value map[string]string }
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
@@ -152,3 +153,14 @@ func (doc renderedDocument) String() string {
|
||||
aux, _ := ioutil.ReadAll(doc.Document)
|
||||
return string(aux)
|
||||
}
|
||||
|
||||
func CastToRbacResource(val interface{}) (out rbac.Resource, err error) {
|
||||
switch val := expr.UntypedValue(val).(type) {
|
||||
case rbac.Resource:
|
||||
return val, nil
|
||||
case RbacResource:
|
||||
return val.value, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unable to cast type %T to %T", val, out)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package: automation
|
||||
imports:
|
||||
- github.com/cortezaproject/corteza-server/system/types
|
||||
- github.com/cortezaproject/corteza-server/pkg/rbac
|
||||
|
||||
types:
|
||||
Template:
|
||||
@@ -63,9 +64,12 @@ types:
|
||||
- { name: 'type', exprType: 'string', goType: 'string' }
|
||||
RenderOptions:
|
||||
as: 'map[string]string'
|
||||
|
||||
|
||||
QueueMessage:
|
||||
as: '*types.QueueMessage'
|
||||
struct:
|
||||
- { name: 'Queue', exprType: 'String', goType: 'string' }
|
||||
- { name: 'Payload', exprType: 'String', goType: '[]byte' }
|
||||
|
||||
RbacResource:
|
||||
as: 'rbac.Resource'
|
||||
|
||||
Generated
+372
@@ -0,0 +1,372 @@
|
||||
package automation
|
||||
|
||||
// This file is auto-generated.
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
//
|
||||
// Definitions file that controls how this file is generated:
|
||||
// system/automation/rbac_handler.yaml
|
||||
|
||||
import (
|
||||
"context"
|
||||
atypes "github.com/cortezaproject/corteza-server/automation/types"
|
||||
"github.com/cortezaproject/corteza-server/pkg/expr"
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
"github.com/cortezaproject/corteza-server/pkg/wfexec"
|
||||
"github.com/cortezaproject/corteza-server/system/types"
|
||||
)
|
||||
|
||||
var _ wfexec.ExecResponse
|
||||
|
||||
type (
|
||||
rbacHandlerRegistry interface {
|
||||
AddFunctions(ff ...*atypes.Function)
|
||||
Type(ref string) expr.Type
|
||||
}
|
||||
)
|
||||
|
||||
func (h rbacHandler) register() {
|
||||
h.reg.AddFunctions(
|
||||
h.Allow(),
|
||||
h.Deny(),
|
||||
h.Inherit(),
|
||||
h.Check(),
|
||||
)
|
||||
}
|
||||
|
||||
type (
|
||||
rbacAllowArgs struct {
|
||||
hasResource bool
|
||||
Resource rbac.Resource
|
||||
|
||||
hasRole bool
|
||||
Role interface{}
|
||||
roleID uint64
|
||||
roleHandle string
|
||||
roleRes *types.Role
|
||||
|
||||
hasOperation bool
|
||||
Operation string
|
||||
}
|
||||
)
|
||||
|
||||
func (a rbacAllowArgs) GetRole() (bool, uint64, string, *types.Role) {
|
||||
return a.hasRole, a.roleID, a.roleHandle, a.roleRes
|
||||
}
|
||||
|
||||
// Allow function RBAC: Allow operation on resource to a role
|
||||
//
|
||||
// expects implementation of allow function:
|
||||
// func (h rbacHandler) allow(ctx context.Context, args *rbacAllowArgs) (err error) {
|
||||
// return
|
||||
// }
|
||||
func (h rbacHandler) Allow() *atypes.Function {
|
||||
return &atypes.Function{
|
||||
Ref: "rbacAllow",
|
||||
Kind: "function",
|
||||
Labels: map[string]string{"users": "rbac"},
|
||||
Meta: &atypes.FunctionMeta{
|
||||
Short: "RBAC: Allow operation on resource to a role",
|
||||
},
|
||||
|
||||
Parameters: []*atypes.Param{
|
||||
{
|
||||
Name: "resource",
|
||||
Types: []string{"RbacResource"}, Required: true,
|
||||
},
|
||||
{
|
||||
Name: "role",
|
||||
Types: []string{"ID", "Handle", "Role"}, Required: true,
|
||||
},
|
||||
{
|
||||
Name: "operation",
|
||||
Types: []string{"String"}, Required: true,
|
||||
},
|
||||
},
|
||||
|
||||
Handler: func(ctx context.Context, in *expr.Vars) (out *expr.Vars, err error) {
|
||||
var (
|
||||
args = &rbacAllowArgs{
|
||||
hasResource: in.Has("resource"),
|
||||
hasRole: in.Has("role"),
|
||||
hasOperation: in.Has("operation"),
|
||||
}
|
||||
)
|
||||
|
||||
if err = in.Decode(args); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Converting Role argument
|
||||
if args.hasRole {
|
||||
aux := expr.Must(expr.Select(in, "role"))
|
||||
switch aux.Type() {
|
||||
case h.reg.Type("ID").Type():
|
||||
args.roleID = aux.Get().(uint64)
|
||||
case h.reg.Type("Handle").Type():
|
||||
args.roleHandle = aux.Get().(string)
|
||||
case h.reg.Type("Role").Type():
|
||||
args.roleRes = aux.Get().(*types.Role)
|
||||
}
|
||||
}
|
||||
|
||||
return out, h.allow(ctx, args)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
rbacDenyArgs struct {
|
||||
hasResource bool
|
||||
Resource rbac.Resource
|
||||
|
||||
hasRole bool
|
||||
Role interface{}
|
||||
roleID uint64
|
||||
roleHandle string
|
||||
roleRes *types.Role
|
||||
|
||||
hasOperation bool
|
||||
Operation string
|
||||
}
|
||||
)
|
||||
|
||||
func (a rbacDenyArgs) GetRole() (bool, uint64, string, *types.Role) {
|
||||
return a.hasRole, a.roleID, a.roleHandle, a.roleRes
|
||||
}
|
||||
|
||||
// Deny function RBAC: Deny operation on resource to a role
|
||||
//
|
||||
// expects implementation of deny function:
|
||||
// func (h rbacHandler) deny(ctx context.Context, args *rbacDenyArgs) (err error) {
|
||||
// return
|
||||
// }
|
||||
func (h rbacHandler) Deny() *atypes.Function {
|
||||
return &atypes.Function{
|
||||
Ref: "rbacDeny",
|
||||
Kind: "function",
|
||||
Labels: map[string]string{"users": "rbac"},
|
||||
Meta: &atypes.FunctionMeta{
|
||||
Short: "RBAC: Deny operation on resource to a role",
|
||||
},
|
||||
|
||||
Parameters: []*atypes.Param{
|
||||
{
|
||||
Name: "resource",
|
||||
Types: []string{"RbacResource"}, Required: true,
|
||||
},
|
||||
{
|
||||
Name: "role",
|
||||
Types: []string{"ID", "Handle", "Role"}, Required: true,
|
||||
},
|
||||
{
|
||||
Name: "operation",
|
||||
Types: []string{"String"}, Required: true,
|
||||
},
|
||||
},
|
||||
|
||||
Handler: func(ctx context.Context, in *expr.Vars) (out *expr.Vars, err error) {
|
||||
var (
|
||||
args = &rbacDenyArgs{
|
||||
hasResource: in.Has("resource"),
|
||||
hasRole: in.Has("role"),
|
||||
hasOperation: in.Has("operation"),
|
||||
}
|
||||
)
|
||||
|
||||
if err = in.Decode(args); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Converting Role argument
|
||||
if args.hasRole {
|
||||
aux := expr.Must(expr.Select(in, "role"))
|
||||
switch aux.Type() {
|
||||
case h.reg.Type("ID").Type():
|
||||
args.roleID = aux.Get().(uint64)
|
||||
case h.reg.Type("Handle").Type():
|
||||
args.roleHandle = aux.Get().(string)
|
||||
case h.reg.Type("Role").Type():
|
||||
args.roleRes = aux.Get().(*types.Role)
|
||||
}
|
||||
}
|
||||
|
||||
return out, h.deny(ctx, args)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
rbacInheritArgs struct {
|
||||
hasResource bool
|
||||
Resource rbac.Resource
|
||||
|
||||
hasRole bool
|
||||
Role interface{}
|
||||
roleID uint64
|
||||
roleHandle string
|
||||
roleRes *types.Role
|
||||
|
||||
hasOperation bool
|
||||
Operation string
|
||||
}
|
||||
)
|
||||
|
||||
func (a rbacInheritArgs) GetRole() (bool, uint64, string, *types.Role) {
|
||||
return a.hasRole, a.roleID, a.roleHandle, a.roleRes
|
||||
}
|
||||
|
||||
// Inherit function RBAC: Remove allow/deny operation of a role from resource
|
||||
//
|
||||
// expects implementation of inherit function:
|
||||
// func (h rbacHandler) inherit(ctx context.Context, args *rbacInheritArgs) (err error) {
|
||||
// return
|
||||
// }
|
||||
func (h rbacHandler) Inherit() *atypes.Function {
|
||||
return &atypes.Function{
|
||||
Ref: "rbacInherit",
|
||||
Kind: "function",
|
||||
Labels: map[string]string{"users": "rbac"},
|
||||
Meta: &atypes.FunctionMeta{
|
||||
Short: "RBAC: Remove allow/deny operation of a role from resource",
|
||||
},
|
||||
|
||||
Parameters: []*atypes.Param{
|
||||
{
|
||||
Name: "resource",
|
||||
Types: []string{"RbacResource"}, Required: true,
|
||||
},
|
||||
{
|
||||
Name: "role",
|
||||
Types: []string{"ID", "Handle", "Role"}, Required: true,
|
||||
},
|
||||
{
|
||||
Name: "operation",
|
||||
Types: []string{"String"}, Required: true,
|
||||
},
|
||||
},
|
||||
|
||||
Handler: func(ctx context.Context, in *expr.Vars) (out *expr.Vars, err error) {
|
||||
var (
|
||||
args = &rbacInheritArgs{
|
||||
hasResource: in.Has("resource"),
|
||||
hasRole: in.Has("role"),
|
||||
hasOperation: in.Has("operation"),
|
||||
}
|
||||
)
|
||||
|
||||
if err = in.Decode(args); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Converting Role argument
|
||||
if args.hasRole {
|
||||
aux := expr.Must(expr.Select(in, "role"))
|
||||
switch aux.Type() {
|
||||
case h.reg.Type("ID").Type():
|
||||
args.roleID = aux.Get().(uint64)
|
||||
case h.reg.Type("Handle").Type():
|
||||
args.roleHandle = aux.Get().(string)
|
||||
case h.reg.Type("Role").Type():
|
||||
args.roleRes = aux.Get().(*types.Role)
|
||||
}
|
||||
}
|
||||
|
||||
return out, h.inherit(ctx, args)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
rbacCheckArgs struct {
|
||||
hasResource bool
|
||||
Resource rbac.Resource
|
||||
|
||||
hasOperation bool
|
||||
Operation string
|
||||
|
||||
hasUser bool
|
||||
User *types.User
|
||||
}
|
||||
|
||||
rbacCheckResults struct {
|
||||
Can bool
|
||||
}
|
||||
)
|
||||
|
||||
// Check function RBAC: Can user perform an operation on a resource
|
||||
//
|
||||
// expects implementation of check function:
|
||||
// func (h rbacHandler) check(ctx context.Context, args *rbacCheckArgs) (results *rbacCheckResults, err error) {
|
||||
// return
|
||||
// }
|
||||
func (h rbacHandler) Check() *atypes.Function {
|
||||
return &atypes.Function{
|
||||
Ref: "rbacCheck",
|
||||
Kind: "function",
|
||||
Labels: map[string]string{"users": "rbac"},
|
||||
Meta: &atypes.FunctionMeta{
|
||||
Short: "RBAC: Can user perform an operation on a resource",
|
||||
},
|
||||
|
||||
Parameters: []*atypes.Param{
|
||||
{
|
||||
Name: "resource",
|
||||
Types: []string{"RbacResource"}, Required: true,
|
||||
},
|
||||
{
|
||||
Name: "operation",
|
||||
Types: []string{"String"}, Required: true,
|
||||
},
|
||||
{
|
||||
Name: "user",
|
||||
Types: []string{"User"},
|
||||
},
|
||||
},
|
||||
|
||||
Results: []*atypes.Param{
|
||||
|
||||
{
|
||||
Name: "can",
|
||||
Types: []string{"Boolean"},
|
||||
},
|
||||
},
|
||||
|
||||
Handler: func(ctx context.Context, in *expr.Vars) (out *expr.Vars, err error) {
|
||||
var (
|
||||
args = &rbacCheckArgs{
|
||||
hasResource: in.Has("resource"),
|
||||
hasOperation: in.Has("operation"),
|
||||
hasUser: in.Has("user"),
|
||||
}
|
||||
)
|
||||
|
||||
if err = in.Decode(args); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var results *rbacCheckResults
|
||||
if results, err = h.check(ctx, args); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
out = &expr.Vars{}
|
||||
|
||||
{
|
||||
// converting results.Can (bool) to Boolean
|
||||
var (
|
||||
tval expr.TypedValue
|
||||
)
|
||||
|
||||
if tval, err = h.reg.Type("Boolean").Cast(results.Can); err != nil {
|
||||
return
|
||||
} else if err = expr.Assign(out, "can", tval); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package automation
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/cortezaproject/corteza-server/pkg/rbac"
|
||||
)
|
||||
|
||||
type (
|
||||
rbacService interface {
|
||||
Can(ses rbac.Session, op string, res rbac.Resource) bool
|
||||
Grant(ctx context.Context, rules ...*rbac.Rule) (err error)
|
||||
}
|
||||
|
||||
rbacHandler struct {
|
||||
reg rbacHandlerRegistry
|
||||
svc rbacService
|
||||
}
|
||||
|
||||
auxResource struct{ res string }
|
||||
)
|
||||
|
||||
var _ rbac.Resource = &auxResource{}
|
||||
|
||||
func (r auxResource) RbacResource() string {
|
||||
return r.res
|
||||
}
|
||||
|
||||
func RbacHandler(reg rbacHandlerRegistry, svc rbacService) *rbacHandler {
|
||||
h := &rbacHandler{
|
||||
reg: reg,
|
||||
svc: svc,
|
||||
}
|
||||
|
||||
h.register()
|
||||
return h
|
||||
}
|
||||
|
||||
func (h rbacHandler) allow(ctx context.Context, args *rbacAllowArgs) (err error) {
|
||||
return h.grant(ctx, rbac.AllowRule(args.roleID, args.Operation, args.Resource.RbacResource()))
|
||||
}
|
||||
|
||||
func (h rbacHandler) deny(ctx context.Context, args *rbacDenyArgs) (err error) {
|
||||
return h.grant(ctx, rbac.DenyRule(args.roleID, args.Operation, args.Resource.RbacResource()))
|
||||
}
|
||||
|
||||
func (h rbacHandler) inherit(ctx context.Context, args *rbacInheritArgs) (err error) {
|
||||
return h.grant(ctx, rbac.InheritRule(args.roleID, args.Operation, args.Resource.RbacResource()))
|
||||
}
|
||||
|
||||
// verifies grant op (granter needs to be allowed to grant on the component
|
||||
|
||||
func (h rbacHandler) grant(ctx context.Context, r *rbac.Rule) (err error) {
|
||||
// we can safely create a fake component resource since there are
|
||||
// no extra metadata hidden under it,
|
||||
cmpRes := &auxResource{rbac.ResourceComponent(r.Resource)}
|
||||
|
||||
if !h.svc.Can(rbac.ContextToSession(ctx), "grant", cmpRes) {
|
||||
return fmt.Errorf("not allowed to grant %s", r.String())
|
||||
}
|
||||
|
||||
return h.svc.Grant(ctx, r)
|
||||
}
|
||||
|
||||
func (h rbacHandler) check(ctx context.Context, args *rbacCheckArgs) (b *rbacCheckResults, err error) {
|
||||
b = &rbacCheckResults{}
|
||||
|
||||
b.Can = h.svc.Can(rbac.ContextToSession(ctx), args.Operation, args.Resource)
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
imports:
|
||||
- github.com/cortezaproject/corteza-server/system/types
|
||||
- github.com/cortezaproject/corteza-server/pkg/rbac
|
||||
|
||||
params:
|
||||
manageParams: &manageParams
|
||||
resource:
|
||||
required: true
|
||||
types:
|
||||
# Note that we can not accept string here because
|
||||
# we need whole resource with all the info loaded
|
||||
- { wf: RbacResource }
|
||||
role:
|
||||
required: true
|
||||
types:
|
||||
- { wf: ID }
|
||||
- { wf: Handle }
|
||||
- { wf: Role, suffix: res }
|
||||
operation:
|
||||
required: true
|
||||
types:
|
||||
- { wf: String }
|
||||
|
||||
labels: &labels
|
||||
users: "rbac"
|
||||
|
||||
functions:
|
||||
allow:
|
||||
meta:
|
||||
short: 'RBAC: Allow operation on resource to a role'
|
||||
labels:
|
||||
<<: *labels
|
||||
params: *manageParams
|
||||
|
||||
deny:
|
||||
meta:
|
||||
short: 'RBAC: Deny operation on resource to a role'
|
||||
labels:
|
||||
<<: *labels
|
||||
params: *manageParams
|
||||
|
||||
inherit:
|
||||
meta:
|
||||
short: 'RBAC: Remove allow/deny operation of a role from resource'
|
||||
labels:
|
||||
<<: *labels
|
||||
params: *manageParams
|
||||
|
||||
check:
|
||||
meta:
|
||||
short: 'RBAC: Can user perform an operation on a resource'
|
||||
labels:
|
||||
<<: *labels
|
||||
params:
|
||||
resource:
|
||||
required: true
|
||||
types: [ { wf: RbacResource } ]
|
||||
operation:
|
||||
required: true
|
||||
types: [ { wf: String } ]
|
||||
user:
|
||||
types: [ { wf: User } ]
|
||||
results:
|
||||
can: { wf: Boolean }
|
||||
@@ -181,6 +181,7 @@ func Initialize(ctx context.Context, log *zap.Logger, s store.Storer, ws websock
|
||||
automation.Template{},
|
||||
automation.RenderOptions{},
|
||||
automation.RenderedDocument{},
|
||||
automation.RbacResource{},
|
||||
)
|
||||
|
||||
automation.UsersHandler(
|
||||
@@ -198,6 +199,11 @@ func Initialize(ctx context.Context, log *zap.Logger, s store.Storer, ws websock
|
||||
DefaultRole,
|
||||
)
|
||||
|
||||
automation.RbacHandler(
|
||||
automationService.Registry(),
|
||||
rbac.Global(),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user