diff --git a/src/blob/authentication/OperationAccountSASPermission.ts b/src/blob/authentication/OperationAccountSASPermission.ts index f9c4dcd53..d119087b2 100644 --- a/src/blob/authentication/OperationAccountSASPermission.ts +++ b/src/blob/authentication/OperationAccountSASPermission.ts @@ -35,7 +35,12 @@ export class OperationAccountSASPermission { public validateResourceTypes( resourceTypes: AccountSASResourceTypes | string ): boolean { - return resourceTypes.toString().includes(this.resourceType); + for (const p of this.resourceType) { + if (resourceTypes.toString().includes(p)) { + return true; + } + } + return false; } public validatePermissions( @@ -61,8 +66,17 @@ OPERATION_ACCOUNT_SAS_PERMISSIONS.set( Operation.Service_GetAccountInfo, new OperationAccountSASPermission( AccountSASService.Blob, - AccountSASResourceType.Service, - AccountSASPermission.Read + AccountSASResourceType.Service + + AccountSASResourceType.Container + + AccountSASResourceType.Object, + AccountSASPermission.Read + + AccountSASPermission.Create + + AccountSASPermission.Delete + + AccountSASPermission.List + + AccountSASPermission.Process + + AccountSASPermission.Read + + AccountSASPermission.Update + + AccountSASPermission.Write ) ); @@ -70,8 +84,17 @@ OPERATION_ACCOUNT_SAS_PERMISSIONS.set( Operation.Service_GetAccountInfoWithHead, new OperationAccountSASPermission( AccountSASService.Blob, - AccountSASResourceType.Service, - AccountSASPermission.Read + AccountSASResourceType.Service + + AccountSASResourceType.Container + + AccountSASResourceType.Object, + AccountSASPermission.Read + + AccountSASPermission.Create + + AccountSASPermission.Delete + + AccountSASPermission.List + + AccountSASPermission.Process + + AccountSASPermission.Read + + AccountSASPermission.Update + + AccountSASPermission.Write ) ); @@ -79,8 +102,17 @@ OPERATION_ACCOUNT_SAS_PERMISSIONS.set( Operation.Container_GetAccountInfo, new OperationAccountSASPermission( AccountSASService.Blob, - AccountSASResourceType.Service, - AccountSASPermission.Read + AccountSASResourceType.Service + + AccountSASResourceType.Container + + AccountSASResourceType.Object, + AccountSASPermission.Read + + AccountSASPermission.Create + + AccountSASPermission.Delete + + AccountSASPermission.List + + AccountSASPermission.Process + + AccountSASPermission.Read + + AccountSASPermission.Update + + AccountSASPermission.Write ) ); @@ -88,8 +120,17 @@ OPERATION_ACCOUNT_SAS_PERMISSIONS.set( Operation.Container_GetAccountInfoWithHead, new OperationAccountSASPermission( AccountSASService.Blob, - AccountSASResourceType.Service, - AccountSASPermission.Read + AccountSASResourceType.Service + + AccountSASResourceType.Container + + AccountSASResourceType.Object, + AccountSASPermission.Read + + AccountSASPermission.Create + + AccountSASPermission.Delete + + AccountSASPermission.List + + AccountSASPermission.Process + + AccountSASPermission.Read + + AccountSASPermission.Update + + AccountSASPermission.Write ) ); @@ -97,8 +138,17 @@ OPERATION_ACCOUNT_SAS_PERMISSIONS.set( Operation.Blob_GetAccountInfo, new OperationAccountSASPermission( AccountSASService.Blob, - AccountSASResourceType.Service, - AccountSASPermission.Read + AccountSASResourceType.Service + + AccountSASResourceType.Container + + AccountSASResourceType.Object, + AccountSASPermission.Read + + AccountSASPermission.Create + + AccountSASPermission.Delete + + AccountSASPermission.List + + AccountSASPermission.Process + + AccountSASPermission.Read + + AccountSASPermission.Update + + AccountSASPermission.Write ) ); @@ -106,8 +156,17 @@ OPERATION_ACCOUNT_SAS_PERMISSIONS.set( Operation.Blob_GetAccountInfoWithHead, new OperationAccountSASPermission( AccountSASService.Blob, - AccountSASResourceType.Service, - AccountSASPermission.Read + AccountSASResourceType.Service + + AccountSASResourceType.Container + + AccountSASResourceType.Object, + AccountSASPermission.Read + + AccountSASPermission.Create + + AccountSASPermission.Delete + + AccountSASPermission.List + + AccountSASPermission.Process + + AccountSASPermission.Read + + AccountSASPermission.Update + + AccountSASPermission.Write ) ); diff --git a/src/blob/handlers/BlobHandler.ts b/src/blob/handlers/BlobHandler.ts index 2159d1eee..8b364049b 100644 --- a/src/blob/handlers/BlobHandler.ts +++ b/src/blob/handlers/BlobHandler.ts @@ -940,7 +940,8 @@ export default class BlobHandler extends BaseHandler implements IBlobHandler { } const response: Models.BlobDownloadResponse = { - statusCode: rangesParts[1] === Infinity ? 200 : 206, + statusCode: + rangesParts[1] === Infinity && rangesParts[0] === 0 ? 200 : 206, body, metadata: blob.metadata, eTag: blob.properties.etag, diff --git a/src/blob/handlers/BlockBlobHandler.ts b/src/blob/handlers/BlockBlobHandler.ts index 3f2ae57eb..0953b43fa 100644 --- a/src/blob/handlers/BlockBlobHandler.ts +++ b/src/blob/handlers/BlockBlobHandler.ts @@ -276,7 +276,8 @@ export default class BlockBlobHandler extends BaseHandler name: blobName, snapshot: "", properties: { - lastModified: new Date(), + lastModified: context.startTime!, + creationTime: context.startTime!, etag: newEtag() }, isCommitted: true diff --git a/src/blob/handlers/PageBlobHandler.ts b/src/blob/handlers/PageBlobHandler.ts index 5280883b2..85f6c87df 100644 --- a/src/blob/handlers/PageBlobHandler.ts +++ b/src/blob/handlers/PageBlobHandler.ts @@ -182,10 +182,7 @@ export default class PageBlobHandler extends BaseHandler ); if (blob.properties.blobType !== Models.BlobType.PageBlob) { - throw StorageErrorFactory.getInvalidOperation( - blobCtx.contextId!, - "Get Page Ranges could only be against a page blob." - ); + throw StorageErrorFactory.getBlobInvalidBlobType(blobCtx.contextId!); } // Check Lease status @@ -276,10 +273,7 @@ export default class PageBlobHandler extends BaseHandler ); if (blob.properties.blobType !== Models.BlobType.PageBlob) { - throw StorageErrorFactory.getInvalidOperation( - blobCtx.contextId!, - "Get Page Ranges could only be against a page blob." - ); + throw StorageErrorFactory.getBlobInvalidBlobType(blobCtx.contextId!); } let ranges; @@ -339,10 +333,7 @@ export default class PageBlobHandler extends BaseHandler ); if (blob.properties.blobType !== Models.BlobType.PageBlob) { - throw StorageErrorFactory.getInvalidOperation( - blobCtx.contextId!, - "Get Page Ranges could only be against a page blob." - ); + throw StorageErrorFactory.getBlobInvalidBlobType(blobCtx.contextId!); } let ranges = deserializePageBlobRangeHeader( diff --git a/src/blob/persistence/LokiBlobMetadataStore.ts b/src/blob/persistence/LokiBlobMetadataStore.ts index f4d1675d0..9f4d4a78b 100644 --- a/src/blob/persistence/LokiBlobMetadataStore.ts +++ b/src/blob/persistence/LokiBlobMetadataStore.ts @@ -1722,6 +1722,9 @@ export default class LokiBlobMetadataStore }); } + if (destBlob) { + coll.remove(destBlob); + } coll.insert(copiedBlob); return copiedBlob.properties; } @@ -1970,6 +1973,7 @@ export default class LokiBlobMetadataStore if (doc) { // Commit block list doc.properties.blobType = blob.properties.blobType; + doc.properties.lastModified = blob.properties.lastModified; doc.committedBlocksInOrder = selectedBlockList; doc.isCommitted = true; doc.metadata = blob.metadata; diff --git a/src/blob/persistence/SqlBlobMetadataStore.ts b/src/blob/persistence/SqlBlobMetadataStore.ts index 971e093ec..3e8e72ca9 100644 --- a/src/blob/persistence/SqlBlobMetadataStore.ts +++ b/src/blob/persistence/SqlBlobMetadataStore.ts @@ -1444,11 +1444,15 @@ export default class SqlBlobMetadataStore implements IBlobMetadataStore { transaction: t }); + let creationTime = blob.properties.creationTime || context.startTime; + if (blobFindResult !== null && blobFindResult !== undefined) { const blobModel: BlobModel = this.convertDbModelToBlobModel( blobFindResult ); + creationTime = blobModel.properties.creationTime || creationTime; + LeaseFactory.createLeaseState( new BlobLeaseAdapter(blobModel), context @@ -1519,7 +1523,7 @@ export default class SqlBlobMetadataStore implements IBlobMetadataStore { committedBlocksInOrder: selectedBlockList, properties: { ...blob.properties, - creationTime: blob.properties.creationTime || context.startTime, + creationTime, lastModified: blob.properties.lastModified || context.startTime, contentLength: selectedBlockList .map(block => block.size) diff --git a/src/queue/authentication/OperationAccountSASPermission.ts b/src/queue/authentication/OperationAccountSASPermission.ts index 6a1781779..477f76fa5 100644 --- a/src/queue/authentication/OperationAccountSASPermission.ts +++ b/src/queue/authentication/OperationAccountSASPermission.ts @@ -35,7 +35,12 @@ export class OperationAccountSASPermission { public validateResourceTypes( resourceTypes: AccountSASResourceTypes | string ): boolean { - return resourceTypes.toString().includes(this.resourceType); + for (const p of this.resourceType) { + if (resourceTypes.toString().includes(p)) { + return true; + } + } + return false; } public validatePermissions( diff --git a/tests/blob/apis/blockblob.test.ts b/tests/blob/apis/blockblob.test.ts index d86011609..917cbd5c3 100644 --- a/tests/blob/apis/blockblob.test.ts +++ b/tests/blob/apis/blockblob.test.ts @@ -237,6 +237,10 @@ describe("BlockBlobAPIs", () => { result_commit._response.request.headers.get("x-ms-client-request-id"), result_commit.clientRequestId ); + + const properties1 = await blockBlobURL.getProperties(Aborter.none); + assert.notDeepStrictEqual(properties1.creationTime, undefined); + const listResponse = await blockBlobURL.getBlockList( Aborter.none, "committed" @@ -259,6 +263,10 @@ describe("BlockBlobAPIs", () => { assert.equal(listResponse2.committedBlocks!.length, 1); assert.equal(listResponse2.committedBlocks![0].name, base64encode("2")); assert.equal(listResponse2.committedBlocks![0].size, body.length); + + const properties2 = await blockBlobURL.getProperties(Aborter.none); + assert.notDeepStrictEqual(properties2.creationTime, undefined); + assert.deepStrictEqual(properties1.creationTime, properties2.creationTime); }); it("commitBlockList with empty list should create an empty block blob @loki @sql", async () => { diff --git a/tests/blob/apis/pageblob.test.ts b/tests/blob/apis/pageblob.test.ts index 724c02c73..acf099183 100644 --- a/tests/blob/apis/pageblob.test.ts +++ b/tests/blob/apis/pageblob.test.ts @@ -152,7 +152,7 @@ describe("PageBlobAPIs", () => { ranges._response.request.headers.get("x-ms-client-request-id"), ranges.clientRequestId ); - const result = await blobURL.download(Aborter.none, 0, 10); + let result = await blobURL.download(Aborter.none, 0, 10); assert.deepStrictEqual(result.contentRange, `bytes 0-9/5120`); assert.deepStrictEqual( await bodyToString(result, length), @@ -162,6 +162,10 @@ describe("PageBlobAPIs", () => { result._response.request.headers.get("x-ms-client-request-id"), result.clientRequestId ); + + result = await blobURL.download(Aborter.none, 1); + assert.deepStrictEqual(result.contentRange, `bytes 1-5119/5120`); + assert.deepStrictEqual(result._response.status, 206); }); it("download page blob with no ranges uploaded @loki", async () => {