/// <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));
        }
Example #2
0
        /// <summary>
        /// Log an activity to the transcript.
        /// </summary>
        /// <param name="activity">The activity to transcribe.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        public Task LogActivityAsync(IActivity activity)
        {
            BotAssert.ActivityNotNull(activity);
            if (_traceActivity)
            {
                Trace.TraceInformation(JsonConvert.SerializeObject(activity, _serializationSettings));
            }
            else
            {
                if (Debugger.IsAttached && activity.Type == ActivityTypes.Message)
                {
                    Trace.TraceInformation($"{activity.From.Name ?? activity.From.Id ?? activity.From.Role} [{activity.Type}] {activity.AsMessageActivity()?.Text}");
                }
                else
                {
                    Trace.TraceInformation($"{activity.From.Name ?? activity.From.Id ?? activity.From.Role} [{activity.Type}]");
                }
            }

            return(Task.CompletedTask);
        }
Example #3
0
        private async Task <ResourceResponse> UpdateActivityInternalAsync(
            Activity activity,
            IEnumerable <UpdateActivityHandler> updateHandlers,
            Func <Task <ResourceResponse> > callAtBottom,
            CancellationToken cancellationToken)
        {
            BotAssert.ActivityNotNull(activity);
            if (updateHandlers == null)
            {
                throw new ArgumentException($"{nameof(updateHandlers)} is null.", nameof(updateHandlers));
            }

            // No middleware to run.
            if (!updateHandlers.Any())
            {
                if (callAtBottom != null)
                {
                    return(await callAtBottom().ConfigureAwait(false));
                }

                return(null);
            }

            // Default to "No more Middleware after this".
            async Task <ResourceResponse> Next()
            {
                // Remove the first item from the list of middleware to call,
                // so that the next call just has the remaining items to worry about.
                IEnumerable <UpdateActivityHandler> remaining = updateHandlers.Skip(1);
                var result = await UpdateActivityInternalAsync(activity, remaining, callAtBottom, cancellationToken).ConfigureAwait(false);

                activity.Id = result.Id;
                return(result);
            }

            // Grab the current middleware, which is the 1st element in the array, and execute it
            UpdateActivityHandler toCall = updateHandlers.First();

            return(await toCall(this, activity, Next).ConfigureAwait(false));
        }
Example #4
0
        private async Task DeleteActivityInternalAsync(
            ConversationReference cr,
            IEnumerable <DeleteActivityHandler> deleteHandlers,
            Func <Task> callAtBottom,
            CancellationToken cancellationToken)
        {
            BotAssert.ConversationReferenceNotNull(cr);

            if (deleteHandlers == null)
            {
                throw new ArgumentException($"{nameof(deleteHandlers)} is null", nameof(deleteHandlers));
            }

            // No middleware to run.
            if (!deleteHandlers.Any())
            {
                if (callAtBottom != null)
                {
                    await callAtBottom().ConfigureAwait(false);
                }

                return;
            }

            // Default to "No more Middleware after this".
            async Task Next()
            {
                // Remove the first item from the list of middleware to call,
                // so that the next call just has the remaining items to worry about.
                IEnumerable <DeleteActivityHandler> remaining = deleteHandlers.Skip(1);

                await DeleteActivityInternalAsync(cr, remaining, callAtBottom, cancellationToken).ConfigureAwait(false);
            }

            // Grab the current middleware, which is the 1st element in the array, and execute it.
            DeleteActivityHandler toCall = deleteHandlers.First();

            await toCall(this, cr, Next).ConfigureAwait(false);
        }
Example #5
0
        /// <summary>
        /// Sends an activity to the sender of the incoming activity.
        /// </summary>
        /// <param name="activity">The activity to send.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <returns>A task that represents the work queued to execute.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="activity"/> is <c>null</c>.</exception>
        /// <remarks>If the activity is successfully sent, the task result contains
        /// a <see cref="ResourceResponse"/> object containing the ID that the receiving
        /// channel assigned to the activity.</remarks>
        public async Task <ResourceResponse> SendActivityAsync(IActivity activity, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (_disposed)
            {
                throw new ObjectDisposedException(nameof(SendActivityAsync));
            }

            BotAssert.ActivityNotNull(activity);

            ResourceResponse[] responses = await SendActivitiesAsync(new[] { activity }, cancellationToken).ConfigureAwait(false);

            if (responses == null || responses.Length == 0)
            {
                // It's possible an interceptor prevented the activity from having been sent.
                // Just return an empty response in that case.
                return(new ResourceResponse());
            }
            else
            {
                return(responses[0]);
            }
        }
        /// <summary>
        /// Creates a turn context and runs the middleware pipeline for an incoming activity.
        /// </summary>
        /// <param name="identity">A <see cref="ClaimsIdentity"/> for the request.</param>
        /// <param name="activity">The incoming activity.</param>
        /// <param name="callback">The code to run at the end of the adapter's middleware pipeline.</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>
        public async Task <InvokeResponse> ProcessActivityAsync(ClaimsIdentity identity, Activity activity, BotCallbackHandler callback, CancellationToken cancellationToken)
        {
            BotAssert.ActivityNotNull(activity);

            _logger.LogInformation($"Received an incoming activity.  ActivityId: {activity.Id}");

            using (var context = new TurnContext(this, activity))
            {
                context.TurnState.Add <IIdentity>(BotIdentityKey, identity);

                var connectorClient = await CreateConnectorClientAsync(activity.ServiceUrl, identity, cancellationToken).ConfigureAwait(false);

                context.TurnState.Add(connectorClient);

                await RunPipelineAsync(context, callback, cancellationToken).ConfigureAwait(false);

                // Handle Invoke scenarios, which deviate from the request/response model in that
                // the Bot will return a specific body and return code.
                if (activity.Type == ActivityTypes.Invoke)
                {
                    var activityInvokeResponse = context.TurnState.Get <Activity>(InvokeReponseKey);
                    if (activityInvokeResponse == null)
                    {
                        return(new InvokeResponse {
                            Status = (int)HttpStatusCode.NotImplemented
                        });
                    }
                    else
                    {
                        return((InvokeResponse)activityInvokeResponse.Value);
                    }
                }

                // For all non-invoke scenarios, the HTTP layers above don't have to mess
                // withthe Body and return codes.
                return(null);
            }
        }
        /// <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 #8
0
 /// <summary>
 /// Log an activity to the transcript
 /// </summary>
 /// <param name="activity">activity to log</param>
 /// <returns></returns>
 public Task LogActivity(IActivity activity)
 {
     BotAssert.ActivityNotNull(activity);
     Trace.TraceInformation(JsonConvert.SerializeObject(activity, serializationSettings));
     return(Task.CompletedTask);
 }
 /// <summary>
 /// Adds a middleware object to the end of the set.
 /// </summary>
 /// <param name="middleware">The middleware to add.</param>
 /// <returns>The updated middleware set.</returns>
 /// <see cref="BotAdapter.Use(IMiddleware)"/>
 public MiddlewareSet Use(IMiddleware middleware)
 {
     BotAssert.MiddlewareNotNull(middleware);
     _middleware.Add(middleware);
     return(this);
 }
Example #10
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));
        }
Example #11
0
 /// <summary>
 /// Log an activity to the transcript
 /// </summary>
 /// <param name="activity">activity to log</param>
 /// <returns></returns>
 public async Task LogActivity(IActivity activity)
 {
     BotAssert.ActivityNotNull(activity);
     await Console.Out.WriteLineAsync(JsonConvert.SerializeObject(activity, serializationSettings));
 }