Skip to content

Commit

Permalink
port: [#6813][#6798] Not able to create instance of BlobsTranscriptSt…
Browse files Browse the repository at this point in the history
…ore using TokenCredential instead of connectionString and containerName (#4720)

* add token credential authentication

* added constructor validations

* update botbuilder-azure-blobs.api
  • Loading branch information
JhontSouth authored Jul 31, 2024
1 parent 364fae8 commit 543f70c
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,19 @@ 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<void>;
getTranscriptActivities(channelId: string, conversationId: string, continuationToken?: string, startDate?: Date): Promise<PagedResult<Activity>>;
listTranscripts(channelId: string, continuationToken?: string): Promise<PagedResult<TranscriptInfo>>;
logActivity(activity: Activity, options?: BlobsTranscriptStoreOptions): Promise<void>;
}
}

// @public
export interface BlobsTranscriptStoreOptions {
decodeTranscriptKey?: boolean;
storagePipelineOptions?: StoragePipelineOptions;
}


// (No @packageDocumentation comment for this package)

```
62 changes: 52 additions & 10 deletions libraries/botbuilder-azure-blobs/src/blobsTranscriptStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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 () {
Expand Down

0 comments on commit 543f70c

Please sign in to comment.