Added read signal, and modified policies to use non-pointer receivers

gql_cataclysm
noah metz 2023-07-28 11:21:18 -06:00
parent b3de3144cc
commit fc69bc3d0d
8 changed files with 132 additions and 25 deletions

@ -785,6 +785,14 @@ type GQLExt struct {
SubscribeListeners []chan Signal SubscribeListeners []chan Signal
} }
func (ext *GQLExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*GQLExt)interface{}{
"listen": func(ext *GQLExt) interface{} {
return ext.Listen
},
})
}
func (ext *GQLExt) NewSubscriptionChannel(buffer int) chan Signal { func (ext *GQLExt) NewSubscriptionChannel(buffer int) chan Signal {
ext.SubscribeLock.Lock() ext.SubscribeLock.Lock()
defer ext.SubscribeLock.Unlock() defer ext.SubscribeLock.Unlock()

@ -91,7 +91,7 @@ func NewSimpleListener(ctx *Context, buffer int) (*Node, *ListenerExt) {
SimpleListenerNodeType, SimpleListenerNodeType,
nil, nil,
listener_extension, listener_extension,
NewACLExt(&policy), NewACLExt(policy),
NewLockableExt()) NewLockableExt())
return listener, listener_extension return listener, listener_extension

@ -19,6 +19,17 @@ func NewListenerExt(buffer int) *ListenerExt {
} }
} }
func (ext *ListenerExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*ListenerExt)interface{}{
"buffer": func(ext *ListenerExt) interface{} {
return ext.Buffer
},
"chan": func(ext *ListenerExt) interface{} {
return ext.Chan
},
})
}
// Simple load function, unmarshal the buffer int from json // Simple load function, unmarshal the buffer int from json
func LoadListenerExt(ctx *Context, data []byte) (Extension, error) { func LoadListenerExt(ctx *Context, data []byte) (Extension, error) {
var j int var j int
@ -66,6 +77,23 @@ type LockableExtJSON struct {
Dependencies map[string]string `json:"dependencies"` Dependencies map[string]string `json:"dependencies"`
} }
func (ext *LockableExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*LockableExt)interface{}{
"owner": func(ext *LockableExt) interface{} {
return ext.Owner
},
"pending_owner": func(ext *LockableExt) interface{} {
return ext.PendingOwner
},
"requirements": func(ext *LockableExt) interface{} {
return ext.Requirements
},
"dependencies": func(ext *LockableExt) interface{} {
return ext.Dependencies
},
})
}
func LoadLockableExt(ctx *Context, data []byte) (Extension, error) { func LoadLockableExt(ctx *Context, data []byte) (Extension, error) {
var j LockableExtJSON var j LockableExtJSON
err := json.Unmarshal(data, &j) err := json.Unmarshal(data, &j)

@ -26,13 +26,13 @@ func TestLink(t *testing.T) {
l1_listener := NewListenerExt(10) l1_listener := NewListenerExt(10)
l1 := NewNode(ctx, RandID(), TestLockableType, nil, l1 := NewNode(ctx, RandID(), TestLockableType, nil,
l1_listener, l1_listener,
NewACLExt(&link_policy), NewACLExt(link_policy),
NewLockableExt(), NewLockableExt(),
) )
l2_listener := NewListenerExt(10) l2_listener := NewListenerExt(10)
l2 := NewNode(ctx, RandID(), TestLockableType, nil, l2 := NewNode(ctx, RandID(), TestLockableType, nil,
l2_listener, l2_listener,
NewACLExt(&link_policy), NewACLExt(link_policy),
NewLockableExt(), NewLockableExt(),
) )
@ -57,7 +57,7 @@ func TestLock(t *testing.T) {
listener := NewListenerExt(10) listener := NewListenerExt(10)
l := NewNode(ctx, RandID(), TestLockableType, nil, l := NewNode(ctx, RandID(), TestLockableType, nil,
listener, listener,
NewACLExt(&lock_policy, &link_policy), NewACLExt(lock_policy, link_policy),
NewLockableExt(), NewLockableExt(),
) )
return l, listener return l, listener

@ -72,6 +72,7 @@ type Serializable[I comparable] interface {
// Extensions are data attached to nodes that process signals // Extensions are data attached to nodes that process signals
type Extension interface { type Extension interface {
Serializable[ExtType] Serializable[ExtType]
Field(string)interface{}
Process(context *Context, source NodeID, node *Node, signal Signal) Process(context *Context, source NodeID, node *Node, signal Signal)
} }
@ -142,6 +143,27 @@ type Msg struct {
Signal Signal Signal Signal
} }
func ReadNodeFields(ctx *Context, self *Node, princ NodeID, reqs map[ExtType][]string)map[ExtType]map[string]interface{} {
exts := map[ExtType]map[string]interface{}{}
for ext_type, field_reqs := range(reqs) {
fields := map[string]interface{}{}
for _, req := range(field_reqs) {
err := Allowed(ctx, princ, MakeAction(ReadSignalType, ext_type, req), self)
if err != nil {
fields[req] = err
} else {
ext, exists := self.Extensions[ext_type]
if exists == false {
fields[req] = fmt.Errorf("%s does not have %s extension", self.ID, ext_type)
} else {
fields[req] = ext.Field(req)
}
}
}
}
return exts
}
// Main Loop for Threads, starts a write context, so cannot be called from a write or read context // Main Loop for Threads, starts a write context, so cannot be called from a write or read context
func nodeLoop(ctx *Context, node *Node) error { func nodeLoop(ctx *Context, node *Node) error {
started := node.Active.CompareAndSwap(false, true) started := node.Active.CompareAndSwap(false, true)
@ -171,7 +193,16 @@ func nodeLoop(ctx *Context, node *Node) error {
if signal.Type() == StopSignalType { if signal.Type() == StopSignalType {
node.Process(ctx, node.ID, NewStatusSignal("stopped", node.ID)) node.Process(ctx, node.ID, NewStatusSignal("stopped", node.ID))
break break
} else if signal.Type() == ReadSignalType {
read_signal, ok := signal.(ReadSignal)
if ok == false {
ctx.Log.Logf("signal", "READ_SIGNAL: bad cast %+v", signal)
} else {
fields := ReadNodeFields(ctx, node, source, read_signal.Extensions)
ctx.Log.Logf("test", "READ_RESULT: %+v", fields)
}
} }
node.Process(ctx, source, signal) node.Process(ctx, source, signal)
} }

@ -22,11 +22,11 @@ type Policy interface {
Merge(Policy) Policy Merge(Policy) Policy
} }
func (policy *AllNodesPolicy) Allows(principal_id NodeID, action Action, node *Node) error { func (policy AllNodesPolicy) Allows(principal_id NodeID, action Action, node *Node) error {
return policy.Actions.Allows(action) return policy.Actions.Allows(action)
} }
func (policy *PerNodePolicy) Allows(principal_id NodeID, action Action, node *Node) error { func (policy PerNodePolicy) Allows(principal_id NodeID, action Action, node *Node) error {
for id, actions := range(policy.NodeActions) { for id, actions := range(policy.NodeActions) {
if id != principal_id { if id != principal_id {
continue continue
@ -36,7 +36,7 @@ func (policy *PerNodePolicy) Allows(principal_id NodeID, action Action, node *No
return fmt.Errorf("%s is not in per node policy of %s", principal_id, node.ID) return fmt.Errorf("%s is not in per node policy of %s", principal_id, node.ID)
} }
func (policy *RequirementOfPolicy) Allows(principal_id NodeID, action Action, node *Node) error { func (policy RequirementOfPolicy) Allows(principal_id NodeID, action Action, node *Node) error {
lockable_ext, err := GetExt[*LockableExt](node) lockable_ext, err := GetExt[*LockableExt](node)
if err != nil { if err != nil {
return err return err
@ -54,7 +54,7 @@ func (policy *RequirementOfPolicy) Allows(principal_id NodeID, action Action, no
type RequirementOfPolicy struct { type RequirementOfPolicy struct {
AllNodesPolicy AllNodesPolicy
} }
func (policy *RequirementOfPolicy) Type() PolicyType { func (policy RequirementOfPolicy) Type() PolicyType {
return RequirementOfPolicyType return RequirementOfPolicyType
} }
@ -83,20 +83,20 @@ func MergeNodeActions(modified NodeActions, read NodeActions) {
} }
} }
func (policy *PerNodePolicy) Merge(p Policy) Policy { func (policy PerNodePolicy) Merge(p Policy) Policy {
other := p.(*PerNodePolicy) other := p.(PerNodePolicy)
MergeNodeActions(policy.NodeActions, other.NodeActions) MergeNodeActions(policy.NodeActions, other.NodeActions)
return policy return policy
} }
func (policy *AllNodesPolicy) Merge(p Policy) Policy { func (policy AllNodesPolicy) Merge(p Policy) Policy {
other := p.(*AllNodesPolicy) other := p.(AllNodesPolicy)
policy.Actions = MergeActions(policy.Actions, other.Actions) policy.Actions = MergeActions(policy.Actions, other.Actions)
return policy return policy
} }
func (policy *RequirementOfPolicy) Merge(p Policy) Policy { func (policy RequirementOfPolicy) Merge(p Policy) Policy {
other := p.(*RequirementOfPolicy) other := p.(RequirementOfPolicy)
policy.Actions = MergeActions(policy.Actions, other.Actions) policy.Actions = MergeActions(policy.Actions, other.Actions)
return policy return policy
} }
@ -190,11 +190,11 @@ type PerNodePolicy struct {
NodeActions NodeActions `json:"node_actions"` NodeActions NodeActions `json:"node_actions"`
} }
func (policy *PerNodePolicy) Type() PolicyType { func (policy PerNodePolicy) Type() PolicyType {
return PerNodePolicyType return PerNodePolicyType
} }
func (policy *PerNodePolicy) Serialize() ([]byte, error) { func (policy PerNodePolicy) Serialize() ([]byte, error) {
return json.MarshalIndent(policy, "", " ") return json.MarshalIndent(policy, "", " ")
} }
@ -212,11 +212,11 @@ type AllNodesPolicy struct {
Actions Actions Actions Actions
} }
func (policy *AllNodesPolicy) Type() PolicyType { func (policy AllNodesPolicy) Type() PolicyType {
return AllNodesPolicyType return AllNodesPolicyType
} }
func (policy *AllNodesPolicy) Serialize() ([]byte, error) { func (policy AllNodesPolicy) Serialize() ([]byte, error) {
return json.MarshalIndent(policy, "", " ") return json.MarshalIndent(policy, "", " ")
} }
@ -288,6 +288,14 @@ func (ext *ACLExt) Serialize() ([]byte, error) {
func (ext *ACLExt) Process(ctx *Context, princ_id NodeID, node *Node, signal Signal) { func (ext *ACLExt) Process(ctx *Context, princ_id NodeID, node *Node, signal Signal) {
} }
func (ext *ACLExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*ACLExt)interface{}{
"policies": func(ext *ACLExt) interface{} {
return ext.Policies
},
})
}
func NewACLExt(policies ...Policy) *ACLExt { func NewACLExt(policies ...Policy) *ACLExt {
policy_map := map[PolicyType]Policy{} policy_map := map[PolicyType]Policy{}
for _, policy := range(policies) { for _, policy := range(policies) {

@ -9,6 +9,7 @@ const (
StatusSignalType = SignalType("STATUS") StatusSignalType = SignalType("STATUS")
LinkSignalType = SignalType("LINK") LinkSignalType = SignalType("LINK")
LockSignalType = SignalType("LOCK") LockSignalType = SignalType("LOCK")
ReadSignalType = SignalType("READ")
) )
type SignalDirection int type SignalDirection int
@ -144,14 +145,14 @@ func (signal StateSignal) Permission() Action {
return MakeAction(signal.Type(), signal.State) return MakeAction(signal.Type(), signal.State)
} }
type StartChildSignal struct { type ReadSignal struct {
IDSignal BaseSignal
Action string `json:"action"` Extensions map[ExtType][]string `json:"extensions"`
} }
func NewStartChildSignal(child_id NodeID, action string) StartChildSignal { func NewReadSignal(exts map[ExtType][]string) ReadSignal {
return StartChildSignal{ return ReadSignal{
IDSignal: NewIDSignal("start_child", Direct, child_id), BaseSignal: NewDirectSignal(ReadSignalType),
Action: action, Extensions: exts,
} }
} }

@ -14,6 +14,29 @@ type ECDHExt struct {
Shared []byte Shared []byte
} }
func ResolveFields[T Extension](t T, name string, field_funcs map[string]func(T)interface{})interface{} {
var zero T
field_func, ok := field_funcs[name]
if ok == false {
return fmt.Errorf("%s is not a field of %s", name, zero.Type())
}
return field_func(t)
}
func (ext *ECDHExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*ECDHExt)interface{}{
"granted": func(ext *ECDHExt) interface{} {
return ext.Granted
},
"pubkey": func(ext *ECDHExt) interface{} {
return ext.Pubkey
},
"shared": func(ext *ECDHExt) interface{} {
return ext.Shared
},
})
}
type ECDHExtJSON struct { type ECDHExtJSON struct {
Granted time.Time `json:"granted"` Granted time.Time `json:"granted"`
Pubkey []byte `json:"pubkey"` Pubkey []byte `json:"pubkey"`
@ -88,6 +111,14 @@ func (ext *GroupExt) Serialize() ([]byte, error) {
}, "", " ") }, "", " ")
} }
func (ext *GroupExt) Field(name string) interface{} {
return ResolveFields(ext, name, map[string]func(*GroupExt)interface{}{
"members": func(ext *GroupExt) interface{} {
return ext.Members
},
})
}
func NewGroupExt(members map[NodeID]string) *GroupExt { func NewGroupExt(members map[NodeID]string) *GroupExt {
if members == nil { if members == nil {
members = map[NodeID]string{} members = map[NodeID]string{}