From 1ddc98dc750cb886d2c4337b68c65d6928c7bcd2 Mon Sep 17 00:00:00 2001
From: Alex Vanin <alexey@nspcc.ru>
Date: Wed, 25 Aug 2021 14:11:35 +0300
Subject: [PATCH] [#333] pkg/acl: Add remaining well-known eACL filter setters

Signed-off-by: Alex Vanin <alexey@nspcc.ru>
---
 pkg/acl/eacl/filter.go      |   7 +++
 pkg/acl/eacl/record.go      |  31 ++++++++++-
 pkg/acl/eacl/record_test.go | 103 ++++++++++++++++++++++++++++++++++++
 3 files changed, 140 insertions(+), 1 deletion(-)

diff --git a/pkg/acl/eacl/filter.go b/pkg/acl/eacl/filter.go
index 03c093e4..23e76777 100644
--- a/pkg/acl/eacl/filter.go
+++ b/pkg/acl/eacl/filter.go
@@ -2,6 +2,7 @@ package eacl
 
 import (
 	"fmt"
+	"strconv"
 
 	v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl"
 )
@@ -19,6 +20,8 @@ type Filter struct {
 
 type staticStringer string
 
+type u64Stringer uint64
+
 type filterKey struct {
 	typ filterKeyType
 
@@ -45,6 +48,10 @@ func (s staticStringer) String() string {
 	return string(s)
 }
 
+func (u u64Stringer) String() string {
+	return strconv.FormatUint(uint64(u), 10)
+}
+
 // Value returns filtered string value.
 func (f Filter) Value() string {
 	return f.value.String()
diff --git a/pkg/acl/eacl/record.go b/pkg/acl/eacl/record.go
index 7ba97433..b12d52aa 100644
--- a/pkg/acl/eacl/record.go
+++ b/pkg/acl/eacl/record.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/nspcc-dev/neofs-api-go/pkg"
 	cid "github.com/nspcc-dev/neofs-api-go/pkg/container/id"
+	"github.com/nspcc-dev/neofs-api-go/pkg/object"
 	"github.com/nspcc-dev/neofs-api-go/pkg/owner"
 	v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl"
 )
@@ -115,6 +116,11 @@ func (r *Record) AddObjectVersionFilter(m Match, v *pkg.Version) {
 	r.addObjectReservedFilter(m, fKeyObjVersion, v)
 }
 
+// AddObjectIDFilter adds filter by object ID.
+func (r *Record) AddObjectIDFilter(m Match, id *object.ID) {
+	r.addObjectReservedFilter(m, fKeyObjID, id)
+}
+
 // AddObjectContainerIDFilter adds filter by object container ID.
 func (r *Record) AddObjectContainerIDFilter(m Match, id *cid.ID) {
 	r.addObjectReservedFilter(m, fKeyObjContainerID, id)
@@ -125,7 +131,30 @@ func (r *Record) AddObjectOwnerIDFilter(m Match, id *owner.ID) {
 	r.addObjectReservedFilter(m, fKeyObjOwnerID, id)
 }
 
-// TODO: add remaining filters after neofs-api#72
+// AddObjectCreationEpoch adds filter by object creation epoch.
+func (r *Record) AddObjectCreationEpoch(m Match, epoch uint64) {
+	r.addObjectReservedFilter(m, fKeyObjCreationEpoch, u64Stringer(epoch))
+}
+
+// AddObjectPayloadLengthFilter adds filter by object payload length.
+func (r *Record) AddObjectPayloadLengthFilter(m Match, size uint64) {
+	r.addObjectReservedFilter(m, fKeyObjPayloadLength, u64Stringer(size))
+}
+
+// AddObjectPayloadHashFilter adds filter by object payload hash value.
+func (r *Record) AddObjectPayloadHashFilter(m Match, h *pkg.Checksum) {
+	r.addObjectReservedFilter(m, fKeyObjPayloadHash, h)
+}
+
+// AddObjectTypeFilter adds filter by object type.
+func (r *Record) AddObjectTypeFilter(m Match, t object.Type) {
+	r.addObjectReservedFilter(m, fKeyObjType, t)
+}
+
+// AddObjectHomomorphicHashFilter adds filter by object payload homomorphic hash value.
+func (r *Record) AddObjectHomomorphicHashFilter(m Match, h *pkg.Checksum) {
+	r.addObjectReservedFilter(m, fKeyObjHomomorphicHash, h)
+}
 
 // ToV2 converts Record to v2 acl.EACLRecord message.
 //
diff --git a/pkg/acl/eacl/record_test.go b/pkg/acl/eacl/record_test.go
index 7ed59dd0..1baaf4ac 100644
--- a/pkg/acl/eacl/record_test.go
+++ b/pkg/acl/eacl/record_test.go
@@ -2,8 +2,14 @@ package eacl
 
 import (
 	"crypto/ecdsa"
+	"fmt"
 	"testing"
 
+	cidtest "github.com/nspcc-dev/neofs-api-go/pkg/container/id/test"
+	"github.com/nspcc-dev/neofs-api-go/pkg/object"
+	objecttest "github.com/nspcc-dev/neofs-api-go/pkg/object/test"
+	ownertest "github.com/nspcc-dev/neofs-api-go/pkg/owner/test"
+	refstest "github.com/nspcc-dev/neofs-api-go/pkg/test"
 	v2acl "github.com/nspcc-dev/neofs-api-go/v2/acl"
 	"github.com/nspcc-dev/neofs-crypto/test"
 	"github.com/stretchr/testify/require"
@@ -145,3 +151,100 @@ func TestRecord_ToV2(t *testing.T) {
 		require.Nil(t, recordV2.GetFilters())
 	})
 }
+
+func TestReservedRecords(t *testing.T) {
+	var (
+		v       = refstest.Version()
+		oid     = objecttest.ID()
+		cid     = cidtest.Generate()
+		ownerid = ownertest.Generate()
+		h       = refstest.Checksum()
+		typ     = new(object.Type)
+	)
+
+	testSuit := []struct {
+		f     func(r *Record)
+		key   string
+		value string
+	}{
+		{
+			f:     func(r *Record) { r.AddObjectAttributeFilter(MatchStringEqual, "foo", "bar") },
+			key:   "foo",
+			value: "bar",
+		},
+		{
+			f:     func(r *Record) { r.AddObjectVersionFilter(MatchStringEqual, v) },
+			key:   v2acl.FilterObjectVersion,
+			value: v.String(),
+		},
+		{
+			f:     func(r *Record) { r.AddObjectIDFilter(MatchStringEqual, oid) },
+			key:   v2acl.FilterObjectID,
+			value: oid.String(),
+		},
+		{
+			f:     func(r *Record) { r.AddObjectContainerIDFilter(MatchStringEqual, cid) },
+			key:   v2acl.FilterObjectContainerID,
+			value: cid.String(),
+		},
+		{
+			f:     func(r *Record) { r.AddObjectOwnerIDFilter(MatchStringEqual, ownerid) },
+			key:   v2acl.FilterObjectOwnerID,
+			value: ownerid.String(),
+		},
+		{
+			f:     func(r *Record) { r.AddObjectCreationEpoch(MatchStringEqual, 100) },
+			key:   v2acl.FilterObjectCreationEpoch,
+			value: "100",
+		},
+		{
+			f:     func(r *Record) { r.AddObjectPayloadLengthFilter(MatchStringEqual, 5000) },
+			key:   v2acl.FilterObjectPayloadLength,
+			value: "5000",
+		},
+		{
+			f:     func(r *Record) { r.AddObjectPayloadHashFilter(MatchStringEqual, h) },
+			key:   v2acl.FilterObjectPayloadHash,
+			value: h.String(),
+		},
+		{
+			f:     func(r *Record) { r.AddObjectHomomorphicHashFilter(MatchStringEqual, h) },
+			key:   v2acl.FilterObjectHomomorphicHash,
+			value: h.String(),
+		},
+		{
+			f: func(r *Record) {
+				require.True(t, typ.FromString("REGULAR"))
+				r.AddObjectTypeFilter(MatchStringEqual, *typ)
+			},
+			key:   v2acl.FilterObjectType,
+			value: "REGULAR",
+		},
+		{
+			f: func(r *Record) {
+				require.True(t, typ.FromString("TOMBSTONE"))
+				r.AddObjectTypeFilter(MatchStringEqual, *typ)
+			},
+			key:   v2acl.FilterObjectType,
+			value: "TOMBSTONE",
+		},
+		{
+			f: func(r *Record) {
+				require.True(t, typ.FromString("STORAGE_GROUP"))
+				r.AddObjectTypeFilter(MatchStringEqual, *typ)
+			},
+			key:   v2acl.FilterObjectType,
+			value: "STORAGE_GROUP",
+		},
+	}
+
+	for n, testCase := range testSuit {
+		desc := fmt.Sprintf("case #%d", n)
+		record := NewRecord()
+		testCase.f(record)
+		require.Len(t, record.Filters(), 1, desc)
+		f := record.Filters()[0]
+		require.Equal(t, f.Key(), testCase.key, desc)
+		require.Equal(t, f.Value(), testCase.value, desc)
+	}
+}