public async Task CloudAdapterConnectorFactory() { // this is just a basic test to verify the wire-up of a ConnectorFactory in the CloudAdapter // Arrange var headerDictionaryMock = new Mock <IHeaderDictionary>(); headerDictionaryMock.Setup(h => h[It.Is <string>(v => v == "Authorization")]).Returns <string>(null); var httpRequestMock = new Mock <HttpRequest>(); httpRequestMock.Setup(r => r.Method).Returns(HttpMethods.Post); httpRequestMock.Setup(r => r.Body).Returns(CreateMessageActivityStream()); httpRequestMock.Setup(r => r.Headers).Returns(headerDictionaryMock.Object); var httpResponseMock = new Mock <HttpResponse>(); var claimsIdentity = new ClaimsIdentity(); var authenticateRequestResult = new AuthenticateRequestResult { ClaimsIdentity = claimsIdentity, ConnectorFactory = new TestConnectorFactory(), Audience = "audience", CallerId = "callerId" }; var userTokenClient = new TestUserTokenClient("appId"); var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>(); cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult)); cloudEnvironmentMock.Setup(ce => ce.CreateConnectorFactory(It.IsAny <ClaimsIdentity>())).Returns(new TestConnectorFactory()); cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient)); var bot = new ConnectorFactoryBot(); // Act var adapter = new CloudAdapter(cloudEnvironmentMock.Object); await adapter.ProcessAsync(httpRequestMock.Object, httpResponseMock.Object, bot); // Assert Assert.Equal("audience", bot.Authorization.Parameter); Assert.Equal(claimsIdentity, bot.Identity); Assert.Equal(userTokenClient, bot.UserTokenClient); Assert.True(bot.ConnectorClient != null); Assert.True(bot.BotCallbackHandler != null); }
public async Task InjectCloudEnvironment() { // Arrange var headerDictionaryMock = new Mock <IHeaderDictionary>(); headerDictionaryMock.Setup(h => h[It.Is <string>(v => v == "Authorization")]).Returns <string>(null); var httpRequestMock = new Mock <HttpRequest>(); httpRequestMock.Setup(r => r.Method).Returns(HttpMethods.Post); httpRequestMock.Setup(r => r.Body).Returns(CreateMessageActivityStream()); httpRequestMock.Setup(r => r.Headers).Returns(headerDictionaryMock.Object); var httpResponseMock = new Mock <HttpResponse>(); var botMock = new Mock <IBot>(); botMock.Setup(b => b.OnTurnAsync(It.IsAny <TurnContext>(), It.IsAny <CancellationToken>())).Returns(Task.CompletedTask); var authenticateRequestResult = new AuthenticateRequestResult { ClaimsIdentity = new ClaimsIdentity(), ConnectorFactory = new TestConnectorFactory(), Audience = "audience", CallerId = "callerId" }; var userTokenClient = new TestUserTokenClient("appId"); var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>(); cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult)); cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient)); var httpClient = new Mock <HttpClient>(); // Act var adapter = new CloudAdapter(cloudEnvironmentMock.Object); await adapter.ProcessAsync(httpRequestMock.Object, httpResponseMock.Object, botMock.Object); // Assert botMock.Verify(m => m.OnTurnAsync(It.Is <TurnContext>(tc => true), It.Is <CancellationToken>(ct => true)), Times.Once()); cloudEnvironmentMock.Verify(ce => ce.AuthenticateRequestAsync(It.Is <Activity>(tc => true), It.Is <string>(tc => true), It.Is <CancellationToken>(ct => true)), Times.Once()); }
public async Task CloudAdapterContinueConversation() { // Arrange var claimsIdentity = new ClaimsIdentity(); var authenticateRequestResult = new AuthenticateRequestResult { ClaimsIdentity = claimsIdentity, ConnectorFactory = new TestConnectorFactory(), Scope = "scope", CallerId = "callerId" }; var userTokenClient = new TestUserTokenClient("appId"); var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>(); cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult)); cloudEnvironmentMock.Setup(ce => ce.CreateConnectorFactory(It.IsAny <ClaimsIdentity>())).Returns(new TestConnectorFactory()); cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient)); var bot = new ConnectorFactoryBot(); var expectedServiceUrl = "http://serviceUrl"; var conversationAccount = new ConversationAccount { Id = "conversation Id" }; var continuationActivity = new Activity { Type = ActivityTypes.Event, ServiceUrl = expectedServiceUrl, Conversation = conversationAccount }; var conversationReference = new ConversationReference { ServiceUrl = expectedServiceUrl, Conversation = conversationAccount }; var actualServiceUrl1 = string.Empty; var actualServiceUrl2 = string.Empty; var actualServiceUrl3 = string.Empty; var actualServiceUrl4 = string.Empty; var actualServiceUrl5 = string.Empty; var actualServiceUrl6 = string.Empty; BotCallbackHandler callback1 = (t, c) => { actualServiceUrl1 = t.Activity.ServiceUrl; return(Task.CompletedTask); }; BotCallbackHandler callback2 = (t, c) => { actualServiceUrl2 = t.Activity.ServiceUrl; return(Task.CompletedTask); }; BotCallbackHandler callback3 = (t, c) => { actualServiceUrl3 = t.Activity.ServiceUrl; return(Task.CompletedTask); }; BotCallbackHandler callback4 = (t, c) => { actualServiceUrl4 = t.Activity.ServiceUrl; return(Task.CompletedTask); }; BotCallbackHandler callback5 = (t, c) => { actualServiceUrl5 = t.Activity.ServiceUrl; return(Task.CompletedTask); }; BotCallbackHandler callback6 = (t, c) => { actualServiceUrl6 = t.Activity.ServiceUrl; return(Task.CompletedTask); }; // Act var adapter = new CloudAdapter(cloudEnvironmentMock.Object); await adapter.ContinueConversationAsync("botAppId", continuationActivity, callback1, CancellationToken.None); await adapter.ContinueConversationAsync(claimsIdentity, continuationActivity, callback2, CancellationToken.None); await adapter.ContinueConversationAsync(claimsIdentity, continuationActivity, "audience", callback3, CancellationToken.None); await adapter.ContinueConversationAsync("botAppId", conversationReference, callback4, CancellationToken.None); await adapter.ContinueConversationAsync(claimsIdentity, conversationReference, callback5, CancellationToken.None); await adapter.ContinueConversationAsync(claimsIdentity, conversationReference, "audience", callback6, CancellationToken.None); // Assert Assert.Equal(expectedServiceUrl, actualServiceUrl1); Assert.Equal(expectedServiceUrl, actualServiceUrl2); Assert.Equal(expectedServiceUrl, actualServiceUrl3); Assert.Equal(expectedServiceUrl, actualServiceUrl4); Assert.Equal(expectedServiceUrl, actualServiceUrl5); Assert.Equal(expectedServiceUrl, actualServiceUrl6); }
public async Task CloudAdapterProvidesUserTokenClient() { // this is just a basic test to verify the wire-up of a UserTokenClient in the CloudAdapter // there is also some coverage for the internal code that creates the TokenExchangeState string // Arrange string appId = "appId"; string userId = "userId"; string channelId = "channelId"; string conversationId = "conversationId"; string recipientId = "botId"; string relatesToActivityId = "relatesToActivityId"; string connectionName = "connectionName"; var headerDictionaryMock = new Mock <IHeaderDictionary>(); headerDictionaryMock.Setup(h => h[It.Is <string>(v => v == "Authorization")]).Returns <string>(null); var httpRequestMock = new Mock <HttpRequest>(); httpRequestMock.Setup(r => r.Body).Returns(CreateMessageActivityStream(userId, channelId, conversationId, recipientId, relatesToActivityId)); httpRequestMock.Setup(r => r.Headers).Returns(headerDictionaryMock.Object); var httpResponseMock = new Mock <HttpResponse>(); var authenticateRequestResult = new AuthenticateRequestResult { ClaimsIdentity = new ClaimsIdentity(), ConnectorFactory = new TestConnectorFactory(), Scope = "scope", CallerId = "callerId" }; var userTokenClient = new TestUserTokenClient(appId); var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>(); cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult)); cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient)); var bot = new UserTokenClientBot(connectionName); // Act var adapter = new CloudAdapter(cloudEnvironmentMock.Object); await adapter.ProcessAsync(httpRequestMock.Object, httpResponseMock.Object, bot); // Assert var args_ExchangeTokenAsync = userTokenClient.Record["ExchangeTokenAsync"]; Assert.Equal(userId, (string)args_ExchangeTokenAsync[0]); Assert.Equal(connectionName, (string)args_ExchangeTokenAsync[1]); Assert.Equal(channelId, (string)args_ExchangeTokenAsync[2]); Assert.Equal("TokenExchangeRequest", args_ExchangeTokenAsync[3].GetType().Name); var args_GetAadTokensAsync = userTokenClient.Record["GetAadTokensAsync"]; Assert.Equal(userId, (string)args_GetAadTokensAsync[0]); Assert.Equal(connectionName, (string)args_GetAadTokensAsync[1]); Assert.Equal("x", ((string[])args_GetAadTokensAsync[2])[0]); Assert.Equal("y", ((string[])args_GetAadTokensAsync[2])[1]); Assert.Equal(channelId, (string)args_GetAadTokensAsync[3]); var args_GetSignInResourceAsync = userTokenClient.Record["GetSignInResourceAsync"]; // this code is testing the internal CreateTokenExchangeState function by doing the work in reverse var state = (string)args_GetSignInResourceAsync[0]; var json = Encoding.UTF8.GetString(Convert.FromBase64String(state)); var tokenExchangeState = JsonConvert.DeserializeObject <TokenExchangeState>(json); Assert.Equal(connectionName, tokenExchangeState.ConnectionName); Assert.Equal(appId, tokenExchangeState.MsAppId); Assert.Equal(conversationId, tokenExchangeState.Conversation.Conversation.Id); Assert.Equal(recipientId, tokenExchangeState.Conversation.Bot.Id); Assert.Equal(relatesToActivityId, tokenExchangeState.RelatesTo.ActivityId); Assert.Equal("finalRedirect", (string)args_GetSignInResourceAsync[1]); var args_GetTokenStatusAsync = userTokenClient.Record["GetTokenStatusAsync"]; Assert.Equal(userId, (string)args_GetTokenStatusAsync[0]); Assert.Equal(channelId, (string)args_GetTokenStatusAsync[1]); Assert.Equal("includeFilter", (string)args_GetTokenStatusAsync[2]); var args_GetUserTokenAsync = userTokenClient.Record["GetUserTokenAsync"]; Assert.Equal(userId, (string)args_GetUserTokenAsync[0]); Assert.Equal(connectionName, (string)args_GetUserTokenAsync[1]); Assert.Equal(channelId, (string)args_GetUserTokenAsync[2]); Assert.Equal("magicCode", (string)args_GetUserTokenAsync[3]); var args_SignOutUserAsync = userTokenClient.Record["SignOutUserAsync"]; Assert.Equal(userId, (string)args_SignOutUserAsync[0]); Assert.Equal(connectionName, (string)args_SignOutUserAsync[1]); Assert.Equal(channelId, (string)args_SignOutUserAsync[2]); }
public async Task CloudAdapterCreateConversation() { // Arrange var claimsIdentity = new ClaimsIdentity(); var authenticateRequestResult = new AuthenticateRequestResult { ClaimsIdentity = claimsIdentity, ConnectorFactory = new TestConnectorFactory(), Audience = "audience", CallerId = "callerId" }; var userTokenClient = new TestUserTokenClient("appId"); var conversationResourceResponse = new ConversationResourceResponse(); var createResponse = new HttpOperationResponse <ConversationResourceResponse> { Body = conversationResourceResponse }; // note Moq doesn't support extension methods used in the implementation so we are actually mocking the underlying CreateConversationWithHttpMessagesAsync method var conversationsMock = new Mock <IConversations>(); conversationsMock.Setup(cm => cm.CreateConversationWithHttpMessagesAsync(It.IsAny <ConversationParameters>(), It.IsAny <Dictionary <string, List <string> > >(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(createResponse)); var connectorMock = new Mock <IConnectorClient>(); connectorMock.SetupGet(m => m.Conversations).Returns(conversationsMock.Object); var expectedServiceUrl = "http://serviceUrl"; var expectedAudience = "audience"; var connectorFactoryMock = new Mock <ConnectorFactory>(); connectorFactoryMock.Setup(cf => cf.CreateAsync(It.Is <string>(serviceUrl => serviceUrl == expectedServiceUrl), It.Is <string>(audience => audience == expectedAudience), It.IsAny <CancellationToken>())).Returns(Task.FromResult(connectorMock.Object)); var cloudEnvironmentMock = new Mock <BotFrameworkAuthentication>(); cloudEnvironmentMock.Setup(ce => ce.AuthenticateRequestAsync(It.IsAny <Activity>(), It.IsAny <string>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult(authenticateRequestResult)); cloudEnvironmentMock.Setup(ce => ce.CreateConnectorFactory(It.IsAny <ClaimsIdentity>())).Returns(connectorFactoryMock.Object); cloudEnvironmentMock.Setup(ce => ce.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())).Returns(Task.FromResult <UserTokenClient>(userTokenClient)); var expectedChannelId = "expected-channel-id"; var actualChannelId = string.Empty; BotCallbackHandler callback1 = (t, c) => { actualChannelId = t.Activity.ChannelId; return(Task.CompletedTask); }; var conversationParameters = new ConversationParameters { IsGroup = false, Bot = new ChannelAccount { }, Members = new ChannelAccount[] { }, TenantId = "tenantId", }; // Act var adapter = new CloudAdapter(cloudEnvironmentMock.Object); await adapter.CreateConversationAsync("botAppId", expectedChannelId, expectedServiceUrl, expectedAudience, conversationParameters, callback1, CancellationToken.None); // Assert Assert.Equal(expectedChannelId, actualChannelId); }
public void CanContinueConversationOverWebSocket() { // Arrange var continueConversationWaiter = new AutoResetEvent(false); var verifiedValidContinuation = false; var appId = "testAppId"; var tenantId = "testTenantId"; var token = "Bearer testjwt"; var channelId = "testChannel"; var audience = "testAudience"; var callerId = "testCallerId"; var authResult = new AuthenticateRequestResult { Audience = audience, CallerId = callerId, ClaimsIdentity = new ClaimsIdentity(new List <Claim> { new Claim("aud", audience), new Claim("iss", $"https://login.microsoftonline.com/{tenantId}/"), new Claim("azp", appId), new Claim("tid", tenantId), new Claim("ver", "2.0") }) }; var userTokenClient = new TestUserTokenClient(appId); var validActivity = new Activity { Id = Guid.NewGuid().ToString("N"), Type = ActivityTypes.Message, From = new ChannelAccount { Id = "testUser" }, Conversation = new ConversationAccount { Id = Guid.NewGuid().ToString("N") }, Recipient = new ChannelAccount { Id = "testBot" }, ServiceUrl = "wss://InvalidServiceUrl/api/messages", ChannelId = channelId, Text = "hi", }; var validContent = new StringContent(JsonConvert.SerializeObject(validActivity), Encoding.UTF8, "application/json"); var invalidActivity = new Activity { Id = Guid.NewGuid().ToString("N"), Type = ActivityTypes.Message, From = new ChannelAccount { Id = "testUser" }, Conversation = new ConversationAccount { Id = Guid.NewGuid().ToString("N") }, Recipient = new ChannelAccount { Id = "testBot" }, ServiceUrl = "wss://InvalidServiceUrl/api/messages", ChannelId = channelId, Text = "hi", }; var streamingConnection = new Mock <StreamingConnection>(); streamingConnection .Setup(c => c.ListenAsync(It.IsAny <RequestHandler>(), It.IsAny <CancellationToken>())) .Returns <RequestHandler, CancellationToken>((handler, cancellationToken) => handler.ProcessRequestAsync( new ReceiveRequest { Verb = "POST", Path = "/api/messages", Streams = new List <IContentStream> { new TestContentStream { Id = Guid.NewGuid(), ContentType = "application/json", Length = (int?)validContent.Headers.ContentLength, Stream = validContent.ReadAsStreamAsync().GetAwaiter().GetResult() } } }, null, cancellationToken: cancellationToken)); var auth = new Mock <BotFrameworkAuthentication>(); auth.Setup(a => a.AuthenticateStreamingRequestAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult(authResult)); auth.Setup(a => a.CreateUserTokenClientAsync(It.IsAny <ClaimsIdentity>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult <UserTokenClient>(userTokenClient)); var webSocketManager = new Mock <WebSocketManager>(); webSocketManager.Setup(m => m.IsWebSocketRequest).Returns(true); var httpContext = new Mock <HttpContext>(); httpContext.Setup(c => c.WebSockets).Returns(webSocketManager.Object); var httpRequest = new Mock <HttpRequest>(); httpRequest.Setup(r => r.Method).Returns("GET"); httpRequest.Setup(r => r.HttpContext).Returns(httpContext.Object); httpRequest.Setup(r => r.Headers).Returns(new HeaderDictionary { { "Authorization", new StringValues(token) }, { "channelid", new StringValues(channelId) } }); var httpResponse = new Mock <HttpResponse>(); var bot = new Mock <IBot>(); bot.Setup(b => b.OnTurnAsync(It.IsAny <ITurnContext>(), It.IsAny <CancellationToken>())) .Returns(Task.Factory.StartNew(() => { continueConversationWaiter.WaitOne(); })); // Simulate listening on web socket // Act var adapter = new StreamingTestCloudAdapter(auth.Object, streamingConnection.Object); var processRequest = adapter.ProcessAsync(httpRequest.Object, httpResponse.Object, bot.Object, CancellationToken.None); var validContinuation = adapter.ContinueConversationAsync( authResult.ClaimsIdentity, validActivity, (turn, cancellationToken) => { var connectorFactory = turn.TurnState.Get <ConnectorFactory>(); Assert.NotNull(connectorFactory); var connectorFactoryTypeName = connectorFactory.GetType().FullName ?? string.Empty; Assert.EndsWith("StreamingConnectorFactory", connectorFactoryTypeName); verifiedValidContinuation = true; return(Task.CompletedTask); }, CancellationToken.None); var invalidContinuation = adapter.ContinueConversationAsync( authResult.ClaimsIdentity, invalidActivity, (turn, cancellationToken) => Task.CompletedTask, CancellationToken.None); continueConversationWaiter.Set(); processRequest.Wait(); // Assert Assert.True(processRequest.IsCompletedSuccessfully); Assert.True(verifiedValidContinuation); Assert.True(validContinuation.IsCompletedSuccessfully); Assert.Null(validContinuation.Exception); Assert.True(invalidContinuation.IsFaulted); Assert.NotEmpty(invalidContinuation.Exception.InnerExceptions); Assert.True(invalidContinuation.Exception.InnerExceptions[0] is ApplicationException); }