Added RequirementOfPolicy and thread extension child loading

graph-rework-2
noah metz 2023-07-26 15:40:33 -06:00
parent d2f3daf5a6
commit 89c8fba39b
5 changed files with 92 additions and 30 deletions

@ -11,15 +11,15 @@ import (
) )
func TestGQLDBLoad(t * testing.T) { func TestGQLDBLoad(t * testing.T) {
ctx := logTestContext(t, []string{"test", "db", "policy", "signal"}) ctx := logTestContext(t, []string{"test", "db"})
TestUserNodeType := NodeType("TEST_USER") TestUserNodeType := NodeType("TEST_USER")
err := ctx.RegisterNodeType(TestUserNodeType, []ExtType{ACLExtType, ACLPolicyExtType}) err := ctx.RegisterNodeType(TestUserNodeType, []ExtType{ACLExtType, ACLPolicyExtType})
fatalErr(t, err) fatalErr(t, err)
u1 := NewNode(ctx, RandID(), TestUserNodeType) u1 := NewNode(ctx, RandID(), TestUserNodeType)
u1_policy := NewPerNodePolicy(map[NodeID][]string{ u1_policy := NewPerNodePolicy(NodeActions{
u1.ID: []string{"users.write", "children.write", "parent.write", "dependencies.write", "requirements.write"}, u1.ID: Actions{"users.write", "children.write", "parent.write", "dependencies.write", "requirements.write"},
}) })
u1.Extensions[ACLExtType] = NewACLExt(nil) u1.Extensions[ACLExtType] = NewACLExt(nil)
u1.Extensions[ACLPolicyExtType] = NewACLPolicyExt(map[PolicyType]Policy{ u1.Extensions[ACLPolicyExtType] = NewACLPolicyExt(map[PolicyType]Policy{
@ -33,8 +33,8 @@ func TestGQLDBLoad(t * testing.T) {
fatalErr(t, err) fatalErr(t, err)
l1 := NewNode(ctx, RandID(), ListenerNodeType) l1 := NewNode(ctx, RandID(), ListenerNodeType)
l1_policy := NewRequirementOfPolicy(map[NodeID][]string{ l1_policy := NewRequirementOfPolicy(NodeActions{
l1.ID: []string{"signal.status"}, l1.ID: Actions{"signal.status"},
}) })
l1.Extensions[ACLExtType] = NewACLExt(NodeList(u1)) l1.Extensions[ACLExtType] = NewACLExt(NodeList(u1))
@ -52,8 +52,8 @@ func TestGQLDBLoad(t * testing.T) {
fatalErr(t, err) fatalErr(t, err)
t1 := NewNode(ctx, RandID(), TestThreadNodeType) t1 := NewNode(ctx, RandID(), TestThreadNodeType)
t1_policy := NewParentOfPolicy(map[NodeID][]string{ t1_policy := NewParentOfPolicy(NodeActions{
t1.ID: []string{"signal.abort", "state.write"}, t1.ID: Actions{"signal.abort", "state.write"},
}) })
t1.Extensions[ACLExtType] = NewACLExt(NodeList(u1)) t1.Extensions[ACLExtType] = NewACLExt(NodeList(u1))
t1.Extensions[ACLPolicyExtType] = NewACLPolicyExt(map[PolicyType]Policy{ t1.Extensions[ACLPolicyExtType] = NewACLPolicyExt(map[PolicyType]Policy{
@ -73,8 +73,8 @@ func TestGQLDBLoad(t * testing.T) {
fatalErr(t, err) fatalErr(t, err)
gql := NewNode(ctx, RandID(), TestGQLNodeType) gql := NewNode(ctx, RandID(), TestGQLNodeType)
gql_policy := NewChildOfPolicy(map[NodeID][]string{ gql_policy := NewChildOfPolicy(NodeActions{
gql.ID: []string{"signal.status"}, gql.ID: Actions{"signal.status"},
}) })
gql.Extensions[ACLExtType] = NewACLExt(NodeList(u1)) gql.Extensions[ACLExtType] = NewACLExt(NodeList(u1))
gql.Extensions[ACLPolicyExtType] = NewACLPolicyExt(map[PolicyType]Policy{ gql.Extensions[ACLPolicyExtType] = NewACLPolicyExt(map[PolicyType]Policy{

@ -28,11 +28,11 @@ func LoadListenerExt(ctx *Context, data []byte) (Extension, error) {
} }
const ListenerExtType = ExtType("LISTENER") const ListenerExtType = ExtType("LISTENER")
func (listener ListenerExt) Type() ExtType { func (listener *ListenerExt) Type() ExtType {
return ListenerExtType return ListenerExtType
} }
func (ext ListenerExt) Process(context *StateContext, node *Node, signal Signal) error { func (ext *ListenerExt) Process(context *StateContext, node *Node, signal Signal) error {
select { select {
case ext.Chan <- signal: case ext.Chan <- signal:
default: default:
@ -41,7 +41,7 @@ func (ext ListenerExt) Process(context *StateContext, node *Node, signal Signal)
return nil return nil
} }
func (ext ListenerExt) Serialize() ([]byte, error) { func (ext *ListenerExt) Serialize() ([]byte, error) {
return json.MarshalIndent(ext.Buffer, "", " ") return json.MarshalIndent(ext.Buffer, "", " ")
} }
@ -101,6 +101,8 @@ func LoadLockableExt(ctx *Context, data []byte) (Extension, error) {
return nil, err return nil, err
} }
ctx.Log.Logf("db", "DB_LOADING_LOCKABLE_EXT_JSON: %+v", j)
owner, err := RestoreNode(ctx, j.Owner) owner, err := RestoreNode(ctx, j.Owner)
if err != nil { if err != nil {
return nil, err return nil, err
@ -516,6 +518,9 @@ func SaveNode(node *Node) string {
} }
func RestoreNode(ctx *Context, id_str string) (*Node, error) { func RestoreNode(ctx *Context, id_str string) (*Node, error) {
if id_str == "" {
return nil, nil
}
id, err := ParseID(id_str) id, err := ParseID(id_str)
if err != nil { if err != nil {
return nil, err return nil, err
@ -540,20 +545,23 @@ func RestoreNodeMap(ctx *Context, ids map[string]string) (NodeMap, error) {
return nil, err return nil, err
} }
id_2, err := ParseID(id_str_2) node_1, err := LoadNode(ctx, id_1)
if err != nil { if err != nil {
return nil, err return nil, err
} }
node_1, err := LoadNode(ctx, id_1)
var node_2 *Node = nil
if id_str_2 != "" {
id_2, err := ParseID(id_str_2)
if err != nil { if err != nil {
return nil, err return nil, err
} }
node_2, err = LoadNode(ctx, id_2)
node_2, err := LoadNode(ctx, id_2)
if err != nil { if err != nil {
return nil, err return nil, err
} }
}
nodes[node_1.ID] = node_2 nodes[node_1.ID] = node_2
} }

@ -417,13 +417,14 @@ func LoadNode(ctx * Context, id NodeID) (*Node, error) {
if known == false { if known == false {
return nil, fmt.Errorf("%s tried to load extension 0x%x, which is not a known extension type", id, type_hash) return nil, fmt.Errorf("%s tried to load extension 0x%x, which is not a known extension type", id, type_hash)
} }
ctx.Log.Logf("db", "DB_EXTENSION_LOADING: %s/%s", id, def.Type)
extension, err := def.Load(ctx, ext_db.Data) extension, err := def.Load(ctx, ext_db.Data)
if err != nil { if err != nil {
return nil, err return nil, err
} }
node.Extensions[def.Type] = extension node.Extensions[def.Type] = extension
found_extensions = append(found_extensions, def.Type) found_extensions = append(found_extensions, def.Type)
ctx.Log.Logf("db", "DB_EXTENSION_LOADED: %s - 0x%x - %+v", id, type_hash, def.Type) ctx.Log.Logf("db", "DB_EXTENSION_LOADED: %s/%s - %+v", id, def.Type, extension)
} }
missing_extensions := []ExtType{} missing_extensions := []ExtType{}

@ -24,6 +24,27 @@ func NewRequirementOfPolicy(nodes NodeActions) RequirementOfPolicy {
} }
} }
// Check if any of principals dependencies are in the policy
func (policy *RequirementOfPolicy) Allows(context *StateContext, principal *Node, action string, node *Node) bool {
lockable_ext, err := GetExt[*LockableExt](principal)
if err != nil {
return false
}
for dep_id, _ := range(lockable_ext.Dependencies) {
for node_id, actions := range(policy.NodeActions) {
if node_id == dep_id {
if actions.Allows(action) == true {
return true
}
break
}
}
}
return false
}
const ChildOfPolicyType = PolicyType("CHILD_OF") const ChildOfPolicyType = PolicyType("CHILD_OF")
type ChildOfPolicy struct { type ChildOfPolicy struct {
PerNodePolicy PerNodePolicy
@ -55,7 +76,18 @@ func (policy *ChildOfPolicy) Allows(context *StateContext, principal *Node, acti
return false return false
} }
type NodeActions map[NodeID][]string type Actions []string
func (actions Actions) Allows(action string) bool {
for _, a := range(actions) {
if a == action {
return true
}
}
return false
}
type NodeActions map[NodeID]Actions
func PerNodePolicyLoad(init_fn func(NodeActions)(Policy, error)) func(*Context, []byte)(Policy, error) { func PerNodePolicyLoad(init_fn func(NodeActions)(Policy, error)) func(*Context, []byte)(Policy, error) {
return func(ctx *Context, data []byte)(Policy, error){ return func(ctx *Context, data []byte)(Policy, error){
@ -84,7 +116,7 @@ func PerNodePolicyLoad(init_fn func(NodeActions)(Policy, error)) func(*Context,
} }
} }
func NewChildOfPolicy(node_actions map[NodeID][]string) ChildOfPolicy { func NewChildOfPolicy(node_actions NodeActions) ChildOfPolicy {
return ChildOfPolicy{ return ChildOfPolicy{
PerNodePolicy: NewPerNodePolicy(node_actions), PerNodePolicy: NewPerNodePolicy(node_actions),
} }
@ -121,7 +153,7 @@ func (policy *ParentOfPolicy) Allows(context *StateContext, principal *Node, act
return false return false
} }
func NewParentOfPolicy(node_actions map[NodeID][]string) ParentOfPolicy { func NewParentOfPolicy(node_actions NodeActions) ParentOfPolicy {
return ParentOfPolicy{ return ParentOfPolicy{
PerNodePolicy: NewPerNodePolicy(node_actions), PerNodePolicy: NewPerNodePolicy(node_actions),
} }
@ -129,7 +161,7 @@ func NewParentOfPolicy(node_actions map[NodeID][]string) ParentOfPolicy {
func NewPerNodePolicy(node_actions NodeActions) PerNodePolicy { func NewPerNodePolicy(node_actions NodeActions) PerNodePolicy {
if node_actions == nil { if node_actions == nil {
node_actions = map[NodeID][]string{} node_actions = NodeActions{}
} }
return PerNodePolicy{ return PerNodePolicy{
@ -138,7 +170,7 @@ func NewPerNodePolicy(node_actions NodeActions) PerNodePolicy {
} }
type PerNodePolicy struct { type PerNodePolicy struct {
NodeActions map[NodeID][]string NodeActions NodeActions
} }
type PerNodePolicyJSON struct { type PerNodePolicyJSON struct {
@ -329,7 +361,7 @@ func LoadACLPolicyExt(ctx *Context, data []byte) (Extension, error) {
} }
policies := map[PolicyType]Policy{} policies := map[PolicyType]Policy{}
acl_ctx := ctx.ExtByType(ACLPolicyExtType).Data.(ACLPolicyExtContext) acl_ctx := ctx.ExtByType(ACLPolicyExtType).Data.(*ACLPolicyExtContext)
for name, ser := range(j.Policies) { for name, ser := range(j.Policies) {
policy_def, exists := acl_ctx.Types[PolicyType(name)] policy_def, exists := acl_ctx.Types[PolicyType(name)]
if exists == false { if exists == false {

@ -189,6 +189,7 @@ func NewThreadExt(ctx*Context, thread_type ThreadType, parent *Node, children ma
next_action, timeout_chan := SoonestAction(action_queue) next_action, timeout_chan := SoonestAction(action_queue)
return &ThreadExt{ return &ThreadExt{
ThreadType: thread_type,
Actions: type_info.Actions, Actions: type_info.Actions,
Handlers: type_info.Handlers, Handlers: type_info.Handlers,
SignalChan: make(chan Signal, THREAD_BUFFER_SIZE), SignalChan: make(chan Signal, THREAD_BUFFER_SIZE),
@ -209,23 +210,43 @@ func LoadThreadExt(ctx *Context, data []byte) (Extension, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
ctx.Log.Logf("db", "DB_LOAD_THREAD_EXT_JSON: %+v", j)
parent, err := RestoreNode(ctx, j.Parent) parent, err := RestoreNode(ctx, j.Parent)
if err != nil { if err != nil {
return nil, err return nil, err
} }
thread_ctx, err := GetCtx[*ThreadExt, *ThreadExtContext](ctx)
if err != nil {
return nil, err
}
children := map[NodeID]ChildInfo{} children := map[NodeID]ChildInfo{}
for id_str, _ := range(j.Children) { for id_str, infos := range(j.Children) {
child_node, err := RestoreNode(ctx, id_str) child_node, err := RestoreNode(ctx, id_str)
if err != nil { if err != nil {
return nil, err return nil, err
} }
//TODO: Restore child info based off context child_infos := map[InfoType]Info{}
for info_type_str, info_data := range(infos) {
info_type := InfoType(info_type_str)
info_load, exists := thread_ctx.Loads[info_type]
if exists == false {
return nil, fmt.Errorf("%s is not a known InfoType in ThreacExrContxt", info_type)
}
info, err := info_load(info_data)
if err != nil {
return nil, err
}
child_infos[info_type] = info
}
children[child_node.ID] = ChildInfo{ children[child_node.ID] = ChildInfo{
Child: child_node, Child: child_node,
Infos: map[InfoType]Info{}, Infos: child_infos,
} }
} }