public async Task SyncTeamMembers_NullResponseFromBotAPI_CatchExceptionAndLog() { // Arrange var activityContext = this.GetSyncTeamMembersActivity(); var teamData = new TeamDataEntity() { TenantId = "Tanant1", TeamId = "Team1", ServiceUrl = "serviceUrl" }; IEnumerable <UserDataEntity> userDataEntities = null; this.teamDataRepository .Setup(x => x.GetAsync(It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync(teamData); this.membersService .Setup(x => x.GetUsersAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync(userDataEntities); // Act Func <Task> task = async() => await activityContext.RunAsync((this.notificationId, this.teamId), this.logger.Object); // Assert await task.Should().NotThrowAsync(); this.notificationDataRepository.Verify(x => x.SaveWarningInNotificationDataEntityAsync(It.Is <string>(x => x.Equals(this.notificationId)), It.IsAny <string>()), Times.Once); }
public async Task <ActionResult> PreviewDraftNotificationAsync( [FromBody] DraftNotificationPreviewRequest draftNotificationPreviewRequest) { if (draftNotificationPreviewRequest == null || string.IsNullOrWhiteSpace(draftNotificationPreviewRequest.DraftNotificationId) || string.IsNullOrWhiteSpace(draftNotificationPreviewRequest.TeamsTeamId) || string.IsNullOrWhiteSpace(draftNotificationPreviewRequest.TeamsChannelId)) { return(this.BadRequest()); } var notificationEntity = await this.notificationDataRepository.GetAsync( NotificationDataTableNames.DraftNotificationsPartition, draftNotificationPreviewRequest.DraftNotificationId); if (notificationEntity == null) { return(this.BadRequest($"Notification {draftNotificationPreviewRequest.DraftNotificationId} not found.")); } var teamDataEntity = new TeamDataEntity(); teamDataEntity.TenantId = this.HttpContext.User.FindFirstValue(Common.Constants.ClaimTypeTenantId); teamDataEntity.ServiceUrl = await this.appSettingsService.GetServiceUrlAsync(); var result = await this.draftNotificationPreviewService.SendPreview( notificationEntity, teamDataEntity, draftNotificationPreviewRequest.TeamsChannelId); return(this.StatusCode((int)result)); }
public async Task SyncTeamMembersActivitySuccessTest() { // Arrange var activityContext = this.GetSyncTeamMembersActivity(); TeamDataEntity teamData = new TeamDataEntity() { TenantId = "Tanant1", TeamId = "Team1", ServiceUrl = "serviceUrl" }; IEnumerable <UserDataEntity> userData = new List <UserDataEntity>() { new UserDataEntity() }; teamDataRepository .Setup(x => x.GetAsync(It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync(teamData); membersService .Setup(x => x.GetUsersAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync(userData); sentNotificationDataRepository .Setup(x => x.BatchInsertOrMergeAsync(It.IsAny <IEnumerable <SentNotificationDataEntity> >())) .Returns(Task.CompletedTask); // Act Func <Task> task = async() => await activityContext.RunAsync((notificationId, teamId), logger.Object); // Assert await task.Should().NotThrowAsync(); teamDataRepository.Verify(x => x.GetAsync(It.IsAny <string>(), It.Is <string>(x => x.Equals(teamId)))); membersService.Verify(x => x.GetUsersAsync(It.Is <string>(x => x.Equals(teamData.TeamId)), It.Is <string>(x => x.Equals(teamData.TenantId)), It.Is <string>(x => x.Equals(teamData.ServiceUrl)))); }
/// <summary> /// Run the activity. /// Gets recipient data list (team rosters). /// </summary> /// <param name="context">Durable orchestration context.</param> /// <param name="notificationDataEntityId">Notification data entity id.</param> /// <param name="teamDataEntity">Team data entity.</param> /// <param name="log">Logging service.</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> public async Task RunAsync( IDurableOrchestrationContext context, string notificationDataEntityId, TeamDataEntity teamDataEntity, ILogger log) { try { await context.CallActivityWithRetryAsync <IEnumerable <UserDataEntity> >( nameof(GetRecipientDataListForRosterActivity.GetRecipientDataListForRosterAsync), ActivitySettings.CommonActivityRetryOptions, new GetRecipientDataListForRosterActivityDTO { NotificationDataEntityId = notificationDataEntityId, TeamDataEntity = teamDataEntity, }); } catch (Exception ex) { var format = this.localizer.GetString("FailedToGetMembersForTeamFormat"); var errorMessage = string.Format(format, teamDataEntity.TeamId, ex.Message); log.LogError(ex, errorMessage); await this.handleWarningActivity.RunAsync(context, notificationDataEntityId, errorMessage); } }
/// <summary> /// The main point of this is to set the recipient Id, service URL, and conversation Id for the send parameters. /// </summary> /// <param name="getSendNotificationParamsResponse">The send notification parameters to be updated.</param> /// <param name="incomingTeamDataEntity">The incoming team data entity.</param> private void SetParamsForTeamRecipient( GetSendNotificationParamsResponse getSendNotificationParamsResponse, TeamDataEntity incomingTeamDataEntity) { // All necessary parameters will always be set in the incoming team data. getSendNotificationParamsResponse.RecipientId = incomingTeamDataEntity.TeamId; getSendNotificationParamsResponse.ServiceUrl = incomingTeamDataEntity.ServiceUrl; getSendNotificationParamsResponse.ConversationId = incomingTeamDataEntity.TeamId; }
/// <summary> /// Creates recipient from TeamDataEntity. /// </summary> /// <param name="notificationId">Notification Id.</param> /// <param name="team">Team entity.</param> /// <returns><see cref="SentNotificationDataEntity"/> object.</returns> private SentNotificationDataEntity ConvertToRecipient(string notificationId, TeamDataEntity team) { return(new SentNotificationDataEntity { PartitionKey = notificationId, RowKey = team.TeamId, RecipientType = SentNotificationDataEntity.TeamRecipientType, RecipientId = team.TeamId, StatusCode = SentNotificationDataEntity.InitializationStatusCode, ConversationId = team.TeamId, TenantId = team.TenantId, ServiceUrl = team.ServiceUrl, }); }
/// <summary> /// Creates a SentNotificationDataEntity in an initialized state from the given TeamDataEntity /// and partition key. /// Makes sure to set the correct recipient type for having been created from a TeamDataEntity. /// </summary> /// <param name="teamDataEntity">The team data entity.</param> /// <param name="partitionKey">The partition key.</param> /// <returns>The sent notification data entity.</returns> public static SentNotificationDataEntity CreateInitialSentNotificationDataEntity( this TeamDataEntity teamDataEntity, string partitionKey) { return(new SentNotificationDataEntity { PartitionKey = partitionKey, RowKey = teamDataEntity.TeamId, RecipientType = SentNotificationDataEntity.TeamRecipientType, RecipientId = teamDataEntity.TeamId, StatusCode = SentNotificationDataEntity.InitializationStatusCode, ConversationId = teamDataEntity.TeamId, TenantId = teamDataEntity.TenantId, ServiceUrl = teamDataEntity.ServiceUrl, }); }
public async Task SyncTeamMembers_OnlyExistingMemberUser_StoreInSentNotificationTable() { // Arrange var activityContext = this.GetSyncTeamMembersActivity(); var teamData = new TeamDataEntity() { TenantId = "Tanant1", TeamId = "Team1", ServiceUrl = "serviceUrl" }; var userDataList = new List <UserDataEntity>() { new UserDataEntity() { UserId = "userId", UserType = UserType.Member }, new UserDataEntity() { UserId = "userId", UserType = UserType.Member }, }; var userData = new UserDataEntity() { UserId = "userId" }; this.teamDataRepository .Setup(x => x.GetAsync(It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync(teamData); this.membersService .Setup(x => x.GetUsersAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync(userDataList); this.userDataRepository .Setup(x => x.GetAsync(It.IsAny <string>(), It.IsAny <string>())) .ReturnsAsync(userData); this.sentNotificationDataRepository .Setup(x => x.BatchInsertOrMergeAsync(It.IsAny <IEnumerable <SentNotificationDataEntity> >())) .Returns(Task.CompletedTask); // Act await activityContext.RunAsync((this.notificationId, this.teamId), this.logger.Object); // Assert this.sentNotificationDataRepository.Verify(x => x.BatchInsertOrMergeAsync(It.IsAny <IEnumerable <SentNotificationDataEntity> >()), Times.Once); }
public async Task Get_TeamDataSevice_ShouldNeverBeInvokedForEmptysentNotificationData() { // Arrange var activityInstance = this.GetDataStreamFacadeInstance(); var teamData = new TeamDataEntity(); this.sentNotificationDataRepository .Setup(x => x.GetStreamsAsync(this.notificationId, null)) .Returns(this.sentNotificationDataEmptyList.ToAsyncEnumerable()); this.teamDataRepository.Setup(x => x.GetAsync(It.IsAny <string>(), It.IsAny <string>())).ReturnsAsync(teamData); // Act var teamDataStream = activityInstance.GetTeamDataStreamAsync(this.notificationId); await teamDataStream.ForEachAsync(x => x.ToList()); // Assert this.teamDataRepository.Verify(x => x.GetAsync(It.Is <string>(x => x.Equals(TeamDataTableNames.TeamDataPartition)), It.IsAny <string>()), Times.Never); }
private static TeamDataEntity ParseTeamData(IConversationUpdateActivity activity) { var channelData = activity.GetChannelData <TeamsChannelData>(); if (channelData != null) { var teamsDataEntity = new TeamDataEntity { PartitionKey = PartitionKeyNames.TeamDataTable.TeamDataPartition, RowKey = channelData.Team.Id, TeamId = channelData.Team.Id, Name = channelData.Team.Name, ServiceUrl = activity.ServiceUrl, TenantId = channelData.Tenant.Id, }; return(teamsDataEntity); } return(null); }
public async Task GetTeamDataStreamAsyncSuccesTest() { // Arrange var activityInstance = GetDataStreamFacade(); var teamData = new TeamDataEntity(); sentNotificationDataRepository .Setup(x => x.GetStreamsAsync(notificationId, null)) .Returns(data.ToAsyncEnumerable()); teamDataRepository.Setup(x => x.GetAsync(It.IsAny<string>(), It.IsAny<string>())).ReturnsAsync(teamData); // Act var userDataStream = activityInstance.GetTeamDataStreamAsync(notificationId); Func<Task> task = async () => await userDataStream.ForEachAsync(x => x.ToList()); // Assert await task.Should().NotThrowAsync(); sentNotificationDataRepository.Verify(x => x.GetStreamsAsync(It.Is<string>(x => x.Equals(notificationId)), null), Times.Once); teamDataRepository.Verify(x => x.GetAsync(It.Is<string>(x=>x.Equals(TeamDataTableNames.TeamDataPartition)),It.IsAny<string>()), Times.AtLeastOnce); }
/// <summary> /// Prepare conversation. /// </summary> /// <param name="teamDataEntity">Teams's data.</param> /// <param name="channelId">Teams's channel ID.</param> /// <returns>conversation Reference of chat/conversation.</returns> private ConversationReference PrepareConversationReferenceAsync(TeamDataEntity teamDataEntity, string channelId) { var channelAccount = new ChannelAccount { Id = $"28:{this.botAppId}", }; var conversationAccount = new ConversationAccount { ConversationType = DraftNotificationPreviewService.ChannelConversationType, Id = channelId, TenantId = teamDataEntity.TenantId, }; var conversationReference = new ConversationReference { Bot = channelAccount, ChannelId = DraftNotificationPreviewService.MsTeamsChannelId, Conversation = conversationAccount, ServiceUrl = teamDataEntity.ServiceUrl, }; return(conversationReference); }
/// <summary> /// Send a preview of a draft notification. /// </summary> /// <param name="draftNotificationEntity">Draft notification entity.</param> /// <param name="teamDataEntity">The team data entity.</param> /// <param name="teamsChannelId">The Teams channel id.</param> /// <returns>It returns HttpStatusCode.OK, if this method triggers the bot service to send the adaptive card successfully. /// It returns HttpStatusCode.TooManyRequests, if the bot service throttled the request to send the adaptive card.</returns> public async Task <HttpStatusCode> SendPreview(NotificationDataEntity draftNotificationEntity, TeamDataEntity teamDataEntity, string teamsChannelId) { if (draftNotificationEntity == null) { throw new ArgumentException("Null draft notification entity."); } if (teamDataEntity == null) { throw new ArgumentException("Null team data entity."); } if (string.IsNullOrWhiteSpace(teamsChannelId)) { throw new ArgumentException("Null channel id."); } // Create bot conversation reference. var conversationReference = this.PrepareConversationReferenceAsync(teamDataEntity, teamsChannelId); // Ensure the bot service URL is trusted. if (!MicrosoftAppCredentials.IsTrustedServiceUrl(conversationReference.ServiceUrl)) { MicrosoftAppCredentials.TrustServiceUrl(conversationReference.ServiceUrl); } // Trigger bot to send the adaptive card. try { await this.diConnectBotAdapter.ContinueConversationAsync( this.botAppId, conversationReference, async (turnContext, cancellationToken) => await this.SendAdaptiveCardAsync(turnContext, draftNotificationEntity), CancellationToken.None); return(HttpStatusCode.OK); } catch (ErrorResponseException e) { var errorResponse = (ErrorResponse)e.Body; if (errorResponse != null && errorResponse.Error.Code.Equals(DraftNotificationPreviewService.ThrottledErrorResponse, StringComparison.OrdinalIgnoreCase)) { return(HttpStatusCode.TooManyRequests); } throw; } }
/// <summary> /// Send a preview of a draft notification. /// </summary> /// <param name="draftNotificationEntity">Draft notification entity.</param> /// <param name="teamDataEntity">The team data entity.</param> /// <param name="teamsChannelId">The Teams channel id.</param> /// <returns>It returns HttpStatusCode.OK, if this method triggers the bot service to send the adaptive card successfully. /// It returns HttpStatusCode.TooManyRequests, if the bot service throttled the request to send the adaptive card.</returns> public async Task <HttpStatusCode> SendPreview(NotificationDataEntity draftNotificationEntity, TeamDataEntity teamDataEntity, string teamsChannelId) { if (draftNotificationEntity == null) { throw new ArgumentException("Null draft notification entity."); } if (teamDataEntity == null) { throw new ArgumentException("Null team data entity."); } if (string.IsNullOrWhiteSpace(teamsChannelId)) { throw new ArgumentException("Null channel id."); } // Create bot conversation reference. var conversationReference = this.PrepareConversationReferenceAsync(teamDataEntity, teamsChannelId); // Ensure the bot service URL is trusted. if (!MicrosoftAppCredentials.IsTrustedServiceUrl(conversationReference.ServiceUrl)) { MicrosoftAppCredentials.TrustServiceUrl(conversationReference.ServiceUrl); } // Trigger bot to send the adaptive card. try { var previewQueueMessageContent = new SendQueueMessageContent { NotificationId = draftNotificationEntity.Id, ActivtiyId = null, RecipientData = null, NotificationUpdatePreviewEntity = new NotificationUpdatePreviewEntity { ActionType = "PreviewNotification", NotificationDataEntity = null, ConversationReferance = conversationReference, MessageActivity = await this.GetPreviewMessageActivity(draftNotificationEntity), ServiceUrl = conversationReference.ServiceUrl, AppID = this.botAppId, }, }; await this.sendQueue.SendAsync(previewQueueMessageContent); return(HttpStatusCode.OK); } catch (ErrorResponseException e) { var errorResponse = (ErrorResponse)e.Body; if (errorResponse != null && errorResponse.Error.Code.Equals(DraftNotificationPreviewService.ThrottledErrorResponse, StringComparison.OrdinalIgnoreCase)) { return(HttpStatusCode.TooManyRequests); } throw; } }