Example #1
0
        public static BotAdapter UseState(this BotAdapter botAdapter, UserState userState, ConversationState conversationState, bool auto = true)
        {
            if (botAdapter == null)
            {
                throw new ArgumentNullException(nameof(botAdapter));
            }

            if (userState == null)
            {
                throw new ArgumentNullException(nameof(userState));
            }

            if (conversationState == null)
            {
                throw new ArgumentNullException(nameof(conversationState));
            }

            botAdapter.Use(new RegisterClassMiddleware <UserState>(userState));
            botAdapter.Use(new RegisterClassMiddleware <ConversationState>(conversationState));

            if (auto)
            {
                return(botAdapter.Use(new AutoSaveStateMiddleware(userState, conversationState)));
            }

            return(botAdapter);
        }
        /// <summary>
        /// Creates a context object.
        /// </summary>
        /// <param name="adapter">The adapter creating the context.</param>
        /// <param name="activity">The incoming activity for the turn;
        /// or <c>null</c> for a turn for a proactive message.</param>
        /// <exception cref="ArgumentNullException"><paramref name="activity"/> or
        /// <paramref name="adapter"/> is <c>null</c>.</exception>
        /// <remarks>For use by bot adapter implementations only.</remarks>
        public TurnContext(BotAdapter adapter, Activity activity)
        {
            _adapter  = adapter ?? throw new ArgumentNullException(nameof(adapter));
            _activity = activity ?? throw new ArgumentNullException(nameof(activity));

            _turnServices = new TurnContextServiceCollection();
        }
Example #3
0
        private static readonly TimeSpan PollingInterval = TimeSpan.FromSeconds(1);   // Poll for token every 1 second.

        /// <summary>
        /// Inspects outgoing Activities for <see cref="OAuthCard">OAuthCards</see>.
        /// </summary>
        /// <param name="adapter">The BotFrameworkAdapter used for polling the token service.</param>
        /// <param name="logger">The ILogger implementation this TokenResolver should use.</param>
        /// <param name="turnContext">The context object for the turn.</param>
        /// <param name="activity">The activity to send.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <remarks>If an <see cref="OAuthCard"/> is found in an outgoing activity, the <see cref="TokenResolver"/> polls the Bot Framework Token Service in the background.
        /// When the user completes the login flow, the TokenResolver will retrieve the user's token from the service and create a <see cref="SignInConstants.TokenResponseEventName">TokenResponse</see> activity to "send" to the bot, mimicking non-streaming OAuth flows.
        /// <para />
        /// All bots using OAuth should query the service to ensure the user is successfully logged in before utilizing a user's token. The bot should never store the user's token.
        /// </remarks>
        public static void CheckForOAuthCards(BotAdapter adapter, ILogger logger, ITurnContext turnContext, Activity activity, CancellationToken cancellationToken)
        {
            if (activity?.Attachments == null)
            {
                return;
            }

            var pollingTimeout = TurnStateConstants.OAuthLoginTimeoutValue;

            // Override login timeout with value set from the OAuthPrompt or by the developer
            if (turnContext.TurnState.ContainsKey(TurnStateConstants.OAuthLoginTimeoutKey))
            {
                pollingTimeout = (TimeSpan)turnContext.TurnState.Get <object>(TurnStateConstants.OAuthLoginTimeoutKey);
            }

            var identity      = turnContext.TurnState.Get <IIdentity>(BotAdapter.BotIdentityKey) as ClaimsIdentity;
            var callback      = turnContext.TurnState.Get <BotCallbackHandler>();
            var pollingHelper = new PollingHelper()
            {
                Activity = turnContext.Activity,
                Adapter  = adapter,
                DefaultPollingInterval = PollingInterval,
                DefaultPollingTimeout  = pollingTimeout,
                CancellationToken      = cancellationToken,
                Identity = identity,
                Logger   = logger,
                Callback = callback
            };

            var pollTokenTasks = new List <Task>();

            foreach (var attachment in activity.Attachments.Where(a => a.ContentType == OAuthCard.ContentType))
            {
                if (attachment.Content is OAuthCard oauthCard)
                {
                    if (string.IsNullOrWhiteSpace(oauthCard.ConnectionName))
                    {
                        throw new InvalidOperationException("The OAuthPrompt's ConnectionName property is missing a value.");
                    }

                    pollTokenTasks.Add(PollForTokenAsync(pollingHelper, oauthCard.ConnectionName));
                }
            }

            if (pollTokenTasks.Any())
            {
                // Run the poll operations in the background.
                // On retrieving a token from the token service the TokenResolver creates an Activity to route the token to the bot to continue the conversation.
                // If these Tasks are awaited and the user doesn't complete the login flow, the bot may timeout in sending its response to the channel which can cause the streaming connection to disconnect.
#pragma warning disable VSTHRD110 // Observe result of async calls
                Task.WhenAll(pollTokenTasks.ToArray());
#pragma warning restore VSTHRD110 // Observe result of async calls
            }
        }
Example #4
0
        /// <summary>
        /// Register UserState and ConversationState objects so they are accessible via TurnContext.Get&lt;UserState&gt;() and add auto save middleware.
        /// </summary>
        /// <param name="botAdapter">bot adapater to add save state to.</param>
        /// <param name="userState">UserState to use (default is new UserState(registered storage)).</param>
        /// <param name="conversationState">ConversationState to use (default is new ConversationState (registered storage)).</param>
        /// <param name="auto">automatically manage state (default is true), if set to false, it is your responsibility to load and save state.</param>
        /// <returns>Botadapter.</returns>
        public static BotAdapter UseState(this BotAdapter botAdapter, UserState userState, ConversationState conversationState, bool auto = true)
        {
            if (botAdapter == null)
            {
                throw new ArgumentNullException(nameof(botAdapter));
            }

            if (userState == null || conversationState == null)
            {
                var storageMiddleware = botAdapter.MiddlewareSet.Where(mw => mw is RegisterClassMiddleware <IStorage>).Cast <RegisterClassMiddleware <IStorage> >().FirstOrDefault();
                if (storageMiddleware == null)
                {
                    throw new ArgumentNullException("There is no IStorage registered in the middleware");
                }

                if (userState == null)
                {
                    var userStateMiddleware = botAdapter.MiddlewareSet.Where(mw => mw is RegisterClassMiddleware <UserState>).Cast <RegisterClassMiddleware <UserState> >().FirstOrDefault();
                    if (userStateMiddleware != null)
                    {
                        userState = userStateMiddleware.Service;
                    }
                    else
                    {
                        userState = new UserState(storageMiddleware.Service);
                        botAdapter.Use(new RegisterClassMiddleware <UserState>(userState));
                    }
                }

                if (conversationState == null)
                {
                    var conversationStateMiddleware = botAdapter.MiddlewareSet.Where(mw => mw is RegisterClassMiddleware <ConversationState>).Cast <RegisterClassMiddleware <ConversationState> >().FirstOrDefault();
                    if (conversationStateMiddleware != null)
                    {
                        conversationState = conversationStateMiddleware.Service;
                    }
                    else
                    {
                        conversationState = new ConversationState(storageMiddleware.Service);
                        botAdapter.Use(new RegisterClassMiddleware <ConversationState>(conversationState));
                    }
                }
            }

            if (auto)
            {
                return(botAdapter.Use(new AutoSaveStateMiddleware(userState, conversationState)));
            }

            return(botAdapter);
        }
Example #5
0
        /// <summary>
        /// Registers bot state object into the TurnContext. The botstate will be available via the turn context's
        /// <see cref="TurnContext.TurnState"/>.<see cref="TurnContextStateCollection.Get{typeof(instance)}()"/> method.
        /// </summary>
        /// <param name="botAdapter">The <see cref="BotAdapter"/> on which to register the storage object.</param>
        /// <param name="botStates">One or <see cref="BotState"/> object to register.</param>
        /// <returns>The updated adapter.</returns>
        /// <remarks>
        /// This adds <see cref="IMiddleware"/> to register the a BotState object into turnstate.
        /// </remarks>
        public static BotAdapter UseBotState(this BotAdapter botAdapter, params BotState[] botStates)
        {
            if (botStates == null)
            {
                throw new ArgumentNullException(nameof(botStates));
            }

            foreach (var botState in botStates)
            {
                botAdapter.Use(new RegisterClassMiddleware <BotState>(botState, botState.GetType().FullName));
            }

            return(botAdapter);
        }
