Skip to content
This repository has been archived by the owner on Jun 30, 2022. It is now read-only.

[TypeScript][Bot-Solutions] Implement changes in Bot-Solutions to 1.0 release #3583

Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import { BotFrameworkAdapter, TurnContext } from 'botbuilder';
import { Choice, ChoicePrompt, ComponentDialog, DialogTurnResult, DialogTurnStatus, FoundChoice,
OAuthPrompt, PromptValidatorContext, WaterfallDialog, WaterfallStep, WaterfallStepContext,
OAuthPromptSettings } from 'botbuilder-dialogs';
import { TokenStatus } from 'botframework-connector/lib/tokenApi/models';
import { TokenStatus } from 'botframework-connector';
import { ActionTypes, Activity, ActivityTypes, TokenResponse } from 'botframework-schema';
import { IOAuthConnection } from '../authentication';
import { ResponseManager } from '../responses';
import { TokenEvents } from '../tokenEvents';
import { AuthenticationResponses } from './authenticationResponses';
import { OAuthProviderExtensions } from './oAuthProviderExtensions';
import { IProviderTokenResponse } from './providerTokenResponse';
import { AppCredentials } from 'botframework-connector';

enum DialogIds {
providerPrompt = 'ProviderPrompt',
Expand All @@ -29,17 +30,19 @@ export class MultiProviderAuthDialog extends ComponentDialog {
private selectedAuthType: string = '';
private authenticationConnections: IOAuthConnection[];
private responseManager: ResponseManager;
private oauthCredentials: AppCredentials | undefined;

public constructor(
authenticationConnections: IOAuthConnection[],
promptSettings: OAuthPromptSettings[],
locale: string
locale: string,
promptSettings?: OAuthPromptSettings[],
oauthCredentials?: AppCredentials
) {
super(MultiProviderAuthDialog.name);

if (authenticationConnections === undefined) { throw new Error('The value of authenticationConnections cannot be undefined'); }
this.authenticationConnections = authenticationConnections;

this.oauthCredentials = oauthCredentials;
this.responseManager = new ResponseManager(
['en', 'de', 'es', 'fr', 'it', 'zh'],
[AuthenticationResponses]
Expand Down Expand Up @@ -67,12 +70,13 @@ export class MultiProviderAuthDialog extends ComponentDialog {
// We ignore placeholder connections in config that don't have a Name
if (connection.name !== undefined && connection.name.trim().length > 0) {
const loginButtonActivity: Partial<Activity> = this.responseManager.getResponse(AuthenticationResponses.loginButton, locale);
const loginPromptActivity: Partial<Activity> = this.responseManager.getResponse(AuthenticationResponses.loginPrompt, locale);
const settings: OAuthPromptSettings = promptSettings[i] || {
const loginPromptActivity: Partial<Activity> = this.responseManager.getResponse(AuthenticationResponses.loginPrompt, locale, new Map<string, string>([['authType', connection.name]]));
const settings: OAuthPromptSettings = promptSettings !== undefined ? promptSettings[i] : {
connectionName: connection.name,
title: loginButtonActivity,
text: loginPromptActivity
title: loginButtonActivity.text || '',
text: loginPromptActivity.text || ''
};
settings.oAuthAppCredentials = this.oauthCredentials;

this.addDialog(new OAuthPrompt(
connection.name,
Expand All @@ -82,16 +86,16 @@ export class MultiProviderAuthDialog extends ComponentDialog {
}
};

this.addDialog(new WaterfallDialog(DialogIds.firstStepPrompt, authSteps));
this.addDialog(new WaterfallDialog(DialogIds.authPrompt, authSteps));
this.addDialog(new ChoicePrompt(DialogIds.providerPrompt));
} else {
throw new Error('There is no authenticationConnections value');
}
}

// Validators
protected async tokenResponseValidator(promptContext: PromptValidatorContext<Activity>): Promise<boolean> {
const activity: Activity | undefined = promptContext.recognized.value;
protected async tokenResponseValidator(pc: PromptValidatorContext<Activity>): Promise<boolean> {
const activity: Activity | undefined = pc.recognized.value;
if (activity !== undefined &&
((activity.type === ActivityTypes.Event && activity.name === TokenEvents.tokenResponseEventName) ||
(activity.type === ActivityTypes.Invoke && activity.name === 'signin/verifyState'))) {
Expand All @@ -112,11 +116,14 @@ export class MultiProviderAuthDialog extends ComponentDialog {
return await stepContext.next(result);
}

//PENDING: adapter could not be parsed to IExtendedUserTokenProvider as C# does
const adapter: BotFrameworkAdapter = stepContext.context.adapter as BotFrameworkAdapter;
if (adapter !== undefined) {
const tokenStatusCollection: TokenStatus[] = await adapter.getTokenStatus(
stepContext.context,
stepContext.context.activity.from.id);
stepContext.context.activity.from.id,
undefined,
this.oauthCredentials);

const matchingProviders: TokenStatus[] = tokenStatusCollection.filter((p: TokenStatus): boolean => {
return (p.hasToken || false) && this.authenticationConnections.some((t: IOAuthConnection): boolean => {
Expand Down Expand Up @@ -224,11 +231,12 @@ export class MultiProviderAuthDialog extends ComponentDialog {
throw new Error('"userId" undefined');
}

//PENDING: adapter could not be parsed to IExtendedUserTokenProvider as C# does
const tokenProvider: BotFrameworkAdapter = context.adapter as BotFrameworkAdapter;
if (tokenProvider !== undefined) {
return await tokenProvider.getTokenStatus(context, userId, includeFilter);
return await tokenProvider.getTokenStatus(context, userId, includeFilter, this.oauthCredentials);
} else {
throw new Error('Adapter does not support IUserTokenProvider');
throw new Error('Adapter does not support IExtendedUserTokenProvider');
}
}

Expand Down
112 changes: 0 additions & 112 deletions sdk/typescript/libraries/bot-solutions/src/botSettings.ts

This file was deleted.

150 changes: 150 additions & 0 deletions sdk/typescript/libraries/bot-solutions/src/botSettingsBase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
/**
* Copyright(c) Microsoft Corporation.All rights reserved.
* Licensed under the MIT License.
*/

import { CosmosDbPartitionedStorageOptions } from 'botbuilder-azure';
import { LuisService, QnaMakerService } from 'botframework-config';
import { IOAuthConnection } from './authentication';

/**
* Base interface representing the configuration for a bot.
*/
export interface BotSettingsBase {
/**
* Gets or sets the Microsoft Application Id.
* The Microsoft Application Id.
*/
microsoftAppId: string;

/**
* Gets or sets the Microsoft Application Password.
* The Microsoft Application Password.
*/
microsoftAppPassword: string;

/**
* Gets or sets the default locale of the bot.
* The default locale of the bot.
*/
defaultLocale: string;

/**
* Gets or sets the voiceFont for the bot.
* The default voice font of the bot.
*/
voiceFont: string;

/**
* Gets or sets the OAuth Connections for the bot.
* The OAuth Connections for the bot.
*/
oauthConnections: IOAuthConnection[];

/**
* Gets or sets the OAuthCredentials for OAuth.
* The OAuthCredentials for OAuth for the bot.
*/
oauthCredentials: OAuthCredentialsConfiguration;

/**
* Gets or sets the CosmosDB Configuration for the bot.
* The CosmosDB Configuration for the bot.
*/
cosmosDb: CosmosDbPartitionedStorageOptions;

/**
* Gets or sets the Application Insights configuration for the bot.
* The Application Insights configuration for the bot.
*/
appInsights: TelemetryConfiguration;

/**
* Gets or sets the Azure Blob Storage configuration for the bot.
* The Azure Blob Storage configuration for the bot.
*/
blobStorage: BlobStorageConfiguration;

/**
* Gets or sets the Azure Content Moderator configuration for the bot.
* The Azure Content Moderator configuration for the bot.
*/
contentModerator: ContentModeratorConfiguration;

/**
* Gets or sets the dictionary of cognitive model configurations by locale for the bot.
* The dictionary of cognitive model configurations by locale for the bot.
*/
cognitiveModels: Map<string, CognitiveModelConfiguration>;

/**
* Gets or sets the Properties dictionary.
* The Properties dictionary.
*/
properties: Map<string, string>;
}

export interface TelemetryConfiguration {
instrumentationKey: string;
}

/**
* Class representing configuration for an Azure Blob Storage service.
*/
export interface BlobStorageConfiguration {
/**
* Gets or sets the connection string for the Azure Blob Storage service.
* The connection string for the Azure Blob Storage service.
*/
connectionString: string;
/**
* Gets or sets the blob container for the Azure Blob Storage service.
* The blob container for the Azure Blob Storage service.
*/
container: string;
}

/**
* Class representing configuration for an Azure Content Moderator service.
*/
export interface ContentModeratorConfiguration {
/**
* Gets or sets the subscription key for the Content Moderator service.
* The subscription key for the Content Moderator service.
*/
key: string;
}

/**
* Class representing configuration for a collection of Azure Cognitive Models.
*/
export interface CognitiveModelConfiguration {
/**
* The Dispatch service for the set of cognitive models.
*/
dispatchModel: LuisService;
/**
* Gets or sets the collection of LUIS models.
* The collection of LUIS models.
*/
languageModels: LuisService[];
/**
* Gets or sets the collection of QnA Maker knowledge bases.
* The collection of QnA Maker knowledgebases.
*/
knowledgeBases: QnaMakerService[];
}

export interface OAuthCredentialsConfiguration {
/**
* Gets or sets the Microsoft App Id for OAuth.
* The microsoft app id for OAuth.
*/
microsoftAppId: string;

/**
* Gets or sets the Microsoft App Password for OAuth.
* The microsoft app password for OAuth.
*/
microsoftAppPassword: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Activity, ActivityTypes, IEventActivity } from 'botframework-schema';
/**
* Event prompt that enables Bots to wait for a incoming event matching a given name to be received.
*/
//OBSOLETE: This class is being deprecated. For more information, refer to https://aka.ms/bfvarouting.
export class EventPrompt extends ActivityPrompt {
public eventName: string;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { BotTelemetryClient } from 'botbuilder-core';
import { ComponentDialog, Dialog, DialogContext, DialogTurnResult } from 'botbuilder-dialogs';
import { InterruptionAction } from './interruptionAction';

//OBSOLETE: InterruptableDialog is being deprecated. For more information, refer to https://aka.ms/bfvarouting.
export abstract class InterruptableDialog extends ComponentDialog {
public primaryDialogName: string;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
/**
* Indicates the current status of a dialog interruption.
*/
//OBSOLETE: This class is being deprecated. For more information, refer to https://aka.ms/bfvarouting.
export enum InterruptionAction {
/**
* Indicates that the active dialog was interrupted and should end.
Expand Down