11const assert = require ( 'assert' ) ;
22const sinon = require ( 'sinon' ) ;
3+ const { promisify } = require ( 'util' ) ;
34const metadataUtils = require ( '../../../lib/metadata/metadataUtils' ) ;
45const storeObject = require ( '../../../lib/api/apiUtils/object/storeObject' ) ;
56const metadata = require ( '../../../lib/metadata/wrapper' ) ;
67const { DummyRequestLogger } = require ( '../helpers' ) ;
8+ const dataWrapper = require ( '../../../lib/data/wrapper' ) ;
79const DummyRequest = require ( '../DummyRequest' ) ;
10+ const { auth } = require ( 'arsenal' ) ;
811
912const log = new DummyRequestLogger ( ) ;
1013
11- function prepareDummyRequest ( headers = { } ) {
14+ function prepareDummyRequest ( headers = { } , body = '' ) {
1215 const request = new DummyRequest ( {
1316 hostname : 'localhost' ,
1417 method : 'PUT' ,
@@ -17,8 +20,11 @@ function prepareDummyRequest(headers = {}) {
1720 headers,
1821 socket : {
1922 remoteAddress : '0.0.0.0' ,
23+ destroy : ( ) => { } ,
24+ on : ( ) => { } ,
25+ removeListener : ( ) => { } ,
2026 } ,
21- } , '{"replicationInfo":"{}"}' ) ;
27+ } , body || '{"replicationInfo":"{}"}' ) ;
2228 return request ;
2329}
2430
@@ -186,4 +192,243 @@ describe('routeBackbeat', () => {
186192 assert . strictEqual ( mockResponse . statusCode , 200 ) ;
187193 assert . deepStrictEqual ( mockResponse . body , [ { } ] ) ;
188194 } ) ;
195+
196+ it ( 'should put metadata' , async ( ) => {
197+ mockRequest . method = 'PUT' ;
198+ mockRequest . url = '/_/backbeat/metadata/bucket0/key0' ;
199+ mockRequest . headers = {
200+ 'x-scal-versioning-required' : 'true' ,
201+ } ;
202+ mockRequest . destroy = ( ) => { } ;
203+
204+ sandbox . stub ( metadata , 'putObjectMD' ) . callsFake ( ( bucketName , objectKey , omVal , options , logParam , cb ) => {
205+ cb ( null , { } ) ;
206+ } ) ;
207+
208+ metadataUtils . standardMetadataValidateBucketAndObj . callsFake ( ( params , denies , log , callback ) => {
209+ const bucketInfo = {
210+ getVersioningConfiguration : ( ) => ( { Status : 'Enabled' } ) ,
211+ isVersioningEnabled : ( ) => true ,
212+ } ;
213+ const objMd = { } ;
214+ callback ( null , bucketInfo , objMd ) ;
215+ } ) ;
216+
217+ routeBackbeat ( '127.0.0.1' , mockRequest , mockResponse , log ) ;
218+
219+ /* eslint-disable-next-line no-void */
220+ void await endPromise ;
221+
222+ assert . strictEqual ( mockResponse . statusCode , 200 ) ;
223+ assert . deepStrictEqual ( mockResponse . body , { } ) ;
224+ } ) ;
225+
226+ it ( 'should handle error when putting metadata' , async ( ) => {
227+ mockRequest . method = 'PUT' ;
228+ mockRequest . url = '/_/backbeat/metadata/bucket0/key0' ;
229+ mockRequest . headers = {
230+ 'x-scal-versioning-required' : 'true' ,
231+ } ;
232+ mockRequest . destroy = ( ) => { } ;
233+
234+ sandbox . stub ( metadata , 'putObjectMD' ) . callsFake ( ( bucketName , objectKey , omVal , options , logParam , cb ) => {
235+ cb ( new Error ( 'error' ) ) ;
236+ } ) ;
237+
238+ metadataUtils . standardMetadataValidateBucketAndObj . callsFake ( ( params , denies , log , callback ) => {
239+ const bucketInfo = {
240+ getVersioningConfiguration : ( ) => ( { Status : 'Enabled' } ) ,
241+ isVersioningEnabled : ( ) => true ,
242+ } ;
243+ const objMd = { } ;
244+ callback ( null , bucketInfo , objMd ) ;
245+ } ) ;
246+
247+ routeBackbeat ( '127.0.0.1' , mockRequest , mockResponse , log ) ;
248+
249+ /* eslint-disable-next-line no-void */
250+ void await endPromise ;
251+
252+ assert . strictEqual ( mockResponse . statusCode , 500 ) ;
253+ } ) ;
254+
255+ it ( 'should be rejected when using a wrong route' , async ( ) => {
256+ mockRequest . method = 'PUT' ;
257+ mockRequest . url = '/_/backbeat/metadata/bucket0' ;
258+ mockRequest . headers = {
259+ 'x-scal-versioning-required' : 'true' ,
260+ } ;
261+ mockRequest . destroy = ( ) => { } ;
262+
263+ routeBackbeat ( '127.0.0.1' , mockRequest , mockResponse , log ) ;
264+
265+ /* eslint-disable-next-line no-void */
266+ void await endPromise ;
267+
268+ assert . strictEqual ( mockResponse . statusCode , 405 ) ;
269+ } ) ;
270+
271+ it ( 'should be rejected when trying batchDelete as a public user' , async ( ) => {
272+ mockRequest = prepareDummyRequest ( null , JSON . stringify ( {
273+ Locations : [
274+ {
275+ key : 'key0' ,
276+ bucket : 'bucket0' ,
277+ } ,
278+ ] ,
279+ } ) ) ;
280+
281+ mockRequest . method = 'POST' ;
282+ mockRequest . url = '/_/backbeat/batchdelete' ;
283+ mockRequest . headers = {
284+ 'x-scal-versioning-required' : 'true' ,
285+ } ;
286+ mockRequest . destroy = ( ) => { } ;
287+ routeBackbeat ( '127.0.0.1' , mockRequest , mockResponse , log ) ;
288+
289+ /* eslint-disable-next-line no-void */
290+ void await endPromise ;
291+ assert . strictEqual ( mockResponse . statusCode , 403 ) ;
292+ } ) ;
293+
294+ it ( 'should batchDelete' , async ( ) => {
295+ mockRequest = prepareDummyRequest ( null , JSON . stringify ( {
296+ Locations : [
297+ {
298+ key : 'key0' ,
299+ bucket : 'bucket0' ,
300+ } ,
301+ ] ,
302+ } ) ) ;
303+
304+ mockRequest . method = 'POST' ;
305+ mockRequest . url = '/_/backbeat/batchdelete' ;
306+ mockRequest . headers = {
307+ 'x-scal-versioning-required' : 'true' ,
308+ } ;
309+ mockRequest . destroy = ( ) => { } ;
310+ const doAuthStub = sandbox . stub ( auth . server , 'doAuth' ) ;
311+ doAuthStub . callsFake ( ( req , log , cb ) => {
312+ cb ( null , {
313+ canonicalID : 'id' ,
314+ getCanonicalID : ( ) => 'id' ,
315+ } ) ;
316+ } ) ;
317+
318+ routeBackbeat ( '127.0.0.1' , mockRequest , mockResponse , log ) ;
319+
320+ /* eslint-disable-next-line no-void */
321+ void await endPromise ;
322+ assert . strictEqual ( mockResponse . statusCode , 200 ) ;
323+ assert . deepStrictEqual ( mockResponse . body , null ) ;
324+ } ) ;
325+
326+ it ( 'should batchDelete with conditions and azure location' , async ( ) => {
327+ mockRequest = prepareDummyRequest ( {
328+ 'if-unmodified-since' : '1980-01-01T00:00:00.000Z' ,
329+ 'x-scal-versioning-required' : 'true' ,
330+ 'x-scal-storage-class' : 'azurebackend' ,
331+ } , JSON . stringify ( {
332+ Locations : [
333+ {
334+ key : 'key0' ,
335+ bucket : 'bucket0' ,
336+ } ,
337+ ] ,
338+ } ) ) ;
339+
340+ mockRequest . method = 'POST' ;
341+ mockRequest . url = '/_/backbeat/batchdelete' ;
342+ mockRequest . destroy = ( ) => { } ;
343+ const doAuthStub = sandbox . stub ( auth . server , 'doAuth' ) ;
344+ doAuthStub . callsFake ( ( req , log , cb ) => {
345+ cb ( null , {
346+ canonicalID : 'id' ,
347+ getCanonicalID : ( ) => 'id' ,
348+ } ) ;
349+ } ) ;
350+
351+ routeBackbeat ( '127.0.0.1' , mockRequest , mockResponse , log ) ;
352+
353+ /* eslint-disable-next-line no-void */
354+ void await endPromise ;
355+ assert . strictEqual ( mockResponse . statusCode , 200 ) ;
356+ assert . deepStrictEqual ( mockResponse . body , { } ) ;
357+ } ) ;
358+
359+ it ( 'should not batchDelete with conditions if "if-unmodified-since" header unset' , async ( ) => {
360+ mockRequest = prepareDummyRequest ( {
361+ 'x-scal-versioning-required' : 'true' ,
362+ 'x-scal-storage-class' : 'azurebackend' ,
363+ } , JSON . stringify ( {
364+ Locations : [
365+ {
366+ key : 'key0' ,
367+ bucket : 'bucket0' ,
368+ } ,
369+ ] ,
370+ } ) ) ;
371+
372+ mockRequest . method = 'POST' ;
373+ mockRequest . url = '/_/backbeat/batchdelete' ;
374+ mockRequest . destroy = ( ) => { } ;
375+ const doAuthStub = sandbox . stub ( auth . server , 'doAuth' ) ;
376+ doAuthStub . callsFake ( ( req , log , cb ) => {
377+ cb ( null , {
378+ canonicalID : 'id' ,
379+ getCanonicalID : ( ) => 'id' ,
380+ } ) ;
381+ } ) ;
382+
383+ routeBackbeat ( '127.0.0.1' , mockRequest , mockResponse , log ) ;
384+
385+ /* eslint-disable-next-line no-void */
386+ void await endPromise ;
387+ assert . strictEqual ( mockResponse . statusCode , 200 ) ;
388+ } ) ;
389+
390+ it ( 'should batchDelete with conditions and non-azure location' , async ( ) => {
391+ const putRequest = prepareDummyRequest ( {
392+ 'x-scal-versioning-required' : 'true' ,
393+ } , JSON . stringify ( {
394+ Locations : [
395+ {
396+ key : 'key0' ,
397+ bucket : 'bucket0' ,
398+ lastModified : '2020-01-01T00:00:00.000Z' ,
399+ } ,
400+ ] ,
401+ } ) ) ;
402+ await promisify ( dataWrapper . client . put ) ( putRequest , 91 , 1 , 'reqUids' ) ;
403+ mockRequest = prepareDummyRequest ( {
404+ 'if-unmodified-since' : '2000-01-01T00:00:00.000Z' ,
405+ 'x-scal-versioning-required' : 'true' ,
406+ 'x-scal-storage-class' : 'gcpbackend' ,
407+ 'x-scal-tags' : JSON . stringify ( { key : 'value' } ) ,
408+ } , JSON . stringify ( {
409+ Locations : [
410+ {
411+ key : 1 ,
412+ bucket : 'bucket0' ,
413+ } ,
414+ ] ,
415+ } ) ) ;
416+ mockRequest . method = 'POST' ;
417+ mockRequest . url = '/_/backbeat/batchdelete' ;
418+ mockRequest . destroy = ( ) => { } ;
419+ const doAuthStub = sandbox . stub ( auth . server , 'doAuth' ) ;
420+ doAuthStub . callsFake ( ( req , log , cb ) => {
421+ cb ( null , {
422+ canonicalID : 'id' ,
423+ getCanonicalID : ( ) => 'id' ,
424+ } ) ;
425+ } ) ;
426+
427+ routeBackbeat ( '127.0.0.1' , mockRequest , mockResponse , log ) ;
428+
429+ /* eslint-disable-next-line no-void */
430+ void await endPromise ;
431+ assert . strictEqual ( mockResponse . statusCode , 200 ) ;
432+ assert . deepStrictEqual ( mockResponse . body , null ) ;
433+ } ) ;
189434} ) ;
0 commit comments