From 18c31c6c3972df4eb69d77f45def87713af24717 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Tue, 27 Oct 2020 20:20:01 +0300 Subject: [PATCH] [#182] sdk/eacl: Implement convenient methods for adding object filters Signed-off-by: Leonard Lyubich --- pkg/acl/eacl/filter.go | 68 ++++++++++++++++++++++++++++++++----- pkg/acl/eacl/filter_test.go | 18 ++++++---- pkg/acl/eacl/record.go | 47 ++++++++++++++++++++++--- pkg/acl/eacl/record_test.go | 14 ++------ 4 files changed, 116 insertions(+), 31 deletions(-) diff --git a/pkg/acl/eacl/filter.go b/pkg/acl/eacl/filter.go index 29e8128d..1771b955 100644 --- a/pkg/acl/eacl/filter.go +++ b/pkg/acl/eacl/filter.go @@ -1,6 +1,8 @@ package eacl import ( + "fmt" + v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" ) @@ -8,13 +10,40 @@ import ( // header means that request should be processed according to EACL action. type Filter struct { from FilterHeaderType - key string + key filterKey matcher Match - value string + value fmt.Stringer +} + +type staticStringer string + +type filterKey struct { + typ filterKeyType + + str string +} + +// enumeration of reserved filter keys. +type filterKeyType int + +const ( + _ filterKeyType = iota + fKeyObjVersion + fKeyObjContainerID + fKeyObjOwnerID + fKeyObjCreationEpoch + fKeyObjPayloadLength + fKeyObjPayloadHash + fKeyObjType + fKeyObjHomomorphicHash +) + +func (s staticStringer) String() string { + return string(s) } func (a Filter) Value() string { - return a.value + return a.value.String() } func (a Filter) Matcher() Match { @@ -22,7 +51,7 @@ func (a Filter) Matcher() Match { } func (a Filter) Key() string { - return a.key + return a.key.String() } func (a Filter) From() FilterHeaderType { @@ -31,14 +60,37 @@ func (a Filter) From() FilterHeaderType { func (a *Filter) ToV2() *v2acl.HeaderFilter { filter := new(v2acl.HeaderFilter) - filter.SetValue(a.value) - filter.SetKey(a.key) + filter.SetValue(a.value.String()) + filter.SetKey(a.key.String()) filter.SetMatchType(a.matcher.ToV2()) filter.SetHeaderType(a.from.ToV2()) return filter } +func (k filterKey) String() string { + switch k.typ { + default: + return k.str + case fKeyObjVersion: + return v2acl.FilterObjectVersion + case fKeyObjContainerID: + return v2acl.FilterObjectContainerID + case fKeyObjOwnerID: + return v2acl.FilterObjectOwnerID + case fKeyObjCreationEpoch: + return v2acl.FilterObjectCreationEpoch + case fKeyObjPayloadLength: + return v2acl.FilterObjectPayloadLength + case fKeyObjPayloadHash: + return v2acl.FilterObjectPayloadHash + case fKeyObjType: + return v2acl.FilterObjectType + case fKeyObjHomomorphicHash: + return v2acl.FilterObjectHomomorphicHash + } +} + func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter { f := new(Filter) @@ -48,8 +100,8 @@ func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter { f.from = FilterHeaderTypeFromV2(filter.GetHeaderType()) f.matcher = MatchFromV2(filter.GetMatchType()) - f.key = filter.GetKey() - f.value = filter.GetValue() + f.key.str = filter.GetKey() + f.value = staticStringer(filter.GetValue()) return f } diff --git a/pkg/acl/eacl/filter_test.go b/pkg/acl/eacl/filter_test.go index 0fa874d1..f87033ca 100644 --- a/pkg/acl/eacl/filter_test.go +++ b/pkg/acl/eacl/filter_test.go @@ -7,13 +7,19 @@ import ( "github.com/stretchr/testify/require" ) -func TestFilter(t *testing.T) { - filter := &Filter{ - from: HeaderFromObject, - key: "some name", - matcher: MatchStringEqual, - value: "200", +func newObjectFilter(match Match, key, val string) *Filter { + return &Filter{ + from: HeaderFromObject, + key: filterKey{ + str: key, + }, + matcher: match, + value: staticStringer(val), } +} + +func TestFilter(t *testing.T) { + filter := newObjectFilter(MatchStringEqual, "some name", "200") v2 := filter.ToV2() require.NotNil(t, v2) diff --git a/pkg/acl/eacl/record.go b/pkg/acl/eacl/record.go index f0792b70..126652e6 100644 --- a/pkg/acl/eacl/record.go +++ b/pkg/acl/eacl/record.go @@ -2,7 +2,11 @@ package eacl import ( "crypto/ecdsa" + "fmt" + "github.com/nspcc-dev/neofs-api-go/pkg" + "github.com/nspcc-dev/neofs-api-go/pkg/container" + "github.com/nspcc-dev/neofs-api-go/pkg/owner" v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl" ) @@ -54,17 +58,50 @@ func (r *Record) AddTarget(role Role, keys ...ecdsa.PublicKey) { r.targets = append(r.targets, t) } -func (r *Record) AddFilter(from FilterHeaderType, matcher Match, name, value string) { +func (r *Record) addFilter(from FilterHeaderType, m Match, keyTyp filterKeyType, key string, val fmt.Stringer) { filter := Filter{ - from: from, - key: name, - matcher: matcher, - value: value, + from: from, + key: filterKey{ + typ: keyTyp, + str: key, + }, + matcher: m, + value: val, } r.filters = append(r.filters, filter) } +func (r *Record) addObjectFilter(m Match, keyTyp filterKeyType, key string, val fmt.Stringer) { + r.addFilter(HeaderFromObject, m, keyTyp, key, val) +} + +func (r *Record) addObjectReservedFilter(m Match, typ filterKeyType, val fmt.Stringer) { + r.addObjectFilter(m, typ, "", val) +} + +func (r *Record) AddFilter(from FilterHeaderType, matcher Match, name, value string) { + r.addFilter(from, matcher, 0, name, staticStringer(value)) +} + +func (r *Record) AddObjectAttributeFilter(m Match, key, value string) { + r.addObjectFilter(m, 0, key, staticStringer(value)) +} + +func (r *Record) AddObjectVersionFilter(m Match, v *pkg.Version) { + r.addObjectReservedFilter(m, fKeyObjVersion, v) +} + +func (r *Record) AddObjectContainerIDFilter(m Match, id *container.ID) { + r.addObjectReservedFilter(m, fKeyObjContainerID, id) +} + +func (r *Record) AddObjectOwnerIDFilter(m Match, id *owner.ID) { + r.addObjectReservedFilter(m, fKeyObjOwnerID, id) +} + +// TODO: add remaining filters after neofs-api#72 + func (r *Record) ToV2() *v2acl.Record { targets := make([]*v2acl.Target, 0, len(r.targets)) for _, target := range r.targets { diff --git a/pkg/acl/eacl/record_test.go b/pkg/acl/eacl/record_test.go index 428794a1..7cddd2e0 100644 --- a/pkg/acl/eacl/record_test.go +++ b/pkg/acl/eacl/record_test.go @@ -60,18 +60,8 @@ func TestRecord_AddTarget(t *testing.T) { func TestRecord_AddFilter(t *testing.T) { filters := []Filter{ - { - from: HeaderFromObject, - key: "some name", - matcher: MatchStringEqual, - value: "ContainerID", - }, - { - from: HeaderFromRequest, - key: "X-Header-Name", - matcher: MatchStringNotEqual, - value: "X-Header-Value", - }, + *newObjectFilter(MatchStringEqual, "some name", "ContainerID"), + *newObjectFilter(MatchStringNotEqual, "X-Header-Name", "X-Header-Value"), } r := NewRecord()