From a02d226b4c4645a0f8bf7ce862960945d0c43951 Mon Sep 17 00:00:00 2001 From: Dora Korpar Date: Thu, 1 Mar 2018 14:47:10 -0800 Subject: [PATCH] ft: add date modified headers as condition for object delete --- lib/api/objectDelete.js | 17 +++++++- tests/unit/api/objectDelete.js | 80 ++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/lib/api/objectDelete.js b/lib/api/objectDelete.js index ec8c771122..23325f3c08 100644 --- a/lib/api/objectDelete.js +++ b/lib/api/objectDelete.js @@ -1,6 +1,6 @@ const async = require('async'); -const { errors, versioning } = require('arsenal'); - +const { errors, versioning, s3middleware } = require('arsenal'); +const checkDateModifiedHeaders = s3middleware.checkDateModifiedHeaders; const collectCorsHeaders = require('../utilities/collectCorsHeaders'); const services = require('../services'); const { pushMetric } = require('../utapi/utilities'); @@ -99,6 +99,19 @@ function objectDelete(authInfo, request, log, cb) { return next(null, bucketMD, objectMD, options); }); }, + function validateHeaders(bucketMD, objectMD, options, next) { + if (objectMD) { + const lastModified = objectMD['last-modified']; + const { modifiedSinceRes, unmodifiedSinceRes } = + checkDateModifiedHeaders(request.headers, lastModified); + const err = modifiedSinceRes.error || unmodifiedSinceRes.error; + if (err) { + return process.nextTick(() => next(err, bucketMD)); + } + } + return process.nextTick(() => + next(null, bucketMD, objectMD, options)); + }, function deleteOperation(bucketMD, objectMD, delOptions, next) { const deleteInfo = { removeDeleteMarker: false, diff --git a/tests/unit/api/objectDelete.js b/tests/unit/api/objectDelete.js index 4b3f585650..0e7359db6c 100644 --- a/tests/unit/api/objectDelete.js +++ b/tests/unit/api/objectDelete.js @@ -17,6 +17,10 @@ const namespace = 'default'; const bucketName = 'bucketname'; const postBody = Buffer.from('I am a body', 'utf8'); const objectKey = 'objectName'; +const earlyDate = new Date(); +const lateDate = new Date(); +earlyDate.setMinutes(earlyDate.getMinutes() - 30); +lateDate.setMinutes(lateDate.getMinutes() + 30); function testAuth(bucketOwner, authUser, bucketPutReq, objPutReq, objDelReq, log, cb) { @@ -145,4 +149,80 @@ describe('objectDelete API', () => { testAuth(bucketOwner, authUser, testBucketPutRequest, testPutObjectRequest, testDeleteRequest, log, done); }); + + describe('with \'modified\' headers', () => { + beforeEach(done => { + bucketPut(authInfo, testBucketPutRequest, log, () => { + objectPut(authInfo, testPutObjectRequest, undefined, log, done); + }); + }); + + it('should return error if request includes \'if-unmodified-since\' ' + + 'header and object has been modified', done => { + const testDeleteRequest = new DummyRequest({ + bucketName, + namespace, + objectKey, + headers: { 'if-unmodified-since': earlyDate }, + url: `/${bucketName}/${objectKey}`, + }); + objectDelete(authInfo, testDeleteRequest, log, err => { + assert.deepStrictEqual(err, errors.PreconditionFailed); + done(); + }); + }); + + it('should delete an object with \'if-unmodified-since\' header', + done => { + const testDeleteRequest = new DummyRequest({ + bucketName, + namespace, + objectKey, + headers: { 'if-unmodified-since': lateDate }, + url: `/${bucketName}/${objectKey}`, + }); + objectDelete(authInfo, testDeleteRequest, log, err => { + assert.strictEqual(err, null); + objectGet(authInfo, testGetObjectRequest, false, log, + err => { + assert.deepStrictEqual(err, errors.NoSuchKey); + done(); + }); + }); + }); + + it('should return error if request includes \'if-modified-since\' ' + + 'header and object has not been modified', done => { + const testDeleteRequest = new DummyRequest({ + bucketName, + namespace, + objectKey, + headers: { 'if-modified-since': lateDate }, + url: `/${bucketName}/${objectKey}`, + }); + objectDelete(authInfo, testDeleteRequest, log, err => { + assert.deepStrictEqual(err, errors.NotModified); + done(); + }); + }); + + it('should delete an object with \'if-modified-since\' header', + done => { + const testDeleteRequest = new DummyRequest({ + bucketName, + namespace, + objectKey, + headers: { 'if-modified-since': earlyDate }, + url: `/${bucketName}/${objectKey}`, + }); + objectDelete(authInfo, testDeleteRequest, log, err => { + assert.strictEqual(err, null); + objectGet(authInfo, testGetObjectRequest, false, log, + err => { + assert.deepStrictEqual(err, errors.NoSuchKey); + done(); + }); + }); + }); + }); });