2021-11-08 14:29:54 +00:00
|
|
|
package eacl
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strconv"
|
|
|
|
|
2023-03-07 11:20:03 +00:00
|
|
|
v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl"
|
2021-11-08 14:29:54 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Filter defines check conditions if request header is matched or not. Matched
|
2022-02-17 16:10:49 +00:00
|
|
|
// header means that request should be processed according to ContainerEACL action.
|
2021-11-08 14:29:54 +00:00
|
|
|
//
|
|
|
|
// Filter is compatible with v2 acl.EACLRecord.Filter message.
|
|
|
|
type Filter struct {
|
|
|
|
from FilterHeaderType
|
|
|
|
matcher Match
|
|
|
|
key filterKey
|
2022-05-31 06:55:08 +00:00
|
|
|
value stringEncoder
|
2021-11-08 14:29:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type staticStringer string
|
|
|
|
|
|
|
|
type u64Stringer uint64
|
|
|
|
|
|
|
|
type filterKey struct {
|
|
|
|
typ filterKeyType
|
|
|
|
|
|
|
|
str string
|
|
|
|
}
|
|
|
|
|
|
|
|
// enumeration of reserved filter keys.
|
|
|
|
type filterKeyType int
|
|
|
|
|
|
|
|
const (
|
|
|
|
_ filterKeyType = iota
|
|
|
|
fKeyObjVersion
|
|
|
|
fKeyObjID
|
|
|
|
fKeyObjContainerID
|
|
|
|
fKeyObjOwnerID
|
|
|
|
fKeyObjCreationEpoch
|
|
|
|
fKeyObjPayloadLength
|
|
|
|
fKeyObjPayloadHash
|
|
|
|
fKeyObjType
|
|
|
|
fKeyObjHomomorphicHash
|
2022-06-08 09:16:30 +00:00
|
|
|
fKeyObjLast // helper, used in tests
|
2021-11-08 14:29:54 +00:00
|
|
|
)
|
|
|
|
|
2022-05-31 06:55:08 +00:00
|
|
|
func (s staticStringer) EncodeToString() string {
|
2021-11-08 14:29:54 +00:00
|
|
|
return string(s)
|
|
|
|
}
|
|
|
|
|
2022-05-31 06:55:08 +00:00
|
|
|
func (u u64Stringer) EncodeToString() string {
|
2021-11-08 14:29:54 +00:00
|
|
|
return strconv.FormatUint(uint64(u), 10)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Value returns filtered string value.
|
|
|
|
func (f Filter) Value() string {
|
2022-05-31 06:55:08 +00:00
|
|
|
return f.value.EncodeToString()
|
2021-11-08 14:29:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Matcher returns filter Match type.
|
|
|
|
func (f Filter) Matcher() Match {
|
|
|
|
return f.matcher
|
|
|
|
}
|
|
|
|
|
|
|
|
// Key returns key to the filtered header.
|
|
|
|
func (f Filter) Key() string {
|
|
|
|
return f.key.String()
|
|
|
|
}
|
|
|
|
|
|
|
|
// From returns FilterHeaderType that defined which header will be filtered.
|
|
|
|
func (f Filter) From() FilterHeaderType {
|
|
|
|
return f.from
|
|
|
|
}
|
|
|
|
|
|
|
|
// ToV2 converts Filter to v2 acl.EACLRecord.Filter message.
|
|
|
|
//
|
|
|
|
// Nil Filter converts to nil.
|
|
|
|
func (f *Filter) ToV2() *v2acl.HeaderFilter {
|
|
|
|
if f == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
filter := new(v2acl.HeaderFilter)
|
2022-05-31 06:55:08 +00:00
|
|
|
filter.SetValue(f.value.EncodeToString())
|
2021-11-08 14:29:54 +00:00
|
|
|
filter.SetKey(f.key.String())
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-08 09:16:30 +00:00
|
|
|
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, ""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-08 14:29:54 +00:00
|
|
|
// NewFilter creates, initializes and returns blank Filter instance.
|
|
|
|
//
|
|
|
|
// Defaults:
|
2022-08-24 14:17:40 +00:00
|
|
|
// - header type: HeaderTypeUnknown;
|
|
|
|
// - matcher: MatchUnknown;
|
|
|
|
// - key: "";
|
|
|
|
// - value: "".
|
2021-11-08 14:29:54 +00:00
|
|
|
func NewFilter() *Filter {
|
|
|
|
return NewFilterFromV2(new(v2acl.HeaderFilter))
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewFilterFromV2 converts v2 acl.EACLRecord.Filter message to Filter.
|
|
|
|
func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter {
|
|
|
|
f := new(Filter)
|
|
|
|
|
|
|
|
if filter == nil {
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
|
|
|
|
f.from = FilterHeaderTypeFromV2(filter.GetHeaderType())
|
|
|
|
f.matcher = MatchFromV2(filter.GetMatchType())
|
2022-06-08 09:16:30 +00:00
|
|
|
f.key.fromString(filter.GetKey())
|
2021-11-08 14:29:54 +00:00
|
|
|
f.value = staticStringer(filter.GetValue())
|
|
|
|
|
|
|
|
return f
|
|
|
|
}
|
|
|
|
|
|
|
|
// Marshal marshals Filter into a protobuf binary form.
|
|
|
|
func (f *Filter) Marshal() ([]byte, error) {
|
2022-05-30 19:05:35 +00:00
|
|
|
return f.ToV2().StableMarshal(nil), nil
|
2021-11-08 14:29:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Unmarshal unmarshals protobuf binary representation of Filter.
|
|
|
|
func (f *Filter) Unmarshal(data []byte) error {
|
|
|
|
fV2 := new(v2acl.HeaderFilter)
|
|
|
|
if err := fV2.Unmarshal(data); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*f = *NewFilterFromV2(fV2)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MarshalJSON encodes Filter to protobuf JSON format.
|
|
|
|
func (f *Filter) MarshalJSON() ([]byte, error) {
|
|
|
|
return f.ToV2().MarshalJSON()
|
|
|
|
}
|
|
|
|
|
|
|
|
// UnmarshalJSON decodes Filter from protobuf JSON format.
|
|
|
|
func (f *Filter) UnmarshalJSON(data []byte) error {
|
|
|
|
fV2 := new(v2acl.HeaderFilter)
|
|
|
|
if err := fV2.UnmarshalJSON(data); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
*f = *NewFilterFromV2(fV2)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2022-03-28 08:15:52 +00:00
|
|
|
|
|
|
|
// equalFilters compares Filter with each other.
|
|
|
|
func equalFilters(f1, f2 Filter) bool {
|
|
|
|
return f1.From() == f2.From() &&
|
|
|
|
f1.Matcher() == f2.Matcher() &&
|
|
|
|
f1.Key() == f2.Key() &&
|
|
|
|
f1.Value() == f2.Value()
|
|
|
|
}
|