Example #1
0
        /// <summary>
        /// Starts activity processing for the current bot turn.
        /// </summary>
        /// <param name="context">The turn's context object.</param>
        /// <param name="callback">A callback method to run at the end of the pipeline.</param>
        /// <param name="cancelToken">A cancellation token for the task.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="context"/> is null.</exception>
        /// <remarks>The adapter calls middleware in the order in which you added it.
        /// The adapter passes in the context object for the turn and a next delegate,
        /// and the middleware calls the delegate to pass control to the next middleware
        /// in the pipeline. Once control reaches the end of the pipeline, the adapter calls
        /// the <paramref name="callback"/> method. If a middleware component doesn’t call
        /// the next delegate, the adapter does not call  any of the subsequent middleware’s
        /// <see cref="IMiddleware.OnTurn(ITurnContext, MiddlewareSet.NextDelegate)"/>
        /// methods or the callback method, and the pipeline short circuits.
        /// <para>When the turn is initiated by a user activity (reactive messaging), the
        /// callback method will be a reference to the bot's
        /// <see cref="IBot.OnTurn(ITurnContext)"/> method. When the turn is
        /// initiated by a call to <see cref="ContinueConversation(ConversationReference, Func{ITurnContext, Task})"/>
        /// (proactive messaging), the callback method is the callback method that was provided in the call.</para>
        /// </remarks>
        protected async Task RunPipeline(ITurnContext context, Func <ITurnContext, Task> callback = null, CancellationTokenSource cancelToken = null)
        {
            BotAssert.ContextNotNull(context);

            // Call any registered Middleware Components looking for ReceiveActivity()
            if (context.Activity != null)
            {
                await _middlewareSet.ReceiveActivityWithStatus(context, callback).ConfigureAwait(false);
            }
            else
            {
                // call back to caller on proactive case
                if (callback != null)
                {
                    await callback(context).ConfigureAwait(false);
                }
            }
        }
Example #2
0
        /// <summary>
        /// Writes the state cache for this <see cref="BotState"/> to the storage layer.
        /// </summary>
        /// <param name="turnContext">The context object for this turn.</param>
        /// <param name="force">Optional, <c>true</c> to save the state cache to storage;
        /// or <c>false</c> to save state to storage only if a property in the cache has changed.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="turnContext"/> is <c>null</c>.</exception>
        public virtual async Task SaveChangesAsync(ITurnContext turnContext, bool force = false, CancellationToken cancellationToken = default(CancellationToken))
        {
            BotAssert.ContextNotNull(turnContext);

            var cachedState = GetCachedState(turnContext);

            if (cachedState != null && (force || cachedState.IsChanged()))
            {
                var key     = GetStorageKey(turnContext);
                var changes = new Dictionary <string, object>
                {
                    { key, cachedState.State },
                };
                await _storage.WriteAsync(changes, cancellationToken).ConfigureAwait(false);

                cachedState.Hash = CachedBotState.ComputeHash(cachedState.State);
                return;
            }
        }
        /// <summary>
        /// Get the raw signin link to be sent to the user for signin for a connection name.
        /// </summary>
        /// <param name="turnContext">Context for the current turn of conversation with the user.</param>
        /// <param name="connectionName">Name of the auth connection to use.</param>
        /// <param name="userId">The user id that will be associated with the token.</param>
        /// <param name="finalRedirect">The final URL that the OAuth flow will redirect to.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects
        /// or threads to receive notice of cancellation.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        /// <remarks>If the task completes successfully, the result contains the raw signin link.</remarks>
        public async Task <string> GetOauthSignInLinkAsync(ITurnContext turnContext, string connectionName, string userId, string finalRedirect = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            BotAssert.ContextNotNull(turnContext);

            if (string.IsNullOrWhiteSpace(connectionName))
            {
                throw new ArgumentNullException(nameof(connectionName));
            }

            if (string.IsNullOrWhiteSpace(userId))
            {
                throw new ArgumentNullException(nameof(userId));
            }

            var tokenExchangeState = new TokenExchangeState()
            {
                ConnectionName = connectionName,
                Conversation   = new ConversationReference()
                {
                    ActivityId = null,
                    Bot        = new ChannelAccount {
                        Role = "bot"
                    },
                    ChannelId    = "directline",
                    Conversation = new ConversationAccount(),
                    ServiceUrl   = null,
                    User         = new ChannelAccount {
                        Role = "user", Id = userId,
                    },
                },
                MsAppId = (this._credentialProvider as MicrosoftAppCredentials)?.MicrosoftAppId,
            };

            var serializedState = JsonConvert.SerializeObject(tokenExchangeState);
            var encodedState    = Encoding.UTF8.GetBytes(serializedState);
            var state           = Convert.ToBase64String(encodedState);

            var client = await CreateOAuthApiClientAsync(turnContext).ConfigureAwait(false);

            return(await client.GetSignInLinkAsync(state, finalRedirect, cancellationToken).ConfigureAwait(false));
        }
        /// <summary>
        /// Retrieves Azure Active Directory tokens for particular resources on a configured connection.
        /// </summary>
        /// <param name="context">Context for the current turn of conversation with the user.</param>
        /// <param name="connectionName">The name of the Azure Active Direcotry connection configured with this bot.</param>
        /// <param name="resourceUrls">The list of resource URLs to retrieve tokens for.</param>
        /// <param name="userId">The user Id for which tokens are retrieved. If passing in null the userId is taken from the Activity in the ITurnContext.</param>
        /// <returns>Dictionary of resourceUrl to the corresponding TokenResponse.</returns>
        public async Task <Dictionary <string, TokenResponse> > GetAadTokensAsync(ITurnContext context, string connectionName, string[] resourceUrls, string userId = null)
        {
            BotAssert.ContextNotNull(context);

            if (string.IsNullOrWhiteSpace(connectionName))
            {
                throw new ArgumentNullException(nameof(connectionName));
            }

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

            if (string.IsNullOrWhiteSpace(userId))
            {
                userId = context.Activity?.From?.Id;
            }

            var client = await this.CreateOAuthApiClientAsync(context).ConfigureAwait(false);

            return(await client.GetAadTokensAsync(userId, connectionName, resourceUrls).ConfigureAwait(false));
        }
Example #5
0
        /// <summary>
        /// Gets the cached bot state instance that wraps the raw cached data for this <see cref="BotState"/>
        /// from the turn context.
        /// </summary>
        /// <param name="turnContext">The context object for this turn.</param>
        /// <returns>The cached bot state instance.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="turnContext"/> is <c>null</c>.</exception>
        public CachedBotState GetCachedState(ITurnContext turnContext)
        {
            BotAssert.ContextNotNull(turnContext);

            return(turnContext.TurnState.Get <CachedBotState>(_contextServiceKey));
        }