From 89c8fba39b0b607629505ca47620f6411a013677 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Wed, 26 Jul 2023 15:40:33 -0600 Subject: [PATCH] Added RequirementOfPolicy and thread extension child loading --- gql_test.go | 18 +++++++++--------- lockable.go | 30 +++++++++++++++++++----------- node.go | 3 ++- policy.go | 44 ++++++++++++++++++++++++++++++++++++++------ thread.go | 27 ++++++++++++++++++++++++--- 5 files changed, 92 insertions(+), 30 deletions(-) diff --git a/gql_test.go b/gql_test.go index 49fcc16..266ba5d 100644 --- a/gql_test.go +++ b/gql_test.go @@ -11,15 +11,15 @@ import ( ) func TestGQLDBLoad(t * testing.T) { - ctx := logTestContext(t, []string{"test", "db", "policy", "signal"}) + ctx := logTestContext(t, []string{"test", "db"}) TestUserNodeType := NodeType("TEST_USER") err := ctx.RegisterNodeType(TestUserNodeType, []ExtType{ACLExtType, ACLPolicyExtType}) fatalErr(t, err) u1 := NewNode(ctx, RandID(), TestUserNodeType) - u1_policy := NewPerNodePolicy(map[NodeID][]string{ - u1.ID: []string{"users.write", "children.write", "parent.write", "dependencies.write", "requirements.write"}, + u1_policy := NewPerNodePolicy(NodeActions{ + u1.ID: Actions{"users.write", "children.write", "parent.write", "dependencies.write", "requirements.write"}, }) u1.Extensions[ACLExtType] = NewACLExt(nil) u1.Extensions[ACLPolicyExtType] = NewACLPolicyExt(map[PolicyType]Policy{ @@ -33,8 +33,8 @@ func TestGQLDBLoad(t * testing.T) { fatalErr(t, err) l1 := NewNode(ctx, RandID(), ListenerNodeType) - l1_policy := NewRequirementOfPolicy(map[NodeID][]string{ - l1.ID: []string{"signal.status"}, + l1_policy := NewRequirementOfPolicy(NodeActions{ + l1.ID: Actions{"signal.status"}, }) l1.Extensions[ACLExtType] = NewACLExt(NodeList(u1)) @@ -52,8 +52,8 @@ func TestGQLDBLoad(t * testing.T) { fatalErr(t, err) t1 := NewNode(ctx, RandID(), TestThreadNodeType) - t1_policy := NewParentOfPolicy(map[NodeID][]string{ - t1.ID: []string{"signal.abort", "state.write"}, + t1_policy := NewParentOfPolicy(NodeActions{ + t1.ID: Actions{"signal.abort", "state.write"}, }) t1.Extensions[ACLExtType] = NewACLExt(NodeList(u1)) t1.Extensions[ACLPolicyExtType] = NewACLPolicyExt(map[PolicyType]Policy{ @@ -73,8 +73,8 @@ func TestGQLDBLoad(t * testing.T) { fatalErr(t, err) gql := NewNode(ctx, RandID(), TestGQLNodeType) - gql_policy := NewChildOfPolicy(map[NodeID][]string{ - gql.ID: []string{"signal.status"}, + gql_policy := NewChildOfPolicy(NodeActions{ + gql.ID: Actions{"signal.status"}, }) gql.Extensions[ACLExtType] = NewACLExt(NodeList(u1)) gql.Extensions[ACLPolicyExtType] = NewACLPolicyExt(map[PolicyType]Policy{ diff --git a/lockable.go b/lockable.go index dd3a24a..7c1be78 100644 --- a/lockable.go +++ b/lockable.go @@ -28,11 +28,11 @@ func LoadListenerExt(ctx *Context, data []byte) (Extension, error) { } const ListenerExtType = ExtType("LISTENER") -func (listener ListenerExt) Type() ExtType { +func (listener *ListenerExt) Type() ExtType { 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 { case ext.Chan <- signal: default: @@ -41,7 +41,7 @@ func (ext ListenerExt) Process(context *StateContext, node *Node, signal Signal) return nil } -func (ext ListenerExt) Serialize() ([]byte, error) { +func (ext *ListenerExt) Serialize() ([]byte, error) { return json.MarshalIndent(ext.Buffer, "", " ") } @@ -101,6 +101,8 @@ func LoadLockableExt(ctx *Context, data []byte) (Extension, error) { return nil, err } + ctx.Log.Logf("db", "DB_LOADING_LOCKABLE_EXT_JSON: %+v", j) + owner, err := RestoreNode(ctx, j.Owner) if err != nil { return nil, err @@ -516,6 +518,9 @@ func SaveNode(node *Node) string { } func RestoreNode(ctx *Context, id_str string) (*Node, error) { + if id_str == "" { + return nil, nil + } id, err := ParseID(id_str) if err != nil { return nil, err @@ -540,19 +545,22 @@ func RestoreNodeMap(ctx *Context, ids map[string]string) (NodeMap, error) { return nil, err } - id_2, err := ParseID(id_str_2) - if err != nil { - return nil, err - } - node_1, err := LoadNode(ctx, id_1) if err != nil { return nil, err } - node_2, err := LoadNode(ctx, id_2) - if err != nil { - return nil, err + + var node_2 *Node = nil + if id_str_2 != "" { + id_2, err := ParseID(id_str_2) + if err != nil { + return nil, err + } + node_2, err = LoadNode(ctx, id_2) + if err != nil { + return nil, err + } } nodes[node_1.ID] = node_2 diff --git a/node.go b/node.go index a459f88..29786b3 100644 --- a/node.go +++ b/node.go @@ -417,13 +417,14 @@ func LoadNode(ctx * Context, id NodeID) (*Node, error) { if known == false { 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) if err != nil { return nil, err } node.Extensions[def.Type] = extension 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{} diff --git a/policy.go b/policy.go index 3547947..afe50e7 100644 --- a/policy.go +++ b/policy.go @@ -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") type ChildOfPolicy struct { PerNodePolicy @@ -55,7 +76,18 @@ func (policy *ChildOfPolicy) Allows(context *StateContext, principal *Node, acti 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) { 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{ PerNodePolicy: NewPerNodePolicy(node_actions), } @@ -121,7 +153,7 @@ func (policy *ParentOfPolicy) Allows(context *StateContext, principal *Node, act return false } -func NewParentOfPolicy(node_actions map[NodeID][]string) ParentOfPolicy { +func NewParentOfPolicy(node_actions NodeActions) ParentOfPolicy { return ParentOfPolicy{ PerNodePolicy: NewPerNodePolicy(node_actions), } @@ -129,7 +161,7 @@ func NewParentOfPolicy(node_actions map[NodeID][]string) ParentOfPolicy { func NewPerNodePolicy(node_actions NodeActions) PerNodePolicy { if node_actions == nil { - node_actions = map[NodeID][]string{} + node_actions = NodeActions{} } return PerNodePolicy{ @@ -138,7 +170,7 @@ func NewPerNodePolicy(node_actions NodeActions) PerNodePolicy { } type PerNodePolicy struct { - NodeActions map[NodeID][]string + NodeActions NodeActions } type PerNodePolicyJSON struct { @@ -329,7 +361,7 @@ func LoadACLPolicyExt(ctx *Context, data []byte) (Extension, error) { } policies := map[PolicyType]Policy{} - acl_ctx := ctx.ExtByType(ACLPolicyExtType).Data.(ACLPolicyExtContext) + acl_ctx := ctx.ExtByType(ACLPolicyExtType).Data.(*ACLPolicyExtContext) for name, ser := range(j.Policies) { policy_def, exists := acl_ctx.Types[PolicyType(name)] if exists == false { diff --git a/thread.go b/thread.go index e24a398..4c804cf 100644 --- a/thread.go +++ b/thread.go @@ -189,6 +189,7 @@ func NewThreadExt(ctx*Context, thread_type ThreadType, parent *Node, children ma next_action, timeout_chan := SoonestAction(action_queue) return &ThreadExt{ + ThreadType: thread_type, Actions: type_info.Actions, Handlers: type_info.Handlers, SignalChan: make(chan Signal, THREAD_BUFFER_SIZE), @@ -209,23 +210,43 @@ func LoadThreadExt(ctx *Context, data []byte) (Extension, error) { if err != nil { return nil, err } + ctx.Log.Logf("db", "DB_LOAD_THREAD_EXT_JSON: %+v", j) parent, err := RestoreNode(ctx, j.Parent) if err != nil { return nil, err } + + thread_ctx, err := GetCtx[*ThreadExt, *ThreadExtContext](ctx) + if err != nil { + return nil, err + } + children := map[NodeID]ChildInfo{} - for id_str, _ := range(j.Children) { + for id_str, infos := range(j.Children) { child_node, err := RestoreNode(ctx, id_str) if err != nil { 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{ Child: child_node, - Infos: map[InfoType]Info{}, + Infos: child_infos, } }