diff --git a/sdk/storage/storage-blob/CHANGELOG.md b/sdk/storage/storage-blob/CHANGELOG.md index ece4cd540d03..013882254578 100644 --- a/sdk/storage/storage-blob/CHANGELOG.md +++ b/sdk/storage/storage-blob/CHANGELOG.md @@ -2,6 +2,7 @@ ## 12.4.0-beta.2 (Unreleased) +- Added a new `from(permissionLike)` function to `AccountSASPermissions`, `BlobSASPermissions` and `ContainerSASPermissions` for creating such a permission from a raw permission-like object. Addressed issue [9714](https://github.com/Azure/azure-sdk-for-js/issues/9714). ## 12.4.0-beta.1 (2020-12-09) diff --git a/sdk/storage/storage-blob/recordings/node/shared_access_signature_sas_generation_nodejs_only/recording_sas_permission_parse_from_raw_object_should_work.js b/sdk/storage/storage-blob/recordings/node/shared_access_signature_sas_generation_nodejs_only/recording_sas_permission_parse_from_raw_object_should_work.js new file mode 100644 index 000000000000..2503ca0a3f47 --- /dev/null +++ b/sdk/storage/storage-blob/recordings/node/shared_access_signature_sas_generation_nodejs_only/recording_sas_permission_parse_from_raw_object_should_work.js @@ -0,0 +1,5 @@ +let nock = require('nock'); + +module.exports.hash = "289db09825e2b32795f634e714b81ae7"; + +module.exports.testInfo = {"uniqueName":{},"newDate":{}} diff --git a/sdk/storage/storage-blob/review/storage-blob.api.md b/sdk/storage/storage-blob/review/storage-blob.api.md index ffccdf0e9920..03ee99aa60dc 100644 --- a/sdk/storage/storage-blob/review/storage-blob.api.md +++ b/sdk/storage/storage-blob/review/storage-blob.api.md @@ -50,6 +50,7 @@ export class AccountSASPermissions { delete: boolean; deleteVersion: boolean; filter: boolean; + static from(permissionLike: AccountSASPermissionsLike): AccountSASPermissions; list: boolean; static parse(permissions: string): AccountSASPermissions; process: boolean; @@ -60,6 +61,21 @@ export class AccountSASPermissions { write: boolean; } +// @public +export interface AccountSASPermissionsLike { + add?: boolean; + create?: boolean; + delete?: boolean; + deleteVersion?: boolean; + filter?: boolean; + list?: boolean; + process?: boolean; + read?: boolean; + tag?: boolean; + update?: boolean; + write?: boolean; +} + // @public export class AccountSASResourceTypes { container: boolean; @@ -1006,6 +1022,7 @@ export class BlobSASPermissions { delete: boolean; deleteVersion: boolean; execute: boolean; + static from(permissionLike: BlobSASPermissionsLike): BlobSASPermissions; move: boolean; static parse(permissions: string): BlobSASPermissions; read: boolean; @@ -1014,6 +1031,19 @@ export class BlobSASPermissions { write: boolean; } +// @public +export interface BlobSASPermissionsLike { + add?: boolean; + create?: boolean; + delete?: boolean; + deleteVersion?: boolean; + execute?: boolean; + move?: boolean; + read?: boolean; + tag?: boolean; + write?: boolean; +} + // @public export interface BlobSASSignatureValues { blobName?: string; @@ -1916,6 +1946,7 @@ export class ContainerSASPermissions { delete: boolean; deleteVersion: boolean; execute: boolean; + static from(permissionLike: ContainerSASPermissionsLike): ContainerSASPermissions; list: boolean; move: boolean; static parse(permissions: string): ContainerSASPermissions; @@ -1925,6 +1956,20 @@ export class ContainerSASPermissions { write: boolean; } +// @public +export interface ContainerSASPermissionsLike { + add?: boolean; + create?: boolean; + delete?: boolean; + deleteVersion?: boolean; + execute?: boolean; + list?: boolean; + move?: boolean; + read?: boolean; + tag?: boolean; + write?: boolean; +} + // @public export interface ContainerSetAccessPolicyHeaders { clientRequestId?: string; diff --git a/sdk/storage/storage-blob/src/sas/AccountSASPermissions.ts b/sdk/storage/storage-blob/src/sas/AccountSASPermissions.ts index 4e1c030e1b68..850659fa012c 100644 --- a/sdk/storage/storage-blob/src/sas/AccountSASPermissions.ts +++ b/sdk/storage/storage-blob/src/sas/AccountSASPermissions.ts @@ -68,6 +68,53 @@ export class AccountSASPermissions { return accountSASPermissions; } + /** + * Creates a {@link AccountSASPermissions} from a raw object which contains same keys as it + * and boolean values for them. + * + * @static + * @param {AccountSASPermissionsLike} permissionLike + * @returns {AccountSASPermissions} + * @memberof AccountSASPermissions + */ + public static from(permissionLike: AccountSASPermissionsLike): AccountSASPermissions { + const accountSASPermissions = new AccountSASPermissions(); + if (permissionLike.read) { + accountSASPermissions.read = true; + } + if (permissionLike.write) { + accountSASPermissions.write = true; + } + if (permissionLike.delete) { + accountSASPermissions.delete = true; + } + if (permissionLike.deleteVersion) { + accountSASPermissions.deleteVersion = true; + } + if (permissionLike.filter) { + accountSASPermissions.filter = true; + } + if (permissionLike.tag) { + accountSASPermissions.tag = true; + } + if (permissionLike.list) { + accountSASPermissions.list = true; + } + if (permissionLike.add) { + accountSASPermissions.add = true; + } + if (permissionLike.create) { + accountSASPermissions.create = true; + } + if (permissionLike.update) { + accountSASPermissions.update = true; + } + if (permissionLike.process) { + accountSASPermissions.process = true; + } + return accountSASPermissions; + } + /** * Permission to read resources and list queues and tables granted. * @@ -209,3 +256,97 @@ export class AccountSASPermissions { return permissions.join(""); } } + +/** + * A type that looks like an account SAS permission. + * Used in {@link AccountSASPermissions} to parse SAS permissions from raw objects. + */ +export interface AccountSASPermissionsLike { + /** + * Permission to read resources and list queues and tables granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + read?: boolean; + + /** + * Permission to write resources granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + write?: boolean; + + /** + * Permission to create blobs and files granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + delete?: boolean; + + /** + * Permission to delete versions granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + deleteVersion?: boolean; + + /** + * Permission to list blob containers, blobs, shares, directories, and files granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + list?: boolean; + + /** + * Permission to add messages, table entities, and append to blobs granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + add?: boolean; + + /** + * Permission to create blobs and files granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + create?: boolean; + + /** + * Permissions to update messages and table entities granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + update?: boolean; + + /** + * Permission to get and delete messages granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + process?: boolean; + + /** + * Specfies Tag access granted. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + tag?: boolean; + + /** + * Permission to filter blobs. + * + * @type {boolean} + * @memberof AccountSASPermissionsLike + */ + filter?: boolean; +} diff --git a/sdk/storage/storage-blob/src/sas/BlobSASPermissions.ts b/sdk/storage/storage-blob/src/sas/BlobSASPermissions.ts index 3aec48133dfd..8e49fee8d23b 100644 --- a/sdk/storage/storage-blob/src/sas/BlobSASPermissions.ts +++ b/sdk/storage/storage-blob/src/sas/BlobSASPermissions.ts @@ -63,6 +63,47 @@ export class BlobSASPermissions { return blobSASPermissions; } + /** + * Creates a {@link BlobSASPermissions} from a raw object which contains same keys as it + * and boolean values for them. + * + * @static + * @param {BlobSASPermissionsLike} permissionLike + * @returns {BlobSASPermissions} + * @memberof BlobSASPermissions + */ + public static from(permissionLike: BlobSASPermissionsLike): BlobSASPermissions { + const blobSASPermissions = new BlobSASPermissions(); + if (permissionLike.read) { + blobSASPermissions.read = true; + } + if (permissionLike.add) { + blobSASPermissions.add = true; + } + if (permissionLike.create) { + blobSASPermissions.create = true; + } + if (permissionLike.write) { + blobSASPermissions.write = true; + } + if (permissionLike.delete) { + blobSASPermissions.delete = true; + } + if (permissionLike.deleteVersion) { + blobSASPermissions.deleteVersion = true; + } + if (permissionLike.tag) { + blobSASPermissions.tag = true; + } + if (permissionLike.move) { + blobSASPermissions.move = true; + } + if (permissionLike.execute) { + blobSASPermissions.execute = true; + } + return blobSASPermissions; + } + /** * Specifies Read access granted. * @@ -174,3 +215,81 @@ export class BlobSASPermissions { return permissions.join(""); } } + +/** + * A type that looks like a Blob SAS permission. + * Used in {@link BlobSASPermissions} to parse SAS permissions from raw objects. + */ +export interface BlobSASPermissionsLike { + /** + * Specifies Read access granted. + * + * @type {boolean} + * @memberof BlobSASPermissionsLike + */ + read?: boolean; + + /** + * Specifies Add access granted. + * + * @type {boolean} + * @memberof BlobSASPermissionsLike + */ + add?: boolean; + + /** + * Specifies Create access granted. + * + * @type {boolean} + * @memberof BlobSASPermissionsLike + */ + create?: boolean; + + /** + * Specifies Write access granted. + * + * @type {boolean} + * @memberof BlobSASPermissionsLike + */ + write?: boolean; + + /** + * Specifies Delete access granted. + * + * @type {boolean} + * @memberof BlobSASPermissionsLike + */ + delete?: boolean; + + /** + * Specifies Delete version access granted. + * + * @type {boolean} + * @memberof BlobSASPermissionsLike + */ + deleteVersion?: boolean; + + /** + * Specfies Tag access granted. + * + * @type {boolean} + * @memberof BlobSASPermissionsLike + */ + tag?: boolean; + + /** + * Specifies Move access granted. + * + * @type {boolean} + * @memberof BlobSASPermissionsLike + */ + move?: boolean; + + /** + * Specifies Execute access granted. + * + * @type {boolean} + * @memberof BlobSASPermissionsLike + */ + execute?: boolean; +} diff --git a/sdk/storage/storage-blob/src/sas/BlobSASSignatureValues.ts b/sdk/storage/storage-blob/src/sas/BlobSASSignatureValues.ts index 6aa1164f81cf..b002496a005b 100644 --- a/sdk/storage/storage-blob/src/sas/BlobSASSignatureValues.ts +++ b/sdk/storage/storage-blob/src/sas/BlobSASSignatureValues.ts @@ -384,8 +384,7 @@ function generateBlobSASQueryParameters20150405( if ( !blobSASSignatureValues.identifier && - !blobSASSignatureValues.permissions && - !blobSASSignatureValues.expiresOn + !(blobSASSignatureValues.permissions && blobSASSignatureValues.expiresOn) ) { throw new RangeError( "Must provide 'permissions' and 'expiresOn' for Blob SAS generation when 'identifier' is not provided." @@ -483,8 +482,7 @@ function generateBlobSASQueryParameters20181109( if ( !blobSASSignatureValues.identifier && - !blobSASSignatureValues.permissions && - !blobSASSignatureValues.expiresOn + !(blobSASSignatureValues.permissions && blobSASSignatureValues.expiresOn) ) { throw new RangeError( "Must provide 'permissions' and 'expiresOn' for Blob SAS generation when 'identifier' is not provided." diff --git a/sdk/storage/storage-blob/src/sas/ContainerSASPermissions.ts b/sdk/storage/storage-blob/src/sas/ContainerSASPermissions.ts index 96004df31cc4..451c83f8906b 100644 --- a/sdk/storage/storage-blob/src/sas/ContainerSASPermissions.ts +++ b/sdk/storage/storage-blob/src/sas/ContainerSASPermissions.ts @@ -64,6 +64,50 @@ export class ContainerSASPermissions { return containerSASPermissions; } + /** + * Creates a {@link ContainerSASPermissions} from a raw object which contains same keys as it + * and boolean values for them. + * + * @static + * @param {ContainerSASPermissionsLike} permissionLike + * @returns {ContainerSASPermissions} + * @memberof ContainerSASPermissions + */ + public static from(permissionLike: ContainerSASPermissionsLike): ContainerSASPermissions { + const containerSASPermissions = new ContainerSASPermissions(); + if (permissionLike.read) { + containerSASPermissions.read = true; + } + if (permissionLike.add) { + containerSASPermissions.add = true; + } + if (permissionLike.create) { + containerSASPermissions.create = true; + } + if (permissionLike.write) { + containerSASPermissions.write = true; + } + if (permissionLike.delete) { + containerSASPermissions.delete = true; + } + if (permissionLike.list) { + containerSASPermissions.list = true; + } + if (permissionLike.deleteVersion) { + containerSASPermissions.deleteVersion = true; + } + if (permissionLike.tag) { + containerSASPermissions.tag = true; + } + if (permissionLike.move) { + containerSASPermissions.move = true; + } + if (permissionLike.execute) { + containerSASPermissions.execute = true; + } + return containerSASPermissions; + } + /** * Specifies Read access granted. * @@ -189,3 +233,89 @@ export class ContainerSASPermissions { return permissions.join(""); } } + +/** + * A type that looks like a Container SAS permission. + * Used in {@link ContainerSASPermissions} to parse SAS permissions from raw objects. + */ +export interface ContainerSASPermissionsLike { + /** + * Specifies Read access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + read?: boolean; + + /** + * Specifies Add access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + add?: boolean; + + /** + * Specifies Create access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + create?: boolean; + + /** + * Specifies Write access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + write?: boolean; + + /** + * Specifies Delete access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + delete?: boolean; + + /** + * Specifies Delete version access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + deleteVersion?: boolean; + + /** + * Specifies List access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + list?: boolean; + + /** + * Specfies Tag access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + tag?: boolean; + + /** + * Specifies Move access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + move?: boolean; + + /** + * Specifies Execute access granted. + * + * @type {boolean} + * @memberof ContainerSASPermissionsLike + */ + execute?: boolean; +} diff --git a/sdk/storage/storage-blob/test/node/sas.spec.ts b/sdk/storage/storage-blob/test/node/sas.spec.ts index ca512c6e71cd..b58a7bb0540f 100644 --- a/sdk/storage/storage-blob/test/node/sas.spec.ts +++ b/sdk/storage/storage-blob/test/node/sas.spec.ts @@ -1512,6 +1512,29 @@ describe("Shared Access Signature (SAS) generation Node.js only", () => { await containerClient.delete(); }); + + it("SAS permission parse from raw object should work", async () => { + const orderedBlobPermissionStr = "racwdxtme"; + const blobPermission = BlobSASPermissions.parse(orderedBlobPermissionStr); + assert.deepStrictEqual( + BlobSASPermissions.from(blobPermission).toString(), + orderedBlobPermissionStr + ); + + const orderedContainerPermissionStr = "racwdxltme"; + const containerPermission = ContainerSASPermissions.parse(orderedContainerPermissionStr); + assert.deepStrictEqual( + ContainerSASPermissions.from(containerPermission).toString(), + orderedContainerPermissionStr + ); + + const orderedAccountPermissionStr = "rwdxftlacup"; + const accountPermission = AccountSASPermissions.parse(orderedAccountPermissionStr); + assert.deepStrictEqual( + AccountSASPermissions.from(accountPermission).toString(), + orderedAccountPermissionStr + ); + }); }); describe("Generation for user delegation SAS Node.js only", () => { diff --git a/sdk/storage/storage-file-datalake/src/sas/DataLakeSASSignatureValues.ts b/sdk/storage/storage-file-datalake/src/sas/DataLakeSASSignatureValues.ts index 2849963a0bd4..9e2aeb8ee522 100644 --- a/sdk/storage/storage-file-datalake/src/sas/DataLakeSASSignatureValues.ts +++ b/sdk/storage/storage-file-datalake/src/sas/DataLakeSASSignatureValues.ts @@ -384,8 +384,7 @@ function generateBlobSASQueryParameters20150405( ): SASQueryParameters { if ( !dataLakeSASSignatureValues.identifier && - !dataLakeSASSignatureValues.permissions && - !dataLakeSASSignatureValues.expiresOn + !(dataLakeSASSignatureValues.permissions && dataLakeSASSignatureValues.expiresOn) ) { throw new RangeError( "Must provide 'permissions' and 'expiresOn' for DataLake SAS generation when 'identifier' is not provided." @@ -488,8 +487,7 @@ function generateBlobSASQueryParameters20181109( ): SASQueryParameters { if ( !dataLakeSASSignatureValues.identifier && - !dataLakeSASSignatureValues.permissions && - !dataLakeSASSignatureValues.expiresOn + !(dataLakeSASSignatureValues.permissions && dataLakeSASSignatureValues.expiresOn) ) { throw new RangeError( "Must provide 'permissions' and 'expiresOn' for Blob SAS generation when 'identifier' is not provided." diff --git a/sdk/storage/storage-file-share/src/FileSASSignatureValues.ts b/sdk/storage/storage-file-share/src/FileSASSignatureValues.ts index 5e8d2fe3c1cc..fb32af28b551 100644 --- a/sdk/storage/storage-file-share/src/FileSASSignatureValues.ts +++ b/sdk/storage/storage-file-share/src/FileSASSignatureValues.ts @@ -160,8 +160,7 @@ export function generateFileSASQueryParameters( ): SASQueryParameters { if ( !fileSASSignatureValues.identifier && - !fileSASSignatureValues.permissions && - !fileSASSignatureValues.expiresOn + !(fileSASSignatureValues.permissions && fileSASSignatureValues.expiresOn) ) { throw new RangeError( "Must provide 'permissions' and 'expiresOn' for File SAS generation when 'identifier' is not provided." diff --git a/sdk/storage/storage-queue/src/QueueSASSignatureValues.ts b/sdk/storage/storage-queue/src/QueueSASSignatureValues.ts index 1e6365416369..21acc69182e5 100644 --- a/sdk/storage/storage-queue/src/QueueSASSignatureValues.ts +++ b/sdk/storage/storage-queue/src/QueueSASSignatureValues.ts @@ -111,8 +111,7 @@ export function generateQueueSASQueryParameters( ): SASQueryParameters { if ( !queueSASSignatureValues.identifier && - !queueSASSignatureValues.permissions && - !queueSASSignatureValues.expiresOn + !(queueSASSignatureValues.permissions && queueSASSignatureValues.expiresOn) ) { throw new RangeError( "Must provide 'permissions' and 'expiresOn' for Queue SAS generation when 'identifier' is not provided."