diff --git a/acl/extended/enum.go b/acl/extended/enum.go new file mode 100644 index 0000000..e803476 --- /dev/null +++ b/acl/extended/enum.go @@ -0,0 +1,126 @@ +package eacl + +const ( + // MatchUnknown is a MatchType value used to mark value as undefined. + // Most of the tools consider MatchUnknown as incalculable. + // Using MatchUnknown in HeaderFilter is unsafe. + MatchUnknown MatchType = iota + + // StringEqual is a MatchType of string equality. + StringEqual + + // StringNotEqual is a MatchType of string inequality. + StringNotEqual +) + +const ( + // ActionUnknown is Action used to mark value as undefined. + // Most of the tools consider ActionUnknown as incalculable. + // Using ActionUnknown in Record is unsafe. + ActionUnknown Action = iota + + // ActionAllow is Action used to mark an applicability of ACL rule. + ActionAllow + + // ActionDeny is Action used to mark an inapplicability of ACL rule. + ActionDeny +) + +const ( + // GroupUnknown is a Group value used to mark value as undefined. + // Most of the tools consider GroupUnknown as incalculable. + // Using GroupUnknown in Target is unsafe. + GroupUnknown Group = iota + + // GroupUser is a Group value for User access group. + GroupUser + + // GroupSystem is a Group value for System access group. + GroupSystem + + // GroupOthers is a Group value for Others access group. + GroupOthers +) + +const ( + // HdrTypeUnknown is a HeaderType value used to mark value as undefined. + // Most of the tools consider HdrTypeUnknown as incalculable. + // Using HdrTypeUnknown in HeaderFilter is unsafe. + HdrTypeUnknown HeaderType = iota + + // HdrTypeRequest is a HeaderType for request header. + HdrTypeRequest + + // HdrTypeObjSys is a HeaderType for system headers of object. + HdrTypeObjSys + + // HdrTypeObjUsr is a HeaderType for user headers of object. + HdrTypeObjUsr +) + +const ( + // OpTypeUnknown is a OperationType value used to mark value as undefined. + // Most of the tools consider OpTypeUnknown as incalculable. + // Using OpTypeUnknown in Record is unsafe. + OpTypeUnknown OperationType = iota + + // OpTypeGet is an OperationType for object.Get RPC + OpTypeGet + + // OpTypePut is an OperationType for object.Put RPC + OpTypePut + + // OpTypeHead is an OperationType for object.Head RPC + OpTypeHead + + // OpTypeSearch is an OperationType for object.Search RPC + OpTypeSearch + + // OpTypeDelete is an OperationType for object.Delete RPC + OpTypeDelete + + // OpTypeRange is an OperationType for object.GetRange RPC + OpTypeRange + + // OpTypeRangeHash is an OperationType for object.GetRangeHash RPC + OpTypeRangeHash +) + +const ( + // HdrObjSysNameID is a name of ID field in system header of object. + HdrObjSysNameID = "ID" + + // HdrObjSysNameCID is a name of CID field in system header of object. + HdrObjSysNameCID = "CID" + + // HdrObjSysNameOwnerID is a name of OwnerID field in system header of object. + HdrObjSysNameOwnerID = "OWNER_ID" + + // HdrObjSysNameVersion is a name of Version field in system header of object. + HdrObjSysNameVersion = "VERSION" + + // HdrObjSysNamePayloadLength is a name of PayloadLength field in system header of object. + HdrObjSysNamePayloadLength = "PAYLOAD_LENGTH" + + // HdrObjSysNameCreatedUnix is a name of CreatedAt.UnitTime field in system header of object. + HdrObjSysNameCreatedUnix = "CREATED_UNIX" + + // HdrObjSysNameCreatedEpoch is a name of CreatedAt.Epoch field in system header of object. + HdrObjSysNameCreatedEpoch = "CREATED_EPOCH" + + // HdrObjSysLinkPrev is a name of previous link header in extended headers of object. + HdrObjSysLinkPrev = "LINK_PREV" + + // HdrObjSysLinkNext is a name of next link header in extended headers of object. + HdrObjSysLinkNext = "LINK_NEXT" + + // HdrObjSysLinkChild is a name of child link header in extended headers of object. + HdrObjSysLinkChild = "LINK_CHILD" + + // HdrObjSysLinkPar is a name of parent link header in extended headers of object. + HdrObjSysLinkPar = "LINK_PAR" + + // HdrObjSysLinkSG is a name of storage group link header in extended headers of object. + HdrObjSysLinkSG = "LINK_SG" +) + diff --git a/acl/extended/marshal.go b/acl/extended/marshal.go new file mode 100644 index 0000000..d1fac07 --- /dev/null +++ b/acl/extended/marshal.go @@ -0,0 +1,333 @@ +package eacl + +import ( + "encoding/binary" + + "github.com/pkg/errors" +) + +const ( + sliceLenSize = 2 // uint16 for len() + actionSize = 4 // uint32 + opTypeSize = 4 // uint32 + hdrTypeSize = 4 // uint32 + matchTypeSize = 4 // uint32 + targetSize = 4 // uint32 +) + +// MarshalTable encodes Table into a +// binary form and returns the result. +// +// If table is nil, empty slice is returned. +func MarshalTable(table Table) []byte { + if table == nil { + return make([]byte, 0) + } + + // allocate buffer + buf := make([]byte, tableBinSize(table)) + + records := table.Records() + + // write record number + binary.BigEndian.PutUint16(buf, uint16(len(records))) + off := sliceLenSize + + // write all records + for _, record := range records { + // write action + binary.BigEndian.PutUint32(buf[off:], uint32(record.Action())) + off += actionSize + + // write operation type + binary.BigEndian.PutUint32(buf[off:], uint32(record.OperationType())) + off += actionSize + + filters := record.HeaderFilters() + + // write filter number + binary.BigEndian.PutUint16(buf[off:], uint16(len(filters))) + off += sliceLenSize + + // write all filters + for _, filter := range filters { + // write header type + binary.BigEndian.PutUint32(buf[off:], uint32(filter.HeaderType())) + off += hdrTypeSize + + // write match type + binary.BigEndian.PutUint32(buf[off:], uint32(filter.MatchType())) + off += matchTypeSize + + // write header name size + name := []byte(filter.Name()) + binary.BigEndian.PutUint16(buf[off:], uint16(len(name))) + off += sliceLenSize + + // write header name bytes + off += copy(buf[off:], name) + + // write header value size + val := []byte(filter.Value()) + binary.BigEndian.PutUint16(buf[off:], uint16(len(val))) + off += sliceLenSize + + // write header value bytes + off += copy(buf[off:], val) + } + + targets := record.TargetList() + + // write target number + binary.BigEndian.PutUint16(buf[off:], uint16(len(targets))) + off += sliceLenSize + + // write all targets + for _, target := range targets { + // write target group + binary.BigEndian.PutUint32(buf[off:], uint32(target.Group())) + off += targetSize + + keys := target.KeyList() + + // write key number + binary.BigEndian.PutUint16(buf[off:], uint16(len(keys))) + off += sliceLenSize + + // write keys + for i := range keys { + // write key size + binary.BigEndian.PutUint16(buf[off:], uint16(len(keys[i]))) + off += sliceLenSize + + // write key bytes + off += copy(buf[off:], keys[i]) + } + } + } + + return buf +} + +// returns the size of Table in a binary format. +func tableBinSize(table Table) (sz int) { + sz = sliceLenSize // number of records + + records := table.Records() + ln := len(records) + + sz += ln * actionSize // action type of each record + sz += ln * opTypeSize // operation type of each record + + for _, record := range records { + sz += sliceLenSize // number of filters + + filters := record.HeaderFilters() + ln := len(filters) + + sz += ln * hdrTypeSize // header type of each filter + sz += ln * matchTypeSize // match type of each filter + + for _, filter := range filters { + sz += sliceLenSize // header name size + sz += len(filter.Name()) // header name bytes + + sz += sliceLenSize // header value size + sz += len(filter.Value()) // header value bytes + } + + sz += sliceLenSize // number of targets + + targets := record.TargetList() + ln = len(targets) + + sz += ln * targetSize // target group of each target + + for _, target := range targets { + sz += sliceLenSize // number of keys + + for _, key := range target.KeyList() { + sz += sliceLenSize // key size + sz += len(key) // key bytes + } + } + } + + return +} + +// UnmarshalTable unmarshals Table from +// a binary representation. +// +// If data is empty, table w/o records is returned. +func UnmarshalTable(data []byte) (Table, error) { + table := WrapTable(nil) + + if len(data) == 0 { + return table, nil + } + + // decode record number + if len(data) < sliceLenSize { + return nil, errors.New("could not decode record number") + } + + recordNum := binary.BigEndian.Uint16(data) + records := make([]Record, 0, recordNum) + + off := sliceLenSize + + // decode all records one by one + for i := uint16(0); i < recordNum; i++ { + record := WrapRecord(nil) + + // decode action + if len(data[off:]) < actionSize { + return nil, errors.Errorf("could not decode action of record #%d", i) + } + + record.SetAction(Action(binary.BigEndian.Uint32(data[off:]))) + off += actionSize + + // decode operation type + if len(data[off:]) < opTypeSize { + return nil, errors.Errorf("could not decode operation type of record #%d", i) + } + + record.SetOperationType(OperationType(binary.BigEndian.Uint32(data[off:]))) + off += opTypeSize + + // decode filter number + if len(data[off:]) < sliceLenSize { + return nil, errors.Errorf("could not decode filter number of record #%d", i) + } + + filterNum := binary.BigEndian.Uint16(data[off:]) + off += sliceLenSize + filters := make([]HeaderFilter, 0, filterNum) + + // decode filters one by one + for j := uint16(0); j < filterNum; j++ { + filter := WrapFilterInfo(nil) + + // decode header type + if len(data[off:]) < hdrTypeSize { + return nil, errors.Errorf("could not decode header type of filter #%d of record #%d", j, i) + } + + filter.SetHeaderType(HeaderType(binary.BigEndian.Uint32(data[off:])) ) + off += hdrTypeSize + + // decode match type + if len(data[off:]) < matchTypeSize { + return nil, errors.Errorf("could not decode match type of filter #%d of record #%d", j, i) + } + + filter.SetMatchType(MatchType(binary.BigEndian.Uint32(data[off:])) ) + off += matchTypeSize + + // decode header name size + if len(data[off:]) < sliceLenSize { + return nil, errors.Errorf("could not decode header name size of filter #%d of record #%d", j, i) + } + + hdrNameSize := int(binary.BigEndian.Uint16(data[off:])) + off += sliceLenSize + + // decode header name + if len(data[off:]) < hdrNameSize { + return nil, errors.Errorf("could not decode header name of filter #%d of record #%d", j, i) + } + + filter.SetName(string(data[off : off+hdrNameSize])) + + off += hdrNameSize + + // decode header value size + if len(data[off:]) < sliceLenSize { + return nil, errors.Errorf("could not decode header value size of filter #%d of record #%d", j, i) + } + + hdrValSize := int(binary.BigEndian.Uint16(data[off:])) + off += sliceLenSize + + // decode header value + if len(data[off:]) < hdrValSize { + return nil, errors.Errorf("could not decode header value of filter #%d of record #%d", j, i) + } + + filter.SetValue(string(data[off : off+hdrValSize])) + + off += hdrValSize + + filters = append(filters, filter) + } + + record.SetHeaderFilters(filters) + + // decode target number + if len(data[off:]) < sliceLenSize { + return nil, errors.Errorf("could not decode target number of record #%d", i) + } + + targetNum := int(binary.BigEndian.Uint16(data[off:])) + off += sliceLenSize + + targets := make([]Target, 0, targetNum) + + // decode targets one by one + for j := 0; j < targetNum; j++ { + target := WrapTarget(nil) + + // decode target group + if len(data[off:]) < targetSize { + return nil, errors.Errorf("could not decode target group of target #%d of record #%d", j, i) + } + + target.SetGroup( Group(binary.BigEndian.Uint32(data[off:])), ) + off += targetSize + + // decode key number + if len(data[off:]) < sliceLenSize { + return nil, errors.Errorf("could not decode key number of target #%d of record #%d", j, i) + } + + keyNum := int(binary.BigEndian.Uint16(data[off:])) + off += sliceLenSize + keys := make([][]byte, 0, keyNum) + + for k := 0; k < keyNum; k++ { + // decode key size + if len(data[off:]) < sliceLenSize { + return nil, errors.Errorf("could not decode size of key #%d target #%d of record #%d", k, j, i) + } + + keySz := int(binary.BigEndian.Uint16(data[off:])) + off += sliceLenSize + + // decode key + if len(data[off:]) < keySz { + return nil, errors.Errorf("could not decode key #%d target #%d of record #%d", k, j, i) + } + + key := make([]byte, keySz) + + off += copy(key, data[off:off+keySz]) + + keys = append(keys, key) + } + + target.SetKeyList(keys) + + targets = append(targets, target) + } + + record.SetTargetList(targets) + + records = append(records, record) + } + + table.SetRecords(records) + + return table, nil +} diff --git a/acl/extended.go b/acl/extended/types.go similarity index 53% rename from acl/extended.go rename to acl/extended/types.go index df8402a..6b1b74b 100644 --- a/acl/extended.go +++ b/acl/extended/types.go @@ -1,4 +1,4 @@ -package acl +package eacl // OperationType is an enumeration of operation types for extended ACL. type OperationType uint32 @@ -9,8 +9,11 @@ type HeaderType uint32 // MatchType is an enumeration of match types for extended ACL. type MatchType uint32 -// ExtendedACLAction is an enumeration of extended ACL actions. -type ExtendedACLAction uint32 +// Action is an enumeration of extended ACL actions. +type Action uint32 + +// Group is an enumeration of access groups. +type Group uint32 // Header is an interface of string key-value pair, type Header interface { @@ -37,17 +40,17 @@ type HeaderFilter interface { TypedHeader } -// ExtendedACLTarget is an interface of grouped information about extended ACL rule target. -type ExtendedACLTarget interface { +// Target is an interface of grouped information about extended ACL rule target. +type Target interface { // Must return ACL target type. - Target() Target + Group() Group // Must return public key list of ACL targets. KeyList() [][]byte } -// ExtendedACLRecord is an interface of record of extended ACL rule table. -type ExtendedACLRecord interface { +// Record is an interface of record of extended ACL rule table. +type Record interface { // Must return operation type of extended ACL rule. OperationType() OperationType @@ -55,39 +58,16 @@ type ExtendedACLRecord interface { HeaderFilters() []HeaderFilter // Must return target list of extended ACL rule. - TargetList() []ExtendedACLTarget + TargetList() []Target // Must return action of extended ACL rule. - Action() ExtendedACLAction + Action() Action } -// ExtendedACLTable is an interface of extended ACL table. -type ExtendedACLTable interface { +// Table is an interface of extended ACL table. +type Table interface { // Must return list of extended ACL rules. - Records() []ExtendedACLRecord + Records() []Record } -const ( - _ OperationType = iota - // OpTypeGet is an OperationType for object.Get RPC - OpTypeGet - - // OpTypePut is an OperationType for object.Put RPC - OpTypePut - - // OpTypeHead is an OperationType for object.Head RPC - OpTypeHead - - // OpTypeSearch is an OperationType for object.Search RPC - OpTypeSearch - - // OpTypeDelete is an OperationType for object.Delete RPC - OpTypeDelete - - // OpTypeRange is an OperationType for object.GetRange RPC - OpTypeRange - - // OpTypeRangeHash is an OperationType for object.GetRangeHash RPC - OpTypeRangeHash -) diff --git a/acl/extended/wrappers.go b/acl/extended/wrappers.go new file mode 100644 index 0000000..2c8ff2e --- /dev/null +++ b/acl/extended/wrappers.go @@ -0,0 +1,528 @@ +package eacl + +import ( + "github.com/nspcc-dev/neofs-api-go/acl" +) + +// FilterWrapper is a wrapper over acl.EACLRecord_FilterInfo pointer. +type FilterWrapper struct { + filter *acl.EACLRecord_FilterInfo +} + +// TargetWrapper is a wrapper over acl.EACLRecord_TargetInfo pointer. +type TargetWrapper struct { + target *acl.EACLRecord_TargetInfo +} + +// RecordWrapper is a wrapper over acl.EACLRecord pointer. +type RecordWrapper struct { + record *acl.EACLRecord +} + +// TableWrapper is a wrapper over acl.EACLTable pointer. +type TableWrapper struct { + table *acl.EACLTable +} + +// WrapFilterInfo wraps EACLRecord_FilterInfo pointer. +// +// If argument is nil, new EACLRecord_FilterInfo is initialized. +func WrapFilterInfo(v *acl.EACLRecord_FilterInfo) FilterWrapper { + if v == nil { + v = new(acl.EACLRecord_FilterInfo) + } + + return FilterWrapper{ + filter: v, + } +} + +// WrapTarget wraps EACLRecord_TargetInfo pointer. +// +// If argument is nil, new EACLRecord_TargetInfo is initialized. +func WrapTarget(v *acl.EACLRecord_TargetInfo) TargetWrapper { + if v == nil { + v = new(acl.EACLRecord_TargetInfo) + } + + return TargetWrapper{ + target: v, + } +} + +// WrapRecord wraps EACLRecord pointer. +// +// If argument is nil, new EACLRecord is initialized. +func WrapRecord(v *acl.EACLRecord) RecordWrapper { + if v == nil { + v = new(acl.EACLRecord) + } + + return RecordWrapper{ + record: v, + } +} + +// WrapTable wraps EACLTable pointer. +// +// If argument is nil, new EACLTable is initialized. +func WrapTable(v *acl.EACLTable) TableWrapper { + if v == nil { + v = new(acl.EACLTable) + } + + return TableWrapper{ + table: v, + } +} + +// MatchType returns the match type of the filter. +// +// If filter is not initialized, 0 returns. +// +// Returns 0 if MatchType is not one of: +// - EACLRecord_FilterInfo_StringEqual; +// - EACLRecord_FilterInfo_StringNotEqual. +func (s FilterWrapper) MatchType() (res MatchType) { + if s.filter != nil { + switch s.filter.GetMatchType() { + case acl.EACLRecord_FilterInfo_StringEqual: + res = StringEqual + case acl.EACLRecord_FilterInfo_StringNotEqual: + res = StringNotEqual + } + } + + return +} + +// SetMatchType sets the match type of the filter. +// +// If filter is not initialized, nothing changes. +// +// MatchType is set to EACLRecord_FilterInfo_MatchUnknown if argument is not one of: +// - StringEqual; +// - StringNotEqual. +func (s FilterWrapper) SetMatchType(v MatchType) { + if s.filter != nil { + switch v { + case StringEqual: + s.filter.SetMatchType(acl.EACLRecord_FilterInfo_StringEqual) + case StringNotEqual: + s.filter.SetMatchType(acl.EACLRecord_FilterInfo_StringNotEqual) + default: + s.filter.SetMatchType(acl.EACLRecord_FilterInfo_MatchUnknown) + } + } +} + +// Name returns the name of filtering header. +// +// If filter is not initialized, empty string returns. +func (s FilterWrapper) Name() string { + if s.filter == nil { + return "" + } + + return s.filter.GetHeaderName() +} + +// SetName sets the name of the filtering header. +// +// If filter is not initialized, nothing changes. +func (s FilterWrapper) SetName(v string) { + if s.filter != nil { + s.filter.SetHeaderName(v) + } +} + +// Value returns the value of filtering header. +// +// If filter is not initialized, empty string returns. +func (s FilterWrapper) Value() string { + if s.filter == nil { + return "" + } + + return s.filter.GetHeaderVal() +} + +// SetValue sets the value of filtering header. +// +// If filter is not initialized, nothing changes. +func (s FilterWrapper) SetValue(v string) { + if s.filter != nil { + s.filter.SetHeaderVal(v) + } +} + +// HeaderType returns the header type of the filter. +// +// If filter is not initialized, HdrTypeUnknown returns. +// +// Returns HdrTypeUnknown if Header is not one of: +// - EACLRecord_FilterInfo_Request; +// - EACLRecord_FilterInfo_ObjectSystem; +// - EACLRecord_FilterInfo_ObjectUser. +func (s FilterWrapper) HeaderType() (res HeaderType) { + res = HdrTypeUnknown + + if s.filter != nil { + switch s.filter.GetHeader() { + case acl.EACLRecord_FilterInfo_Request: + res = HdrTypeRequest + case acl.EACLRecord_FilterInfo_ObjectSystem: + res = HdrTypeObjSys + case acl.EACLRecord_FilterInfo_ObjectUser: + res = HdrTypeObjUsr + } + } + + return +} + +// SetHeaderType sets the header type of the filter. +// +// If filter is not initialized, nothing changes. +// +// Header is set to EACLRecord_FilterInfo_HeaderUnknown if argument is not one of: +// - HdrTypeRequest; +// - HdrTypeObjSys; +// - HdrTypeObjUsr. +func (s FilterWrapper) SetHeaderType(t HeaderType) { + if s.filter != nil { + switch t { + case HdrTypeRequest: + s.filter.SetHeader(acl.EACLRecord_FilterInfo_Request) + case HdrTypeObjSys: + s.filter.SetHeader(acl.EACLRecord_FilterInfo_ObjectSystem) + case HdrTypeObjUsr: + s.filter.SetHeader(acl.EACLRecord_FilterInfo_ObjectUser) + default: + s.filter.SetHeader(acl.EACLRecord_FilterInfo_HeaderUnknown) + } + } +} + +// Group returns the access group of the target. +// +// If target is not initialized, GroupUnknown returns. +// +// Returns GroupUnknown if Target is not one of: +// - Target_User; +// - GroupSystem; +// - GroupOthers. +func (s TargetWrapper) Group() (res Group) { + res = GroupUnknown + + if s.target != nil { + switch s.target.GetTarget() { + case acl.Target_User: + res = GroupUser + case acl.Target_System: + res = GroupSystem + case acl.Target_Others: + res = GroupOthers + } + } + + return +} + +// SetGroup sets the access group of the target. +// +// If target is not initialized, nothing changes. +// +// Target is set to Target_Unknown if argument is not one of: +// - GroupUser; +// - GroupSystem; +// - GroupOthers. +func (s TargetWrapper) SetGroup(g Group) { + if s.target != nil { + switch g { + case GroupUser: + s.target.SetTarget(acl.Target_User) + case GroupSystem: + s.target.SetTarget(acl.Target_System) + case GroupOthers: + s.target.SetTarget(acl.Target_Others) + default: + s.target.SetTarget(acl.Target_Unknown) + } + } +} + +// KeyList returns the key list of the target. +// +// If target is not initialized, nil returns. +func (s TargetWrapper) KeyList() [][]byte { + if s.target == nil { + return nil + } + + return s.target.GetKeyList() +} + +// SetKeyList sets the key list of the target. +// +// If target is not initialized, nothing changes. +func (s TargetWrapper) SetKeyList(v [][]byte) { + if s.target != nil { + s.target.SetKeyList(v) + } +} + +// OperationType returns the operation type of the record. +// +// If record is not initialized, OpTypeUnknown returns. +// +// Returns OpTypeUnknown if Operation is not one of: +// - EACLRecord_HEAD; +// - EACLRecord_PUT; +// - EACLRecord_SEARCH; +// - EACLRecord_GET; +// - EACLRecord_GETRANGE; +// - EACLRecord_GETRANGEHASH; +// - EACLRecord_DELETE. +func (s RecordWrapper) OperationType() (res OperationType) { + res = OpTypeUnknown + + if s.record != nil { + switch s.record.GetOperation() { + case acl.EACLRecord_HEAD: + res = OpTypeHead + case acl.EACLRecord_PUT: + res = OpTypePut + case acl.EACLRecord_SEARCH: + res = OpTypeSearch + case acl.EACLRecord_GET: + res = OpTypeGet + case acl.EACLRecord_GETRANGE: + res = OpTypeRange + case acl.EACLRecord_GETRANGEHASH: + res = OpTypeRangeHash + case acl.EACLRecord_DELETE: + res = OpTypeDelete + } + } + + return +} + +// SetOperationType sets the operation type of the record. +// +// If record is not initialized, nothing changes. +// +// Operation is set to EACLRecord_OPERATION_UNKNOWN if argument is not one of: +// - OpTypeHead; +// - OpTypePut; +// - OpTypeSearch; +// - OpTypeGet; +// - OpTypeRange; +// - OpTypeRangeHash; +// - OpTypeDelete. +func (s RecordWrapper) SetOperationType(v OperationType) { + if s.record != nil { + switch v { + case OpTypeHead: + s.record.SetOperation(acl.EACLRecord_HEAD) + case OpTypePut: + s.record.SetOperation(acl.EACLRecord_PUT) + case OpTypeSearch: + s.record.SetOperation(acl.EACLRecord_SEARCH) + case OpTypeGet: + s.record.SetOperation(acl.EACLRecord_GET) + case OpTypeRange: + s.record.SetOperation(acl.EACLRecord_GETRANGE) + case OpTypeRangeHash: + s.record.SetOperation(acl.EACLRecord_GETRANGEHASH) + case OpTypeDelete: + s.record.SetOperation(acl.EACLRecord_DELETE) + default: + s.record.SetOperation(acl.EACLRecord_OPERATION_UNKNOWN) + } + } +} + +// Action returns the action of the record. +// +// If record is not initialized, ActionUnknown returns. +// +// Returns ActionUnknown if Action is not one of: +// - EACLRecord_Deny; +// - EACLRecord_Allow. +func (s RecordWrapper) Action() (res Action) { + res = ActionUnknown + + if s.record != nil { + switch s.record.GetAction() { + case acl.EACLRecord_Deny: + res = ActionDeny + case acl.EACLRecord_Allow: + res = ActionAllow + } + } + + return +} + +// SetAction sets the action of the record. +// +// If record is not initialized, nothing changes. +// +// Action is set to EACLRecord_ActionUnknown if argument is not one of: +// - ActionDeny; +// - ActionAllow. +func (s RecordWrapper) SetAction(v Action) { + if s.record != nil { + switch v { + case ActionDeny: + s.record.SetAction(acl.EACLRecord_Deny) + case ActionAllow: + s.record.SetAction(acl.EACLRecord_Allow) + default: + s.record.SetAction(acl.EACLRecord_ActionUnknown) + } + } +} + +// HeaderFilters returns the header filter list of the record. +// +// If record is not initialized, nil returns. +func (s RecordWrapper) HeaderFilters() []HeaderFilter { + if s.record == nil { + return nil + } + + filters := s.record.GetFilters() + + res := make([]HeaderFilter, 0, len(filters)) + + for i := range filters { + res = append(res, WrapFilterInfo(filters[i])) + } + + return res +} + +// SetHeaderFilters sets the header filter list of the record. +// +// Ignores nil elements of argument. +// If record is not initialized, nothing changes. +func (s RecordWrapper) SetHeaderFilters(v []HeaderFilter) { + if s.record == nil { + return + } + + filters := make([]*acl.EACLRecord_FilterInfo, 0, len(v)) + + for i := range v { + if v[i] == nil { + continue + } + + w := WrapFilterInfo(nil) + w.SetMatchType(v[i].MatchType()) + w.SetHeaderType(v[i].HeaderType()) + w.SetName(v[i].Name()) + w.SetValue(v[i].Value()) + + filters = append(filters, w.filter) + } + + s.record.SetFilters(filters) +} + +// TargetList returns the target list of the record. +// +// If record is not initialized, nil returns. +func (s RecordWrapper) TargetList() []Target { + if s.record == nil { + return nil + } + + targets := s.record.GetTargets() + + res := make([]Target, 0, len(targets)) + + for i := range targets { + res = append(res, WrapTarget(targets[i])) + } + + return res +} + +// SetTargetList sets the target list of the record. +// +// Ignores nil elements of argument. +// If record is not initialized, nothing changes. +func (s RecordWrapper) SetTargetList(v []Target) { + if s.record == nil { + return + } + + targets := make([]*acl.EACLRecord_TargetInfo, 0, len(v)) + + for i := range v { + if v[i] == nil { + continue + } + + w := WrapTarget(nil) + w.SetGroup(v[i].Group()) + w.SetKeyList(v[i].KeyList()) + + targets = append(targets, w.target) + } + + s.record.SetTargets(targets) +} + +// Records returns the record list of the table. +// +// If table is not initialized, nil returns. +func (s TableWrapper) Records() []Record { + if s.table == nil { + return nil + } + + records := s.table.GetRecords() + + res := make([]Record, 0, len(records)) + + for i := range records { + res = append(res, WrapRecord(records[i])) + } + + return res +} + +// SetRecords sets the record list of the table. +// +// Ignores nil elements of argument. +// If table is not initialized, nothing changes. +func (s TableWrapper) SetRecords(v []Record) { + if s.table == nil { + return + } + + records := make([]*acl.EACLRecord, 0, len(v)) + + for i := range v { + if v[i] == nil { + continue + } + + w := WrapRecord(nil) + w.SetOperationType(v[i].OperationType()) + w.SetAction(v[i].Action()) + w.SetHeaderFilters(v[i].HeaderFilters()) + w.SetTargetList(v[i].TargetList()) + + records = append(records, w.record) + } + + s.table.SetRecords(records) +} + + diff --git a/acl/wrappers_test.go b/acl/extended/wrappers_test.go similarity index 75% rename from acl/wrappers_test.go rename to acl/extended/wrappers_test.go index b7dbbe0..b139e59 100644 --- a/acl/wrappers_test.go +++ b/acl/extended/wrappers_test.go @@ -1,4 +1,4 @@ -package acl +package eacl import ( "testing" @@ -27,11 +27,11 @@ func TestEACLFilterWrapper(t *testing.T) { } func TestEACLTargetWrapper(t *testing.T) { - s := WrapEACLTarget(nil) + s := WrapTarget(nil) - target := Target(10) - s.SetTarget(target) - require.Equal(t, target, s.Target()) + group := Group(3) + s.SetGroup(group) + require.Equal(t, group, s.Group()) keys := [][]byte{ {1, 2, 3}, @@ -42,7 +42,7 @@ func TestEACLTargetWrapper(t *testing.T) { } func TestEACLRecordWrapper(t *testing.T) { - s := WrapEACLRecord(nil) + s := WrapRecord(nil) action := ActionAllow s.SetAction(action) @@ -67,46 +67,43 @@ func TestEACLRecordWrapper(t *testing.T) { require.Equal(t, f1Name, filters[0].Name()) require.Equal(t, f2Name, filters[1].Name()) - target1 := Target(1) - t1 := WrapEACLTarget(nil) - t1.SetTarget(target1) + group1 := Group(1) + t1 := WrapTarget(nil) + t1.SetGroup(group1) - target2 := Target(2) - t2 := WrapEACLTarget(nil) - t2.SetTarget(target2) + group2 := Group(2) + t2 := WrapTarget(nil) + t2.SetGroup(group2) - s.SetTargetList([]ExtendedACLTarget{t1, t2}) + s.SetTargetList([]Target{t1, t2}) targets := s.TargetList() require.Len(t, targets, 2) - require.Equal(t, target1, targets[0].Target()) - require.Equal(t, target2, targets[1].Target()) + require.Equal(t, group1, targets[0].Group()) + require.Equal(t, group2, targets[1].Group()) } func TestEACLTableWrapper(t *testing.T) { - s := WrapEACLTable(nil) + s := WrapTable(nil) - action1 := ExtendedACLAction(1) - r1 := WrapEACLRecord(nil) + action1 := Action(1) + r1 := WrapRecord(nil) r1.SetAction(action1) - action2 := ExtendedACLAction(2) - r2 := WrapEACLRecord(nil) + action2 := Action(2) + r2 := WrapRecord(nil) r2.SetAction(action2) - s.SetRecords([]ExtendedACLRecord{r1, r2}) + s.SetRecords([]Record{r1, r2}) records := s.Records() require.Len(t, records, 2) require.Equal(t, action1, records[0].Action()) require.Equal(t, action2, records[1].Action()) - data, err := s.MarshalBinary() + s2, err := UnmarshalTable(MarshalTable(s)) require.NoError(t, err) - s2 := WrapEACLTable(nil) - require.NoError(t, s2.UnmarshalBinary(data)) - records1 := s.Records() records2 := s2.Records() require.Len(t, records1, len(records2)) @@ -120,7 +117,7 @@ func TestEACLTableWrapper(t *testing.T) { require.Len(t, targets1, len(targets2)) for j := range targets1 { - require.Equal(t, targets1[j].Target(), targets2[j].Target()) + require.Equal(t, targets1[j].Group(), targets2[j].Group()) require.Equal(t, targets1[j].KeyList(), targets2[j].KeyList()) } diff --git a/acl/types.go b/acl/types.go index c80c9cd..4aaf8fb 100644 --- a/acl/types.go +++ b/acl/types.go @@ -1,78 +1,5 @@ package acl -const ( - _ MatchType = iota - - // StringEqual is a MatchType of string equality. - StringEqual - - // StringNotEqual is a MatchType of string inequality. - StringNotEqual -) - -const ( - // ActionUndefined is ExtendedACLAction used to mark value as undefined. - // Most of the tools consider ActionUndefined as incalculable. - // Using ActionUndefined in ExtendedACLRecord is unsafe. - ActionUndefined ExtendedACLAction = iota - - // ActionAllow is ExtendedACLAction used to mark an applicability of ACL rule. - ActionAllow - - // ActionDeny is ExtendedACLAction used to mark an inapplicability of ACL rule. - ActionDeny -) - -const ( - _ HeaderType = iota - - // HdrTypeRequest is a HeaderType for request header. - HdrTypeRequest - - // HdrTypeObjSys is a HeaderType for system headers of object. - HdrTypeObjSys - - // HdrTypeObjUsr is a HeaderType for user headers of object. - HdrTypeObjUsr -) - -const ( - // HdrObjSysNameID is a name of ID field in system header of object. - HdrObjSysNameID = "ID" - - // HdrObjSysNameCID is a name of CID field in system header of object. - HdrObjSysNameCID = "CID" - - // HdrObjSysNameOwnerID is a name of OwnerID field in system header of object. - HdrObjSysNameOwnerID = "OWNER_ID" - - // HdrObjSysNameVersion is a name of Version field in system header of object. - HdrObjSysNameVersion = "VERSION" - - // HdrObjSysNamePayloadLength is a name of PayloadLength field in system header of object. - HdrObjSysNamePayloadLength = "PAYLOAD_LENGTH" - - // HdrObjSysNameCreatedUnix is a name of CreatedAt.UnitTime field in system header of object. - HdrObjSysNameCreatedUnix = "CREATED_UNIX" - - // HdrObjSysNameCreatedEpoch is a name of CreatedAt.Epoch field in system header of object. - HdrObjSysNameCreatedEpoch = "CREATED_EPOCH" - - // HdrObjSysLinkPrev is a name of previous link header in extended headers of object. - HdrObjSysLinkPrev = "LINK_PREV" - - // HdrObjSysLinkNext is a name of next link header in extended headers of object. - HdrObjSysLinkNext = "LINK_NEXT" - - // HdrObjSysLinkChild is a name of child link header in extended headers of object. - HdrObjSysLinkChild = "LINK_CHILD" - - // HdrObjSysLinkPar is a name of parent link header in extended headers of object. - HdrObjSysLinkPar = "LINK_PAR" - - // HdrObjSysLinkSG is a name of storage group link header in extended headers of object. - HdrObjSysLinkSG = "LINK_SG" -) // SetMatchType is MatchType field setter. func (m *EACLRecord_FilterInfo) SetMatchType(v EACLRecord_FilterInfo_MatchType) { diff --git a/acl/wrappers.go b/acl/wrappers.go deleted file mode 100644 index 30c2ee3..0000000 --- a/acl/wrappers.go +++ /dev/null @@ -1,498 +0,0 @@ -package acl - -// EACLFilterWrapper is a wrapper over EACLRecord_FilterInfo pointer. -type EACLFilterWrapper struct { - filter *EACLRecord_FilterInfo -} - -// EACLTargetWrapper is a wrapper over EACLRecord_TargetInfo pointer. -type EACLTargetWrapper struct { - target *EACLRecord_TargetInfo -} - -// EACLRecordWrapper is a wrapper over EACLRecord pointer. -type EACLRecordWrapper struct { - record *EACLRecord -} - -// EACLTableWrapper is a wrapper over EACLTable pointer. -type EACLTableWrapper struct { - table *EACLTable -} - -// WrapFilterInfo wraps EACLRecord_FilterInfo pointer. -// -// If argument is nil, new EACLRecord_FilterInfo is initialized. -func WrapFilterInfo(v *EACLRecord_FilterInfo) EACLFilterWrapper { - if v == nil { - v = new(EACLRecord_FilterInfo) - } - - return EACLFilterWrapper{ - filter: v, - } -} - -// WrapEACLTarget wraps EACLRecord_TargetInfo pointer. -// -// If argument is nil, new EACLRecord_TargetInfo is initialized. -func WrapEACLTarget(v *EACLRecord_TargetInfo) EACLTargetWrapper { - if v == nil { - v = new(EACLRecord_TargetInfo) - } - - return EACLTargetWrapper{ - target: v, - } -} - -// WrapEACLRecord wraps EACLRecord pointer. -// -// If argument is nil, new EACLRecord is initialized. -func WrapEACLRecord(v *EACLRecord) EACLRecordWrapper { - if v == nil { - v = new(EACLRecord) - } - - return EACLRecordWrapper{ - record: v, - } -} - -// WrapEACLTable wraps EACLTable pointer. -// -// If argument is nil, new EACLTable is initialized. -func WrapEACLTable(v *EACLTable) EACLTableWrapper { - if v == nil { - v = new(EACLTable) - } - - return EACLTableWrapper{ - table: v, - } -} - -// MatchType returns casted result of MatchType field getter. -// -// If filter is not initialized, 0 returns. -// -// Returns 0 if MatchType is not one of: -// - EACLRecord_FilterInfo_StringEqual; -// - EACLRecord_FilterInfo_StringNotEqual. -func (s EACLFilterWrapper) MatchType() (res MatchType) { - if s.filter != nil { - switch s.filter.GetMatchType() { - case EACLRecord_FilterInfo_StringEqual: - res = StringEqual - case EACLRecord_FilterInfo_StringNotEqual: - res = StringNotEqual - } - } - - return -} - -// SetMatchType passes casted argument to MatchType field setter. -// -// If filter is not initialized, nothing changes. -// -// MatchType is set to EACLRecord_FilterInfo_MatchUnknown if argument is not one of: -// - StringEqual; -// - StringNotEqual. -func (s EACLFilterWrapper) SetMatchType(v MatchType) { - if s.filter != nil { - switch v { - case StringEqual: - s.filter.SetMatchType(EACLRecord_FilterInfo_StringEqual) - case StringNotEqual: - s.filter.SetMatchType(EACLRecord_FilterInfo_StringNotEqual) - default: - s.filter.SetMatchType(EACLRecord_FilterInfo_MatchUnknown) - } - } -} - -// Name returns the result of HeaderName field getter. -// -// If filter is not initialized, empty string returns. -func (s EACLFilterWrapper) Name() string { - if s.filter == nil { - return "" - } - - return s.filter.GetHeaderName() -} - -// SetName passes argument to HeaderName field setter. -// -// If filter is not initialized, nothing changes. -func (s EACLFilterWrapper) SetName(v string) { - if s.filter != nil { - s.filter.SetHeaderName(v) - } -} - -// Value returns the result of HeaderVal field getter. -// -// If filter is not initialized, empty string returns. -func (s EACLFilterWrapper) Value() string { - if s.filter == nil { - return "" - } - - return s.filter.GetHeaderVal() -} - -// SetValue passes argument to HeaderVal field setter. -// -// If filter is not initialized, nothing changes. -func (s EACLFilterWrapper) SetValue(v string) { - if s.filter != nil { - s.filter.SetHeaderVal(v) - } -} - -// HeaderType returns the result of Header field getter. -// -// If filter is not initialized, 0 returns. -// -// Returns 0 if Header is not one of: -// - EACLRecord_FilterInfo_Request; -// - EACLRecord_FilterInfo_ObjectSystem; -// - EACLRecord_FilterInfo_ObjectUser. -func (s EACLFilterWrapper) HeaderType() (res HeaderType) { - if s.filter != nil { - switch s.filter.GetHeader() { - case EACLRecord_FilterInfo_Request: - res = HdrTypeRequest - case EACLRecord_FilterInfo_ObjectSystem: - res = HdrTypeObjSys - case EACLRecord_FilterInfo_ObjectUser: - res = HdrTypeObjUsr - } - } - - return -} - -// SetHeaderType passes casted argument to Header field setter. -// -// If filter is not initialized, nothing changes. -// -// Header is set to EACLRecord_FilterInfo_HeaderUnknown if argument is not one of: -// - HdrTypeRequest; -// - HdrTypeObjSys; -// - HdrTypeObjUsr. -func (s EACLFilterWrapper) SetHeaderType(t HeaderType) { - if s.filter != nil { - switch t { - case HdrTypeRequest: - s.filter.SetHeader(EACLRecord_FilterInfo_Request) - case HdrTypeObjSys: - s.filter.SetHeader(EACLRecord_FilterInfo_ObjectSystem) - case HdrTypeObjUsr: - s.filter.SetHeader(EACLRecord_FilterInfo_ObjectUser) - default: - s.filter.SetHeader(EACLRecord_FilterInfo_HeaderUnknown) - } - } -} - -// Target returns the result of Target field getter. -// -// If target is not initialized, Target_Unknown returns. -func (s EACLTargetWrapper) Target() Target { - if s.target == nil { - return Target_Unknown - } - - return s.target.GetTarget() -} - -// SetTarget passes argument to Target field setter. -// -// If target is not initialized, nothing changes. -func (s EACLTargetWrapper) SetTarget(v Target) { - if s.target != nil { - s.target.SetTarget(v) - } -} - -// KeyList returns the result of KeyList field getter. -// -// If target is not initialized, nil returns. -func (s EACLTargetWrapper) KeyList() [][]byte { - if s.target == nil { - return nil - } - - return s.target.GetKeyList() -} - -// SetKeyList passes argument to KeyList field setter. -// -// If target is not initialized, nothing changes. -func (s EACLTargetWrapper) SetKeyList(v [][]byte) { - if s.target != nil { - s.target.SetKeyList(v) - } -} - -// OperationType returns casted result of Operation field getter. -// -// If record is not initialized, 0 returns. -// -// Returns 0 if Operation is not one of: -// - EACLRecord_HEAD; -// - EACLRecord_PUT; -// - EACLRecord_SEARCH; -// - EACLRecord_GET; -// - EACLRecord_GETRANGE; -// - EACLRecord_GETRANGEHASH; -// - EACLRecord_DELETE. -func (s EACLRecordWrapper) OperationType() (res OperationType) { - if s.record != nil { - switch s.record.GetOperation() { - case EACLRecord_HEAD: - res = OpTypeHead - case EACLRecord_PUT: - res = OpTypePut - case EACLRecord_SEARCH: - res = OpTypeSearch - case EACLRecord_GET: - res = OpTypeGet - case EACLRecord_GETRANGE: - res = OpTypeRange - case EACLRecord_GETRANGEHASH: - res = OpTypeRangeHash - case EACLRecord_DELETE: - res = OpTypeDelete - } - } - - return -} - -// SetOperationType passes casted argument to Operation field setter. -// -// If record is not initialized, nothing changes. -// -// Operation is set to EACLRecord_OPERATION_UNKNOWN if argument is not one of: -// - OpTypeHead; -// - OpTypePut; -// - OpTypeSearch; -// - OpTypeGet; -// - OpTypeRange; -// - OpTypeRangeHash; -// - OpTypeDelete. -func (s EACLRecordWrapper) SetOperationType(v OperationType) { - if s.record != nil { - switch v { - case OpTypeHead: - s.record.SetOperation(EACLRecord_HEAD) - case OpTypePut: - s.record.SetOperation(EACLRecord_PUT) - case OpTypeSearch: - s.record.SetOperation(EACLRecord_SEARCH) - case OpTypeGet: - s.record.SetOperation(EACLRecord_GET) - case OpTypeRange: - s.record.SetOperation(EACLRecord_GETRANGE) - case OpTypeRangeHash: - s.record.SetOperation(EACLRecord_GETRANGEHASH) - case OpTypeDelete: - s.record.SetOperation(EACLRecord_DELETE) - default: - s.record.SetOperation(EACLRecord_OPERATION_UNKNOWN) - } - } -} - -// Action returns casted result of Action field getter. -// -// If record is not initialized, 0 returns. -// -// Returns 0 if Action is not one of: -// - EACLRecord_Deny; -// - EACLRecord_Allow. -func (s EACLRecordWrapper) Action() (res ExtendedACLAction) { - if s.record != nil { - switch s.record.GetAction() { - case EACLRecord_Deny: - res = ActionDeny - case EACLRecord_Allow: - res = ActionAllow - } - } - - return -} - -// SetAction passes casted argument to Action field setter. -// -// If record is not initialized, nothing changes. -// -// Action is set to EACLRecord_ActionUnknown if argument is not one of: -// - ActionDeny; -// - ActionAllow. -func (s EACLRecordWrapper) SetAction(v ExtendedACLAction) { - if s.record != nil { - switch v { - case ActionDeny: - s.record.SetAction(EACLRecord_Deny) - case ActionAllow: - s.record.SetAction(EACLRecord_Allow) - default: - s.record.SetAction(EACLRecord_ActionUnknown) - } - } -} - -// HeaderFilters wraps all elements from Filters field getter result and returns HeaderFilter list. -// -// If record is not initialized, nil returns. -func (s EACLRecordWrapper) HeaderFilters() []HeaderFilter { - if s.record == nil { - return nil - } - - filters := s.record.GetFilters() - - res := make([]HeaderFilter, 0, len(filters)) - - for i := range filters { - res = append(res, WrapFilterInfo(filters[i])) - } - - return res -} - -// SetHeaderFilters converts HeaderFilter list to EACLRecord_FilterInfo list and passes it to Filters field setter. -// -// Ignores nil elements of argument. -// If record is not initialized, nothing changes. -func (s EACLRecordWrapper) SetHeaderFilters(v []HeaderFilter) { - if s.record == nil { - return - } - - filters := make([]*EACLRecord_FilterInfo, 0, len(v)) - - for i := range v { - if v[i] == nil { - continue - } - - w := WrapFilterInfo(nil) - w.SetMatchType(v[i].MatchType()) - w.SetHeaderType(v[i].HeaderType()) - w.SetName(v[i].Name()) - w.SetValue(v[i].Value()) - - filters = append(filters, w.filter) - } - - s.record.SetFilters(filters) -} - -// TargetList wraps all elements from Targets field getter result and returns ExtendedACLTarget list. -// -// If record is not initialized, nil returns. -func (s EACLRecordWrapper) TargetList() []ExtendedACLTarget { - if s.record == nil { - return nil - } - - targets := s.record.GetTargets() - - res := make([]ExtendedACLTarget, 0, len(targets)) - - for i := range targets { - res = append(res, WrapEACLTarget(targets[i])) - } - - return res -} - -// SetTargetList converts ExtendedACLTarget list to EACLRecord_TargetInfo list and passes it to Targets field setter. -// -// Ignores nil elements of argument. -// If record is not initialized, nothing changes. -func (s EACLRecordWrapper) SetTargetList(v []ExtendedACLTarget) { - if s.record == nil { - return - } - - targets := make([]*EACLRecord_TargetInfo, 0, len(v)) - - for i := range v { - if v[i] == nil { - continue - } - - w := WrapEACLTarget(nil) - w.SetTarget(v[i].Target()) - w.SetKeyList(v[i].KeyList()) - - targets = append(targets, w.target) - } - - s.record.SetTargets(targets) -} - -// Records wraps all elements from Records field getter result and returns ExtendedACLRecord list. -// -// If table is not initialized, nil returns. -func (s EACLTableWrapper) Records() []ExtendedACLRecord { - if s.table == nil { - return nil - } - - records := s.table.GetRecords() - - res := make([]ExtendedACLRecord, 0, len(records)) - - for i := range records { - res = append(res, WrapEACLRecord(records[i])) - } - - return res -} - -// SetRecords converts ExtendedACLRecord list to EACLRecord list and passes it to Records field setter. -// -// Ignores nil elements of argument. -// If table is not initialized, nothing changes. -func (s EACLTableWrapper) SetRecords(v []ExtendedACLRecord) { - if s.table == nil { - return - } - - records := make([]*EACLRecord, 0, len(v)) - - for i := range v { - if v[i] == nil { - continue - } - - w := WrapEACLRecord(nil) - w.SetOperationType(v[i].OperationType()) - w.SetAction(v[i].Action()) - w.SetHeaderFilters(v[i].HeaderFilters()) - w.SetTargetList(v[i].TargetList()) - - records = append(records, w.record) - } - - s.table.SetRecords(records) -} - -// MarshalBinary returns the result of Marshal method. -func (s EACLTableWrapper) MarshalBinary() ([]byte, error) { - return s.table.Marshal() -} - -// UnmarshalBinary passes argument to Unmarshal method and returns its result. -func (s EACLTableWrapper) UnmarshalBinary(data []byte) error { - return s.table.Unmarshal(data) -}