object: Validate attribute EXPIRATION_EPOCH on put #1188

Merged
fyrchik merged 1 commit from acid-ant/frostfs-node:bugfix/1109-validate-exp-epoch into master 2024-06-19 17:19:32 +00:00
2 changed files with 28 additions and 30 deletions

View file

@ -124,15 +124,22 @@ func (v *FormatValidator) Validate(ctx context.Context, obj *objectSDK.Object, u
return fmt.Errorf("invalid attributes: %w", err)
}
exp, err := expirationEpochAttribute(obj)
dstepanov-yadro marked this conversation as resolved Outdated

Also it could happen, that user has defined both of attributes: objectV2.SysAttributeExpEpoch and objectV2.SysAttributeExpEpochNeoFS. Maybe it has to be an error too?

Also it could happen, that user has defined both of attributes: `objectV2.SysAttributeExpEpoch` and `objectV2.SysAttributeExpEpochNeoFS`. Maybe it has to be an error too?

It definitely should be, but we will eventually remove NeoFS attribute, and currently we have deterministic behaviour, so I would leave it as is.

It definitely should be, but we will eventually remove NeoFS attribute, and currently we have deterministic behaviour, so I would leave it as is.
if err != nil {
if !errors.Is(err, errNoExpirationEpoch) {
return fmt.Errorf("object did not pass expiration check: %w", err)
}
} else if !unprepared && exp < v.netState.CurrentEpoch() {
fyrchik marked this conversation as resolved Outdated

else if !unprepared?

Also, checkExpiration now contains a single if, we could move it here and rename checkExpiration to checkIfExpired. And checking whether expiration epoch is less than the current epoch is valid for both types of objects, the only check that is specific is IsLocked (because not-yet-created object cannot be locked).

`else if !unprepared`? Also, `checkExpiration` now contains a single `if`, we could move it here and rename `checkExpiration` to `checkIfExpired`. And checking whether `expiration epoch` is less than the current epoch is valid for both types of objects, the only check that is specific is `IsLocked` (because not-yet-created object cannot be locked).

OMG, updated. Thanks.

OMG, updated. Thanks.
if err := v.checkIfExpired(ctx, obj); err != nil {
return fmt.Errorf("object did not pass expiration check: %w", err)
}
}
if !unprepared {
if err := v.validateSignatureKey(obj); err != nil {
return fmt.Errorf("(%T) could not validate signature key: %w", v, err)
}
if err := v.checkExpiration(ctx, obj); err != nil {
return fmt.Errorf("object did not pass expiration check: %w", err)
}
if err := objectSDK.CheckHeaderVerificationFields(obj); err != nil {
return fmt.Errorf("(%T) could not validate header fields: %w", v, err)
}
@ -348,35 +355,24 @@ func (v *FormatValidator) fillAndValidateTombstoneMeta(o *objectSDK.Object, meta
var errExpired = errors.New("object has expired")
func (v *FormatValidator) checkExpiration(ctx context.Context, obj *objectSDK.Object) error {
exp, err := expirationEpochAttribute(obj)
if err != nil {
if errors.Is(err, errNoExpirationEpoch) {
return nil // objects without expiration attribute are valid
}
func (v *FormatValidator) checkIfExpired(ctx context.Context, obj *objectSDK.Object) error {
// an object could be expired but locked;
// put such an object is a correct operation
return err
cID, _ := obj.ContainerID()
oID, _ := obj.ID()
var addr oid.Address
addr.SetContainer(cID)
addr.SetObject(oID)
locked, err := v.e.IsLocked(ctx, addr)
if err != nil {
return fmt.Errorf("locking status check for an expired object: %w", err)
}
if exp < v.netState.CurrentEpoch() {
// an object could be expired but locked;
// put such an object is a correct operation
cID, _ := obj.ContainerID()
oID, _ := obj.ID()
var addr oid.Address
addr.SetContainer(cID)
addr.SetObject(oID)
locked, err := v.e.IsLocked(ctx, addr)
if err != nil {
return fmt.Errorf("locking status check for an expired object: %w", err)
}
if !locked {
return errExpired
}
if !locked {
return errExpired
}
return nil

View file

@ -195,6 +195,8 @@ func TestFormatValidator_Validate(t *testing.T) {
val := "text"
err := v.Validate(context.Background(), fn(val), false)
require.Error(t, err)
err = v.Validate(context.Background(), fn(val), true)
require.Error(t, err)
})
t.Run("expired object", func(t *testing.T) {