Skip to content

Commit

Permalink
eacl: Export keys to object filters
Browse files Browse the repository at this point in the history
They are not really needed for eACL setting - convenient methods are
provided. But `Filter.Key` method provides access to them, so user
should be fully equiped for switching or comparison.

Signed-off-by: Leonard Lyubich <leonard@morphbits.io>
  • Loading branch information
cthulhu-rider committed Apr 12, 2024
1 parent 10f0668 commit f761ba3
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 131 deletions.
88 changes: 14 additions & 74 deletions eacl/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,25 @@ import (
type Filter struct {
from FilterHeaderType
matcher Match
key filterKey
key string
value stringEncoder
}

type staticStringer string

type u64Stringer uint64

type filterKey struct {
typ filterKeyType

str string
}

// enumeration of reserved filter keys.
type filterKeyType int

// Various keys to object filters.
const (
_ filterKeyType = iota
fKeyObjVersion
fKeyObjID
fKeyObjContainerID
fKeyObjOwnerID
fKeyObjCreationEpoch
fKeyObjPayloadLength
fKeyObjPayloadHash
fKeyObjType
fKeyObjHomomorphicHash
fKeyObjLast // helper, used in tests
FilterObjectVersion = v2acl.FilterObjectVersion
FilterObjectID = v2acl.FilterObjectID
FilterObjectContainerID = v2acl.FilterObjectContainerID
FilterObjectOwnerID = v2acl.FilterObjectOwnerID
FilterObjectCreationEpoch = v2acl.FilterObjectCreationEpoch
FilterObjectPayloadSize = v2acl.FilterObjectPayloadLength
FilterObjectPayloadChecksum = v2acl.FilterObjectPayloadHash
FilterObjectType = v2acl.FilterObjectType
FilterObjectPayloadHomomorphicChecksum = v2acl.FilterObjectHomomorphicHash
)

func (s staticStringer) EncodeToString() string {
Expand Down Expand Up @@ -72,7 +62,7 @@ func (f Filter) Matcher() Match {

// Key returns key to the filtered header.
func (f Filter) Key() string {
return f.key.String()
return f.key
}

// From returns FilterHeaderType that defined which header will be filtered.
Expand All @@ -90,63 +80,13 @@ func (f *Filter) ToV2() *v2acl.HeaderFilter {

filter := new(v2acl.HeaderFilter)
filter.SetValue(f.value.EncodeToString())
filter.SetKey(f.key.String())
filter.SetKey(f.key)
filter.SetMatchType(f.matcher.ToV2())
filter.SetHeaderType(f.from.ToV2())

return filter
}

func (k filterKey) String() string {
switch k.typ {
default:
return k.str
case fKeyObjVersion:
return v2acl.FilterObjectVersion
case fKeyObjID:
return v2acl.FilterObjectID
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 (k *filterKey) fromString(s string) {
switch s {
default:
k.typ, k.str = 0, s
case v2acl.FilterObjectVersion:
k.typ, k.str = fKeyObjVersion, ""
case v2acl.FilterObjectID:
k.typ, k.str = fKeyObjID, ""
case v2acl.FilterObjectContainerID:
k.typ, k.str = fKeyObjContainerID, ""
case v2acl.FilterObjectOwnerID:
k.typ, k.str = fKeyObjOwnerID, ""
case v2acl.FilterObjectCreationEpoch:
k.typ, k.str = fKeyObjCreationEpoch, ""
case v2acl.FilterObjectPayloadLength:
k.typ, k.str = fKeyObjPayloadLength, ""
case v2acl.FilterObjectPayloadHash:
k.typ, k.str = fKeyObjPayloadHash, ""
case v2acl.FilterObjectType:
k.typ, k.str = fKeyObjType, ""
case v2acl.FilterObjectHomomorphicHash:
k.typ, k.str = fKeyObjHomomorphicHash, ""
}
}

// NewFilter creates, initializes and returns blank Filter instance.
//
// Defaults:
Expand All @@ -168,7 +108,7 @@ func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter {

f.from = FilterHeaderTypeFromV2(filter.GetHeaderType())
f.matcher = MatchFromV2(filter.GetMatchType())
f.key.fromString(filter.GetKey())
f.key = filter.GetKey()
f.value = staticStringer(filter.GetValue())

return f
Expand Down
34 changes: 6 additions & 28 deletions eacl/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package eacl

import (
"bytes"
"strconv"
"testing"

"github.com/nspcc-dev/neofs-api-go/v2/acl"
Expand All @@ -12,10 +11,8 @@ import (

func newObjectFilter(match Match, key, val string) *Filter {
return &Filter{
from: HeaderFromObject,
key: filterKey{
str: key,
},
from: HeaderFromObject,
key: key,
matcher: match,
value: staticStringer(val),
}
Expand Down Expand Up @@ -87,30 +84,14 @@ func TestFilter_ToV2(t *testing.T) {
require.Equal(t, acl.HeaderTypeUnknown, filterV2.GetHeaderType())
require.Equal(t, acl.MatchTypeUnknown, filterV2.GetMatchType())
})

t.Run("reserved types", func(t *testing.T) {
r := NewRecord()
for i := filterKeyType(1); i < fKeyObjLast; i++ {
r.addObjectReservedFilter(MatchStringEqual, i, staticStringer(strconv.FormatUint(uint64(i), 16)))
}

for i := range r.filters {
fv2 := r.filters[i].ToV2()
actual := NewFilterFromV2(fv2)
require.Equal(t, actual, &r.filters[i])
}
})
}

func TestFilter_CopyTo(t *testing.T) {
var filter Filter
filter.value = staticStringer("value")
filter.from = 1
filter.matcher = 1
filter.key = filterKey{
typ: 1,
str: "1",
}
filter.key = "1"

var dst Filter
t.Run("copy", func(t *testing.T) {
Expand All @@ -130,19 +111,16 @@ func TestFilter_CopyTo(t *testing.T) {
require.Equal(t, filter.value, dst.value)
require.Equal(t, filter.from, dst.from)
require.Equal(t, filter.matcher, dst.matcher)
require.Equal(t, filter.key.typ, dst.key.typ)
require.Equal(t, filter.key.str, dst.key.str)
require.Equal(t, filter.key, dst.key)

dst.value = staticStringer("value2")
dst.from = 2
dst.matcher = 2
dst.key.typ = 2
dst.key.str = "2"
dst.key = "2"

require.NotEqual(t, filter.value, dst.value)
require.NotEqual(t, filter.from, dst.from)
require.NotEqual(t, filter.matcher, dst.matcher)
require.NotEqual(t, filter.key.typ, dst.key.typ)
require.NotEqual(t, filter.key.str, dst.key.str)
require.NotEqual(t, filter.key, dst.key)
})
}
39 changes: 16 additions & 23 deletions eacl/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,105 +100,98 @@ type stringEncoder interface {
EncodeToString() string
}

func (r *Record) addFilter(from FilterHeaderType, m Match, keyTyp filterKeyType, key string, val stringEncoder) {
func (r *Record) addFilter(from FilterHeaderType, m Match, key string, val stringEncoder) {
filter := Filter{
from: from,
key: filterKey{
typ: keyTyp,
str: key,
},
from: from,
key: key,
matcher: m,
value: val,
}

r.filters = append(r.filters, filter)
}

func (r *Record) addObjectFilter(m Match, keyTyp filterKeyType, key string, val stringEncoder) {
r.addFilter(HeaderFromObject, m, keyTyp, key, val)
}

func (r *Record) addObjectReservedFilter(m Match, typ filterKeyType, val stringEncoder) {
r.addObjectFilter(m, typ, "", val)
func (r *Record) addObjectFilter(m Match, key string, val stringEncoder) {
r.addFilter(HeaderFromObject, m, key, val)
}

// AddFilter adds generic filter.
//
// If matcher is [MatchNotPresent], the value must be empty. If matcher is
// numeric (e.g. [MatchNumGT]), value must be a base-10 integer.
func (r *Record) AddFilter(from FilterHeaderType, matcher Match, name, value string) {
r.addFilter(from, matcher, 0, name, staticStringer(value))
r.addFilter(from, matcher, name, staticStringer(value))
}

// AddObjectAttributeFilter adds filter by object attribute.
//
// If m is [MatchNotPresent], the value must be empty. If matcher is numeric
// (e.g. [MatchNumGT]), value must be a base-10 integer.
func (r *Record) AddObjectAttributeFilter(m Match, key, value string) {
r.addObjectFilter(m, 0, key, staticStringer(value))
r.addObjectFilter(m, key, staticStringer(value))
}

// AddObjectVersionFilter adds filter by object version.
//
// The m must not be [MatchNotPresent] or numeric (e.g. [MatchNumGT]).
func (r *Record) AddObjectVersionFilter(m Match, v *version.Version) {
r.addObjectReservedFilter(m, fKeyObjVersion, staticStringer(version.EncodeToString(*v)))
r.addObjectFilter(m, FilterObjectVersion, staticStringer(version.EncodeToString(*v)))
}

// AddObjectIDFilter adds filter by object ID.
//
// The m must not be [MatchNotPresent] or numeric (e.g. [MatchNumGT]).
func (r *Record) AddObjectIDFilter(m Match, id oid.ID) {
r.addObjectReservedFilter(m, fKeyObjID, id)
r.addObjectFilter(m, FilterObjectID, id)
}

// AddObjectContainerIDFilter adds filter by object container ID.
//
// The m must not be [MatchNotPresent] or numeric (e.g. [MatchNumGT]).
func (r *Record) AddObjectContainerIDFilter(m Match, id cid.ID) {
r.addObjectReservedFilter(m, fKeyObjContainerID, id)
r.addObjectFilter(m, FilterObjectContainerID, id)
}

// AddObjectOwnerIDFilter adds filter by object owner ID.
//
// The m must not be [MatchNotPresent] or numeric (e.g. [MatchNumGT]).
func (r *Record) AddObjectOwnerIDFilter(m Match, id *user.ID) {
r.addObjectReservedFilter(m, fKeyObjOwnerID, id)
r.addObjectFilter(m, FilterObjectOwnerID, id)
}

// AddObjectCreationEpoch adds filter by object creation epoch.
//
// The m must not be [MatchNotPresent].
func (r *Record) AddObjectCreationEpoch(m Match, epoch uint64) {
r.addObjectReservedFilter(m, fKeyObjCreationEpoch, u64Stringer(epoch))
r.addObjectFilter(m, FilterObjectCreationEpoch, u64Stringer(epoch))
}

// AddObjectPayloadLengthFilter adds filter by object payload length.
//
// The m must not be [MatchNotPresent].
func (r *Record) AddObjectPayloadLengthFilter(m Match, size uint64) {
r.addObjectReservedFilter(m, fKeyObjPayloadLength, u64Stringer(size))
r.addObjectFilter(m, FilterObjectPayloadSize, u64Stringer(size))
}

// AddObjectPayloadHashFilter adds filter by object payload hash value.
//
// The m must not be [MatchNotPresent] or numeric (e.g. [MatchNumGT]).
func (r *Record) AddObjectPayloadHashFilter(m Match, h checksum.Checksum) {
r.addObjectReservedFilter(m, fKeyObjPayloadHash, staticStringer(h.String()))
r.addObjectFilter(m, FilterObjectPayloadChecksum, staticStringer(h.String()))
}

// AddObjectTypeFilter adds filter by object type.
//
// The m must not be [MatchNotPresent] or numeric (e.g. [MatchNumGT]).
func (r *Record) AddObjectTypeFilter(m Match, t object.Type) {
r.addObjectReservedFilter(m, fKeyObjType, staticStringer(t.EncodeToString()))
r.addObjectFilter(m, FilterObjectType, staticStringer(t.EncodeToString()))
}

// AddObjectHomomorphicHashFilter adds filter by object payload homomorphic hash value.
//
// The m must not be [MatchNotPresent] or numeric (e.g. [MatchNumGT]).
func (r *Record) AddObjectHomomorphicHashFilter(m Match, h checksum.Checksum) {
r.addObjectReservedFilter(m, fKeyObjHomomorphicHash, staticStringer(h.String()))
r.addObjectFilter(m, FilterObjectPayloadHomomorphicChecksum, staticStringer(h.String()))
}

// ToV2 converts Record to v2 acl.EACLRecord message.
Expand Down
9 changes: 3 additions & 6 deletions eacl/record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,20 +286,17 @@ func TestRecord_CopyTo(t *testing.T) {
var dst Record
record.CopyTo(&dst)

require.Equal(t, record.filters[0].key.str, dst.filters[0].key.str)
require.Equal(t, record.filters[0].key.typ, dst.filters[0].key.typ)
require.Equal(t, record.filters[0].key, dst.filters[0].key)
require.Equal(t, record.filters[0].matcher, dst.filters[0].matcher)
require.Equal(t, record.filters[0].value, dst.filters[0].value)
require.Equal(t, record.filters[0].from, dst.filters[0].from)

dst.filters[0].key.str = "key2"
dst.filters[0].key.typ = 12345
dst.filters[0].key = "key2"
dst.filters[0].matcher = MatchStringNotEqual
dst.filters[0].value = staticStringer("staticStringer")
dst.filters[0].from = 12345

require.NotEqual(t, record.filters[0].key.str, dst.filters[0].key.str)
require.NotEqual(t, record.filters[0].key.typ, dst.filters[0].key.typ)
require.NotEqual(t, record.filters[0].key, dst.filters[0].key)
require.NotEqual(t, record.filters[0].matcher, dst.filters[0].matcher)
require.NotEqual(t, record.filters[0].value, dst.filters[0].value)
require.NotEqual(t, record.filters[0].from, dst.filters[0].from)
Expand Down

0 comments on commit f761ba3

Please sign in to comment.