From c54101f4a3f6c21afb9cb82c862e5495366dcaf5 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Sat, 11 Nov 2023 13:53:41 -0700 Subject: [PATCH] Don't have time to explain :/ --- context.go | 5 +++++ event.go | 2 +- gql.go | 26 +++++++++++++++++++---- lockable.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++++---- serialize.go | 1 + 5 files changed, 83 insertions(+), 9 deletions(-) diff --git a/context.go b/context.go index b6b7f54..52f4ccc 100644 --- a/context.go +++ b/context.go @@ -614,6 +614,11 @@ func NewContext(db * badger.DB, log Logger) (*Context, error) { return nil, err } + err = ctx.RegisterPolicy(reflect.TypeOf(OwnerOfPolicy{}), OwnerOfPolicyType) + if err != nil { + return nil, err + } + err = ctx.RegisterPolicy(reflect.TypeOf(ParentOfPolicy{}), ParentOfPolicyType) if err != nil { return nil, err diff --git a/event.go b/event.go index 5253cb3..af830e7 100644 --- a/event.go +++ b/event.go @@ -81,7 +81,7 @@ func NewEventStateSignal(source NodeID, state string, t time.Time) *EventStateSi type EventControlSignal struct { SignalHeader - Command string + Command string `gv:"command"` } func (signal EventControlSignal) String() string { diff --git a/gql.go b/gql.go index adcdbc2..09479be 100644 --- a/gql.go +++ b/gql.go @@ -1292,12 +1292,12 @@ func NewGQLExtContext() *GQLExtContext { return name, nil }) - err = context.RegisterField(graphql.String, "State", EventExtType, "state", func(p graphql.ResolveParams, ctx *ResolveContext, val reflect.Value)(interface{}, error) { + err = context.RegisterField(graphql.String, "EventState", EventExtType, "state", func(p graphql.ResolveParams, ctx *ResolveContext, val reflect.Value)(interface{}, error) { state := val.String() return state, nil }) - err = context.RegisterInterface("Event", "EventNode", []string{"Node"}, []string{"EventName", "State"}, map[string]SelfField{}, map[string]ListField{}) + err = context.RegisterInterface("Event", "EventNode", []string{"Node"}, []string{"EventName", "EventState"}, map[string]SelfField{}, map[string]ListField{}) if err != nil { panic(err) } @@ -1371,7 +1371,20 @@ func NewGQLExtContext() *GQLExtContext { panic(err) } - err = context.RegisterInterface("Lockable", "DefaultLockable", []string{"Node"}, []string{}, map[string]SelfField{ + err = context.RegisterField(graphql.String, "LockableState", LockableExtType, "state", + func(p graphql.ResolveParams, ctx *ResolveContext, value reflect.Value)(interface{}, error) { + state, ok := value.Interface().(ReqState) + if ok == false { + return nil, fmt.Errorf("value is %+v, not ReqState", value.Type()) + } + + return ReqStateStrings[state], nil + }) + if err != nil { + panic(err) + } + + err = context.RegisterInterface("Lockable", "DefaultLockable", []string{"Node"}, []string{"LockableState"}, map[string]SelfField{ "Owner": { "owner", LockableExtType, @@ -1414,7 +1427,7 @@ func NewGQLExtContext() *GQLExtContext { panic(err) } - err = context.RegisterNodeType(GQLNodeType, "GQLServer", []string{"Node", "Lockable", "Group"}, []string{"Listen", "Owner", "Requirements", "SubGroups"}) + err = context.RegisterNodeType(GQLNodeType, "GQLServer", []string{"Node", "Lockable", "Group"}, []string{"LockableState", "Listen", "Owner", "Requirements", "SubGroups"}) if err != nil { panic(err) } @@ -1434,6 +1447,11 @@ func NewGQLExtContext() *GQLExtContext { panic(err) } + err = context.AddSignalMutation("eventControl", "event_id", reflect.TypeOf(EventControlSignal{})) + if err != nil { + panic(err) + } + context.Subscription.AddFieldConfig("Self", &graphql.Field{ Type: context.Interfaces["Node"].Interface, Subscribe: func(p graphql.ResolveParams) (interface{}, error) { diff --git a/lockable.go b/lockable.go index 8f5c328..9c84deb 100644 --- a/lockable.go +++ b/lockable.go @@ -75,9 +75,24 @@ func (ext *LockableExt) HandleErrorSignal(ctx *Context, node *Node, source NodeI if info_found { state, found := ext.Requirements[info.Destination] if found == true { - ctx.Log.Logf("lockable", "got mapped response %+v for %+v in state %s", signal, info, ReqStateStrings[state]) - switch state { + changes.Add(LockableExtType, "wait_infos") + ctx.Log.Logf("lockable", "got mapped response %+v for %+v in state %s while in %s", signal, info, ReqStateStrings[state], ReqStateStrings[ext.State]) + switch ext.State { + case AbortingLock: + ext.Requirements[info.Destination] = Unlocked + all_unlocked := true + for _, state := range(ext.Requirements) { + if state != Unlocked { + all_unlocked = false + break + } + } + if all_unlocked == true { + changes.Add(LockableExtType, "state") + ext.State = Unlocked + } case Locking: + changes.Add(LockableExtType, "state") ext.State = AbortingLock ext.Requirements[info.Destination] = Unlocked for id, state := range(ext.Requirements) { @@ -247,7 +262,7 @@ func (ext *LockableExt) HandleLockSignal(ctx *Context, node *Node, source NodeID } lock_signal := NewLockSignal("lock") - ext.WaitInfos[lock_signal.Id] = node.QueueTimeout("lock", id, lock_signal, 5000*time.Millisecond) + ext.WaitInfos[lock_signal.Id] = node.QueueTimeout("lock", id, lock_signal, 500*time.Millisecond) ext.Requirements[id] = Locking messages = messages.Add(ctx, id, node, nil, lock_signal) @@ -255,7 +270,7 @@ func (ext *LockableExt) HandleLockSignal(ctx *Context, node *Node, source NodeID } default: messages = messages.Add(ctx, source, node, nil, NewErrorSignal(signal.ID(), "not_unlocked")) - ctx.Log.Logf("lockable", "Tried to lock %s while locked", node.ID) + ctx.Log.Logf("lockable", "Tried to lock %s while %s", node.ID, ext.State) } case "unlock": if ext.State == Locked { @@ -300,6 +315,7 @@ func (ext *LockableExt) HandleTimeoutSignal(ctx *Context, node *Node, source Nod wait_info, found := node.ProcessResponse(ext.WaitInfos, signal) if found == true { + changes.Add(LockableExtType, "wait_infos") state, found := ext.Requirements[wait_info.Destination] if found == true { ctx.Log.Logf("lockable", "%s timed out %s", wait_info.Destination, ReqStateStrings[state]) @@ -364,6 +380,40 @@ func (ext *LockableExt) Process(ctx *Context, node *Node, source NodeID, signal return messages, changes } +type OwnerOfPolicy struct { + PolicyHeader + Rules Tree `gv:"rules"` +} + +func NewOwnerOfPolicy(rules Tree) OwnerOfPolicy { + return OwnerOfPolicy{ + PolicyHeader: NewPolicyHeader(), + Rules: rules, + } +} + +func (policy OwnerOfPolicy) ContinueAllows(ctx *Context, current PendingACL, signal Signal) RuleResult { + return Deny +} + +func (policy OwnerOfPolicy) Allows(ctx *Context, principal_id NodeID, action Tree, node *Node)(Messages, RuleResult) { + l_ext, err := GetExt[*LockableExt](node, LockableExtType) + if err != nil { + ctx.Log.Logf("lockable", "OwnerOfPolicy.Allows called on node without LockableExt") + return nil, Deny + } + + if l_ext.Owner == nil { + return nil, Deny + } + + if principal_id == *l_ext.Owner { + return nil, Allow + } + + return nil, Deny +} + type RequirementOfPolicy struct { PerNodePolicy } diff --git a/serialize.go b/serialize.go index e0020f7..68e92a4 100644 --- a/serialize.go +++ b/serialize.go @@ -238,6 +238,7 @@ var ( EventStateSignalType = NewSignalType("VEX_MATCH_STATUS") MemberOfPolicyType = NewPolicyType("MEMBER_OF") + OwnerOfPolicyType = NewPolicyType("OWNER_OF") ParentOfPolicyType = NewPolicyType("PARENT_OF") RequirementOfPolicyType = NewPolicyType("REQUIEMENT_OF") PerNodePolicyType = NewPolicyType("PER_NODE")