git.frostfs.info/TrueCloudLab/frostfs-sdk-go@v0.0.0-20241022124111-5361f0ecebd3/eacl/filter.go (about) 1 package eacl 2 3 import ( 4 "strconv" 5 6 v2acl "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/acl" 7 ) 8 9 // Filter defines check conditions if request header is matched or not. Matched 10 // header means that request should be processed according to ContainerEACL action. 11 // 12 // Filter is compatible with v2 acl.EACLRecord.Filter message. 13 type Filter struct { 14 from FilterHeaderType 15 matcher Match 16 key filterKey 17 value stringEncoder 18 } 19 20 type staticStringer string 21 22 type u64Stringer uint64 23 24 type filterKey struct { 25 typ filterKeyType 26 27 str string 28 } 29 30 // enumeration of reserved filter keys. 31 type filterKeyType int 32 33 const ( 34 _ filterKeyType = iota 35 fKeyObjVersion 36 fKeyObjID 37 fKeyObjContainerID 38 fKeyObjOwnerID 39 fKeyObjCreationEpoch 40 fKeyObjPayloadLength 41 fKeyObjPayloadHash 42 fKeyObjType 43 fKeyObjHomomorphicHash 44 fKeyObjLast // helper, used in tests 45 ) 46 47 func (s staticStringer) EncodeToString() string { 48 return string(s) 49 } 50 51 func (u u64Stringer) EncodeToString() string { 52 return strconv.FormatUint(uint64(u), 10) 53 } 54 55 // Value returns filtered string value. 56 func (f Filter) Value() string { 57 return f.value.EncodeToString() 58 } 59 60 // Matcher returns filter Match type. 61 func (f Filter) Matcher() Match { 62 return f.matcher 63 } 64 65 // Key returns key to the filtered header. 66 func (f Filter) Key() string { 67 return f.key.String() 68 } 69 70 // From returns FilterHeaderType that defined which header will be filtered. 71 func (f Filter) From() FilterHeaderType { 72 return f.from 73 } 74 75 // ToV2 converts Filter to v2 acl.EACLRecord.Filter message. 76 // 77 // Nil Filter converts to nil. 78 func (f *Filter) ToV2() *v2acl.HeaderFilter { 79 if f == nil { 80 return nil 81 } 82 83 filter := new(v2acl.HeaderFilter) 84 filter.SetValue(f.value.EncodeToString()) 85 filter.SetKey(f.key.String()) 86 filter.SetMatchType(f.matcher.ToV2()) 87 filter.SetHeaderType(f.from.ToV2()) 88 89 return filter 90 } 91 92 func (k filterKey) String() string { 93 switch k.typ { 94 default: 95 return k.str 96 case fKeyObjVersion: 97 return v2acl.FilterObjectVersion 98 case fKeyObjID: 99 return v2acl.FilterObjectID 100 case fKeyObjContainerID: 101 return v2acl.FilterObjectContainerID 102 case fKeyObjOwnerID: 103 return v2acl.FilterObjectOwnerID 104 case fKeyObjCreationEpoch: 105 return v2acl.FilterObjectCreationEpoch 106 case fKeyObjPayloadLength: 107 return v2acl.FilterObjectPayloadLength 108 case fKeyObjPayloadHash: 109 return v2acl.FilterObjectPayloadHash 110 case fKeyObjType: 111 return v2acl.FilterObjectType 112 case fKeyObjHomomorphicHash: 113 return v2acl.FilterObjectHomomorphicHash 114 } 115 } 116 117 func (k *filterKey) fromString(s string) { 118 switch s { 119 default: 120 k.typ, k.str = 0, s 121 case v2acl.FilterObjectVersion: 122 k.typ, k.str = fKeyObjVersion, "" 123 case v2acl.FilterObjectID: 124 k.typ, k.str = fKeyObjID, "" 125 case v2acl.FilterObjectContainerID: 126 k.typ, k.str = fKeyObjContainerID, "" 127 case v2acl.FilterObjectOwnerID: 128 k.typ, k.str = fKeyObjOwnerID, "" 129 case v2acl.FilterObjectCreationEpoch: 130 k.typ, k.str = fKeyObjCreationEpoch, "" 131 case v2acl.FilterObjectPayloadLength: 132 k.typ, k.str = fKeyObjPayloadLength, "" 133 case v2acl.FilterObjectPayloadHash: 134 k.typ, k.str = fKeyObjPayloadHash, "" 135 case v2acl.FilterObjectType: 136 k.typ, k.str = fKeyObjType, "" 137 case v2acl.FilterObjectHomomorphicHash: 138 k.typ, k.str = fKeyObjHomomorphicHash, "" 139 } 140 } 141 142 // NewFilter creates, initializes and returns blank Filter instance. 143 // 144 // Defaults: 145 // - header type: HeaderTypeUnknown; 146 // - matcher: MatchUnknown; 147 // - key: ""; 148 // - value: "". 149 func NewFilter() *Filter { 150 return NewFilterFromV2(new(v2acl.HeaderFilter)) 151 } 152 153 // NewFilterFromV2 converts v2 acl.EACLRecord.Filter message to Filter. 154 func NewFilterFromV2(filter *v2acl.HeaderFilter) *Filter { 155 f := new(Filter) 156 157 if filter == nil { 158 return f 159 } 160 161 f.from = FilterHeaderTypeFromV2(filter.GetHeaderType()) 162 f.matcher = MatchFromV2(filter.GetMatchType()) 163 f.key.fromString(filter.GetKey()) 164 f.value = staticStringer(filter.GetValue()) 165 166 return f 167 } 168 169 // Marshal marshals Filter into a protobuf binary form. 170 func (f *Filter) Marshal() ([]byte, error) { 171 return f.ToV2().StableMarshal(nil), nil 172 } 173 174 // Unmarshal unmarshals protobuf binary representation of Filter. 175 func (f *Filter) Unmarshal(data []byte) error { 176 fV2 := new(v2acl.HeaderFilter) 177 if err := fV2.Unmarshal(data); err != nil { 178 return err 179 } 180 181 *f = *NewFilterFromV2(fV2) 182 183 return nil 184 } 185 186 // MarshalJSON encodes Filter to protobuf JSON format. 187 func (f *Filter) MarshalJSON() ([]byte, error) { 188 return f.ToV2().MarshalJSON() 189 } 190 191 // UnmarshalJSON decodes Filter from protobuf JSON format. 192 func (f *Filter) UnmarshalJSON(data []byte) error { 193 fV2 := new(v2acl.HeaderFilter) 194 if err := fV2.UnmarshalJSON(data); err != nil { 195 return err 196 } 197 198 *f = *NewFilterFromV2(fV2) 199 200 return nil 201 } 202 203 // equalFilters compares Filter with each other. 204 func equalFilters(f1, f2 Filter) bool { 205 return f1.From() == f2.From() && 206 f1.Matcher() == f2.Matcher() && 207 f1.Key() == f2.Key() && 208 f1.Value() == f2.Value() 209 }