forked from TrueCloudLab/frostfs-node
[#633] object: Prevent duplicate attributes by key
Keys of object attributes must be unique according to NeoFS specification. Make `FormatValidator.Validate` method to return an error if at least one attribute is duplicated. Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
parent
6efeee5ce0
commit
01dd17e30a
2 changed files with 48 additions and 0 deletions
|
@ -77,6 +77,10 @@ func (v *FormatValidator) Validate(obj *Object) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for ; obj != nil; obj = obj.GetParent() {
|
for ; obj != nil; obj = obj.GetParent() {
|
||||||
|
if err := v.checkAttributes(obj); err != nil {
|
||||||
|
return fmt.Errorf("invalid attributes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := v.validateSignatureKey(obj); err != nil {
|
if err := v.validateSignatureKey(obj); err != nil {
|
||||||
return fmt.Errorf("(%T) could not validate signature key: %w", v, err)
|
return fmt.Errorf("(%T) could not validate signature key: %w", v, err)
|
||||||
}
|
}
|
||||||
|
@ -227,6 +231,26 @@ func expirationEpochAttribute(obj *Object) (uint64, error) {
|
||||||
return 0, errNoExpirationEpoch
|
return 0, errNoExpirationEpoch
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errDuplAttr = errors.New("duplication of attributes detected")
|
||||||
|
|
||||||
|
func (v *FormatValidator) checkAttributes(obj *Object) error {
|
||||||
|
as := obj.Attributes()
|
||||||
|
|
||||||
|
mUnique := make(map[string]struct{}, len(as))
|
||||||
|
|
||||||
|
for _, a := range as {
|
||||||
|
key := a.Key()
|
||||||
|
|
||||||
|
if _, was := mUnique[key]; was {
|
||||||
|
return errDuplAttr
|
||||||
|
}
|
||||||
|
|
||||||
|
mUnique[key] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// WithNetState returns options to set network state interface.
|
// WithNetState returns options to set network state interface.
|
||||||
//
|
//
|
||||||
// FIXME: network state is a required parameter.
|
// FIXME: network state is a required parameter.
|
||||||
|
|
|
@ -219,4 +219,28 @@ func TestFormatValidator_Validate(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("attributes", func(t *testing.T) {
|
||||||
|
t.Run("duplication", func(t *testing.T) {
|
||||||
|
obj := blankValidObject(t, ownerKey)
|
||||||
|
|
||||||
|
a1 := object.NewAttribute()
|
||||||
|
a1.SetKey("key1")
|
||||||
|
a1.SetValue("val1")
|
||||||
|
|
||||||
|
a2 := object.NewAttribute()
|
||||||
|
a2.SetKey("key2")
|
||||||
|
a2.SetValue("val2")
|
||||||
|
|
||||||
|
obj.SetAttributes(a1, a2)
|
||||||
|
|
||||||
|
err := v.checkAttributes(obj.Object())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
a2.SetKey(a1.Key())
|
||||||
|
|
||||||
|
err = v.checkAttributes(obj.Object())
|
||||||
|
require.Equal(t, errDuplAttr, err)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue