diff --git a/changelog/unreleased/storage-if-match.md b/changelog/unreleased/storage-if-match.md new file mode 100644 index 0000000000..9a4ff9e3fb --- /dev/null +++ b/changelog/unreleased/storage-if-match.md @@ -0,0 +1,5 @@ +Enhancement: Add an if-match check to the storage provider + +Implement a check for the if-match value in InitiateFileUpload to prevent overwrites of newer versions. + +https://github.com/cs3org/reva/pull/2547 diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index c7fd5d9a06..cfd826601f 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -291,6 +291,29 @@ func (s *service) InitiateFileUpload(ctx context.Context, req *provider.Initiate }, nil } + if ifMatch := req.GetIfMatch(); ifMatch != "" { + sRes, err := s.Stat(ctx, &provider.StatRequest{Ref: req.Ref}) + if err != nil { + return nil, err + } + + switch sRes.Status.Code { + case rpc.Code_CODE_OK: + if sRes.Info.Etag != req.GetIfMatch() { + return &provider.InitiateFileUploadResponse{ + Status: status.NewFailedPrecondition(ctx, errors.New("etag doesn't match"), "etag doesn't match"), + }, nil + } + case rpc.Code_CODE_NOT_FOUND: + // Just continue with a normal upload + default: + return &provider.InitiateFileUploadResponse{ + Status: sRes.Status, + }, nil + } + + } + // FIXME these should be part of the InitiateFileUploadRequest object if req.Opaque != nil { if e, ok := req.Opaque.Map["lockid"]; ok && e.Decoder == "plain" {