// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. const { ChoicePrompt, DialogSet, DialogTurnStatus, OAuthPrompt, TextPrompt, WaterfallDialog } = require('botbuilder-dialogs'); const { LogoutDialog } = require('./logoutDialog'); const { OAuthHelpers } = require('../OAuthHelpers'); const MAIN_WATERFALL_DIALOG = 'mainWaterfallDialog'; const OAUTH_PROMPT = 'oAuthPrompt'; const CHOICE_PROMPT = 'choicePrompt'; const TEXT_PROMPT = 'textPrompt'; class MainDialog extends LogoutDialog { constructor() { super('MainDialog'); this.addDialog(new ChoicePrompt(CHOICE_PROMPT)) .addDialog( new OAuthPrompt(OAUTH_PROMPT, { connectionName: process.env.ConnectionName, text: 'Please login', title: 'Login', timeout: 300000 }) ) .addDialog(new TextPrompt(TEXT_PROMPT)) .addDialog( new WaterfallDialog(MAIN_WATERFALL_DIALOG, [ this.promptStep.bind(this), this.loginStep.bind(this), this.commandStep.bind(this), this.processStep.bind(this) ]) ); this.initialDialogId = MAIN_WATERFALL_DIALOG; } /** * The run method handles the incoming activity (in the form of a TurnContext) and passes it through the dialog system. * If no dialog is active, it will start the default dialog. * @param {*} turnContext * @param {*} accessor */ async run(turnContext, accessor) { const dialogSet = new DialogSet(accessor); dialogSet.add(this); const dialogContext = await dialogSet.createContext(turnContext); const results = await dialogContext.continueDialog(); if (results.status === DialogTurnStatus.empty) { await dialogContext.beginDialog(this.id); } } async promptStep(step) { return step.beginDialog(OAUTH_PROMPT); } async loginStep(step) { // Get the token from the previous step. Note that we could also have gotten the // token directly from the prompt itself. There is an example of this in the next method. const tokenResponse = step.result; if (tokenResponse) { await OAuthHelpers.listMe(step.context, tokenResponse); return await step.prompt(TEXT_PROMPT, { prompt: "What would you like to do? You can type anything or 'logout' to retry." }); } await step.context.sendActivity('Login was not successful please try again.'); return await step.endDialog(); } async commandStep(step) { step.values.command = step.result; // Call the prompt again because we need the token. The reasons for this are: // 1. If the user is already logged in we do not need to store the token locally in the bot and worry // about refreshing it. We can always just call the prompt again to get the token. // 2. We never know how long it will take a user to respond. By the time the // user responds the token may have expired. The user would then be prompted to login again. // // There is no reason to store the token locally in the bot because we can always just call // the OAuth prompt to get the token or get a new token if needed. return await step.beginDialog(OAUTH_PROMPT); } async processStep(step) { if (step.result) { // We do not need to store the token in the bot. When we need the token we can // send another prompt. If the token is valid the user will not need to log back in. // The token will be available in the Result property of the task. const tokenResponse = step.result; // If we have the token use the user is authenticated so we may use it to make API calls. if (tokenResponse && tokenResponse.token) { await OAuthHelpers.listMe(step.context, tokenResponse); } } else { await step.context.sendActivity("We couldn't log you in. Please try again later."); } return await step.endDialog(); } } module.exports.MainDialog = MainDialog;