Example #6
0
        public BotContext(BotAdapter adapter, IActivity request)
        {
            _adapter = adapter ?? throw new ArgumentNullException(nameof(adapter));
            _request = request ?? throw new ArgumentNullException(nameof(request));

            _conversationReference = new ConversationReference()
            {
                ActivityId   = request.Id,
                User         = request.From,
                Bot          = request.Recipient,
                Conversation = request.Conversation,
                ChannelId    = request.ChannelId,
                ServiceUrl   = request.ServiceUrl
            };
        }
Example #7
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TurnContext"/> class.
 /// </summary>
 /// <param name="adapter">The adapter creating the context.</param>
 /// <param name="activity">The incoming activity for the turn;
 /// or <c>null</c> for a turn for a proactive message.</param>
 /// <exception cref="ArgumentNullException"><paramref name="activity"/> or
 /// <paramref name="adapter"/> is <c>null</c>.</exception>
 /// <remarks>For use by bot adapter implementations only.</remarks>
 public TurnContext(BotAdapter adapter, Activity activity)
 {
     Adapter  = adapter ?? throw new ArgumentNullException(nameof(adapter));
     Activity = activity ?? throw new ArgumentNullException(nameof(activity));
 }
Example #8
0
 public BotContext(BotAdapter bot, ConversationReference conversationReference)
 {
     _adapter = bot ?? throw new ArgumentNullException(nameof(bot));
     _conversationReference = conversationReference ?? throw new ArgumentNullException(nameof(conversationReference));
 }
Example #9
0
 /// <summary>
 /// Register storage with the adapter so that is available via TurnContext.Get&lt;IStorage&gt;().
 /// </summary>
 /// <param name="botAdapter">bot adapter to register storage with.</param>
 /// <param name="storage">IStorage implementation to register.</param>
 /// <returns>bot adapter.</returns>
 public static BotAdapter UseStorage(this BotAdapter botAdapter, IStorage storage)
 {
     return(botAdapter.Use(new RegisterClassMiddleware <IStorage>(storage)));
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="BotFrameworkBotContext"/> class.
 /// </summary>
 /// <param name="botAppId">The bot application identifier. Bot's AAD identity.</param>
 /// <param name="botAdapter">The bot adapter.</param>
 /// <param name="requestActivity">The request activity.</param>
 public BotFrameworkBotContext(string botAppId, BotAdapter botAdapter, Activity requestActivity)
     : base(botAdapter, requestActivity)
 {
     this.BotAppId = botAppId;
 }
Example #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="BotFrameworkTurnContext"/> class.
 /// </summary>
 /// <param name="botAppId">The bot application identifier. Bot's AAD identity.</param>
 /// <param name="botAdapter">The bot adapter.</param>
 /// <param name="activity">The request activity.</param>
 public BotFrameworkTurnContext(string botAppId, BotAdapter botAdapter, Activity activity)
     : base(botAdapter, activity)
 {
     this.BotAppId = botAppId;
 }
Example #12
0
 /// <summary>
 /// Registers a storage layer with the adapter. The storage object will be available via the turn context's
 /// <see cref="TurnContext.TurnState"/>.<see cref="TurnContextStateCollection.Get{IStorage}()"/> method.
 /// </summary>
 /// <param name="botAdapter">The <see cref="BotAdapter"/> on which to register the storage object.</param>
 /// <param name="storage">The <see cref="IStorage"/> object to register.</param>
 /// <returns>The updated adapter.</returns>
 /// <remarks>
 /// This adds <see cref="IMiddleware"/> to the adapter to register the storage layer.
 /// </remarks>
 public static BotAdapter UseStorage(this BotAdapter botAdapter, IStorage storage)
 {
     return(botAdapter.Use(new RegisterClassMiddleware <IStorage>(storage ?? throw new ArgumentNullException(nameof(storage)))));
 }