diff --git a/libraries/botbuilder-azure-blobs/etc/botbuilder-azure-blobs.api.md b/libraries/botbuilder-azure-blobs/etc/botbuilder-azure-blobs.api.md index ae1cf9b3a8..c3b31d86db 100644 --- a/libraries/botbuilder-azure-blobs/etc/botbuilder-azure-blobs.api.md +++ b/libraries/botbuilder-azure-blobs/etc/botbuilder-azure-blobs.api.md @@ -30,12 +30,12 @@ export interface BlobsStorageOptions { // @public export class BlobsTranscriptStore implements TranscriptStore { - constructor(connectionString: string, containerName: string, options?: BlobsTranscriptStoreOptions); + constructor(connectionString: string, containerName: string, options?: BlobsTranscriptStoreOptions, blobServiceUri?: string, tokenCredential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential); deleteTranscript(channelId: string, conversationId: string): Promise; getTranscriptActivities(channelId: string, conversationId: string, continuationToken?: string, startDate?: Date): Promise>; listTranscripts(channelId: string, continuationToken?: string): Promise>; logActivity(activity: Activity, options?: BlobsTranscriptStoreOptions): Promise; - } +} // @public export interface BlobsTranscriptStoreOptions { @@ -43,7 +43,6 @@ export interface BlobsTranscriptStoreOptions { storagePipelineOptions?: StoragePipelineOptions; } - // (No @packageDocumentation comment for this package) ``` diff --git a/libraries/botbuilder-azure-blobs/src/blobsTranscriptStore.ts b/libraries/botbuilder-azure-blobs/src/blobsTranscriptStore.ts index a2ed4ff606..a1e68ac6ca 100644 --- a/libraries/botbuilder-azure-blobs/src/blobsTranscriptStore.ts +++ b/libraries/botbuilder-azure-blobs/src/blobsTranscriptStore.ts @@ -9,10 +9,13 @@ import { maybeCast } from 'botbuilder-stdlib'; import { sanitizeBlobKey } from './sanitizeBlobKey'; import { + AnonymousCredential, ContainerClient, ContainerListBlobHierarchySegmentResponse, StoragePipelineOptions, + StorageSharedKeyCredential, } from '@azure/storage-blob'; +import { isTokenCredential, TokenCredential } from '@azure/core-http'; // Formats a timestamp in a way that is consistent with the C# SDK function formatTicks(timestamp: Date): string { @@ -45,6 +48,12 @@ function getBlobKey(activity: Activity, options?: BlobsTranscriptStoreOptions): ); } +function isCredentialType(value: any): value is TokenCredential { + return ( + isTokenCredential(value) || value instanceof StorageSharedKeyCredential || value instanceof AnonymousCredential + ); +} + // Max number of results returned in a single Azure API call const MAX_PAGE_SIZE = 20; @@ -85,21 +94,54 @@ export class BlobsTranscriptStore implements TranscriptStore { * @param {string} connectionString Azure Blob Storage connection string * @param {string} containerName Azure Blob Storage container name * @param {BlobsTranscriptStoreOptions} options Other options for BlobsTranscriptStore + * @param {string} blobServiceUri A Uri referencing the blob container that includes the name of the account and the name of the container + * @param {StorageSharedKeyCredential | AnonymousCredential | TokenCredential} tokenCredential The token credential to authenticate to the Azure storage */ - constructor(connectionString: string, containerName: string, options?: BlobsTranscriptStoreOptions) { - z.object({ connectionString: z.string(), containerName: z.string() }).parse({ - connectionString, - containerName, - }); + constructor( + connectionString: string, + containerName: string, + options?: BlobsTranscriptStoreOptions, + blobServiceUri = '', + tokenCredential?: StorageSharedKeyCredential | AnonymousCredential | TokenCredential + ) { + if (blobServiceUri != '' && tokenCredential != null) { + z.object({ blobServiceUri: z.string() }).parse({ + blobServiceUri, + }); - this._containerClient = new ContainerClient(connectionString, containerName, options?.storagePipelineOptions); + if (typeof tokenCredential != 'object' || !isCredentialType(tokenCredential)) { + throw new ReferenceError('Invalid credential type.'); + } - this._isDecodeTranscriptKey = options?.decodeTranscriptKey; + this._containerClient = new ContainerClient( + blobServiceUri, + tokenCredential, + options?.storagePipelineOptions + ); - // At most one promise at a time to be friendly to local emulator users - if (connectionString.trim() === 'UseDevelopmentStorage=true;') { - this._concurrency = 1; + // At most one promise at a time to be friendly to local emulator users + if (blobServiceUri.trim() === 'UseDevelopmentStorage=true;') { + this._concurrency = 1; + } + } else { + z.object({ connectionString: z.string(), containerName: z.string() }).parse({ + connectionString, + containerName, + }); + + this._containerClient = new ContainerClient( + connectionString, + containerName, + options?.storagePipelineOptions + ); + + // At most one promise at a time to be friendly to local emulator users + if (connectionString.trim() === 'UseDevelopmentStorage=true;') { + this._concurrency = 1; + } } + + this._isDecodeTranscriptKey = options?.decodeTranscriptKey; } // Protects against JSON.stringify cycles diff --git a/libraries/botbuilder-azure-blobs/tests/blobsTranscriptStore.test.js b/libraries/botbuilder-azure-blobs/tests/blobsTranscriptStore.test.js index 132439871c..0399ad5255 100644 --- a/libraries/botbuilder-azure-blobs/tests/blobsTranscriptStore.test.js +++ b/libraries/botbuilder-azure-blobs/tests/blobsTranscriptStore.test.js @@ -11,7 +11,7 @@ const containerName = process.env.AZURE_BLOB_STORAGE_CONTAINER; const maybeClient = () => connectionString && containerName ? new BlobsTranscriptStore(connectionString, containerName) : null; -describe('BlobsStorage', function () { +describe('BlobsTranscriptStore', function () { const client = maybeClient(); const maybeIt = client ? it : it.skip; @@ -69,6 +69,11 @@ describe('BlobsStorage', function () { it('throws for bad args', function () { assert.throws(() => new BlobsTranscriptStore(), 'throws for missing connectionString'); assert.throws(() => new BlobsTranscriptStore('connectionString'), 'throws for missing containerName'); + assert.throws(() => new BlobsTranscriptStore(null, null, null, [], {}), 'throws for missing url'); + assert.throws( + () => new BlobsTranscriptStore(null, null, null, 'url', {}), + ReferenceError('Invalid credential type.') + ); }); it('succeeds for good args', function () {