From ad03154b6ea7999509835bb3edc2850a7051f965 Mon Sep 17 00:00:00 2001 From: Fabio Bozzo Date: Mon, 16 Sep 2024 13:00:13 +0200 Subject: [PATCH] handle list nodes equality in selector --- capability/policy/match.go | 35 +++++++++++++---- capability/policy/selector/selector.go | 52 +++++++++++++++++++++----- 2 files changed, 69 insertions(+), 18 deletions(-) diff --git a/capability/policy/match.go b/capability/policy/match.go index b00d3af..14cdc94 100644 --- a/capability/policy/match.go +++ b/capability/policy/match.go @@ -26,11 +26,22 @@ func matchStatement(statement Statement, node ipld.Node) bool { switch statement.Kind() { case KindEqual: if s, ok := statement.(equality); ok { - one, _, err := selector.Select(s.selector, node) - if err != nil || one == nil { + one, many, err := selector.Select(s.selector, node) + if err != nil { return false } - return datamodel.DeepEqual(s.value, one) + if one != nil { + return datamodel.DeepEqual(s.value, one) + } + if many != nil { + for _, n := range many { + if eq := datamodel.DeepEqual(s.value, n); eq { + return true + } + } + } + + return false } case KindGreaterThan: if s, ok := statement.(equality); ok { @@ -119,17 +130,25 @@ func matchStatement(statement Statement, node ipld.Node) bool { } case KindAny: if s, ok := statement.(quantifier); ok { - // FIXME: line below return a single node, not many - _, many, err := selector.Select(s.selector, node) - if err != nil || many == nil { + one, many, err := selector.Select(s.selector, node) + if err != nil { return false } - for _, n := range many { - ok := matchStatement(s.statement, n) + if one != nil { + ok := matchStatement(s.statement, one) if ok { return true } } + if many != nil { + for _, n := range many { + ok := matchStatement(s.statement, n) + if ok { + return true + } + } + } + return false } } diff --git a/capability/policy/selector/selector.go b/capability/policy/selector/selector.go index 1bd85f2..83c90e7 100644 --- a/capability/policy/selector/selector.go +++ b/capability/policy/selector/selector.go @@ -199,26 +199,58 @@ func resolve(sel Selector, subject ipld.Node, at []string) (ipld.Node, []ipld.No case seg.Field() != "": at = append(at, seg.Field()) - if cur == nil || cur.Kind() != datamodel.Kind_Map { + if cur == nil { if seg.Optional() { cur = nil } else { return nil, nil, newResolutionError(fmt.Sprintf("can not access field: %s on kind: %s", seg.Field(), kindString(cur)), at) } } else { - n, err := cur.LookupByString(seg.Field()) - if err != nil { - if isMissing(err) { - if seg.Optional() { - cur = nil + switch cur.Kind() { + case datamodel.Kind_Map: + n, err := cur.LookupByString(seg.Field()) + if err != nil { + if isMissing(err) { + if seg.Optional() { + cur = nil + } else { + return nil, nil, newResolutionError(fmt.Sprintf("object has no field named: %s", seg.Field()), at) + } } else { - return nil, nil, newResolutionError(fmt.Sprintf("object has no field named: %s", seg.Field()), at) + return nil, nil, err } } else { - return nil, nil, err + cur = n + } + case datamodel.Kind_List: + var many []ipld.Node + it := cur.ListIterator() + for !it.Done() { + _, v, err := it.Next() + if err != nil { + return nil, nil, err + } + if v.Kind() == datamodel.Kind_Map { + n, err := v.LookupByString(seg.Field()) + if err == nil { + many = append(many, n) + } + } + } + if len(many) > 0 { + cur = nil + return nil, many, nil + } else if seg.Optional() { + cur = nil + } else { + return nil, nil, newResolutionError(fmt.Sprintf("no elements in list have field named: %s", seg.Field()), at) + } + default: + if seg.Optional() { + cur = nil + } else { + return nil, nil, newResolutionError(fmt.Sprintf("can not access field: %s on kind: %s", seg.Field(), kindString(cur)), at) } - } else { - cur = n } }