public async Task CalculateDeltaForInitialGroupSyncWithMissingTargetGroup() { var calculator = new MembershipDifferenceCalculator <AzureADUser>(); var senderRecipients = new EmailSenderRecipient(); var syncjobRepository = new MockSyncJobRepository(); var loggingRepository = new MockLoggingRepository(); var mailRepository = new MockMailRepository(); var dryRun = new DryRunValue(); var thresholdConfig = new ThresholdConfig(5, 3, 3, 10); var graphUpdaterService = new MockGraphUpdaterService(mailRepository); var deltaCalculator = new DeltaCalculatorService( calculator, syncjobRepository, loggingRepository, senderRecipients, graphUpdaterService, dryRun, thresholdConfig, _gmmResources, _localizationRepository); syncjobRepository.ExistingSyncJobs.Add((_partitionKey, _rowKey), _job); graphUpdaterService.GroupsToUsers.Add(_sources[0].ObjectId, _users); var response = await deltaCalculator.CalculateDifferenceAsync(_membership, new List <AzureADUser>()); Assert.AreEqual(SyncStatus.Error, response.SyncStatus); Assert.AreEqual(GraphUpdaterStatus.Error, response.GraphUpdaterStatus); Assert.IsTrue(loggingRepository.MessagesLogged.Any(x => x.Message.Contains($"destination group {_membership.Destination} doesn't exist"))); }
public async Task CalculateDeltaWithMissingSyncJob() { var calculator = new MembershipDifferenceCalculator <AzureADUser>(); var senderRecipients = new EmailSenderRecipient(); var syncjobRepository = new MockSyncJobRepository(); var loggingRepository = new MockLoggingRepository(); var mailRepository = new MockMailRepository(); var dryRun = new DryRunValue(); var thresholdConfig = new ThresholdConfig(5, 3, 3, 10); var graphUpdaterService = new MockGraphUpdaterService(mailRepository); var deltaCalculator = new DeltaCalculatorService( calculator, syncjobRepository, loggingRepository, senderRecipients, graphUpdaterService, dryRun, thresholdConfig, _gmmResources, _localizationRepository); var targetGroupUsers = new List <AzureADUser>(); graphUpdaterService.GroupsToUsers.Add(_sources[0].ObjectId, _users); graphUpdaterService.GroupsToUsers.Add(_targetGroupId, targetGroupUsers); var response = await deltaCalculator.CalculateDifferenceAsync(_membership, targetGroupUsers); Assert.AreEqual(SyncStatus.Error, response.SyncStatus); Assert.AreEqual(GraphUpdaterStatus.Error, response.GraphUpdaterStatus); }
public async Task CanGroupSyncIntoEmptyGroup() { await _groupRepo.AddUsersToGroup(_testUsers, _sourceGroup); await Task.Delay(_waitForGraph); // Sometimes you have to wait for the graph to catch up. var sourceGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_sourceGroup.ObjectId); Assert.AreEqual(UserCount, _testUsers.Length); Assert.IsTrue(SequencesMatch(_testUsers, sourceGroupMembers)); var destinationGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_destinationGroup.ObjectId); Assert.AreEqual(0, destinationGroupMembers.Count); var calc = new MembershipDifferenceCalculator <AzureADUser>(); var membershipDelta = calc.CalculateDifference(sourceGroupMembers, destinationGroupMembers); Assert.IsTrue(SequencesMatch(_testUsers, membershipDelta.ToAdd)); Assert.AreEqual(0, membershipDelta.ToRemove.Count); await _groupRepo.AddUsersToGroup(membershipDelta.ToAdd, _destinationGroup); await _groupRepo.RemoveUsersFromGroup(membershipDelta.ToRemove, _destinationGroup); await Task.Delay(_waitForGraph); destinationGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_destinationGroup.ObjectId); Assert.IsTrue(SequencesMatch(_testUsers, destinationGroupMembers)); }
public async Task CanGroupSyncIntoNonEmptyGroup() { var initialSourceUsers = _testUsers.Where((_, idx) => idx % 2 == 0).ToArray(); var inititalDestinationUsers = _testUsers.Where((_, idx) => idx % 2 == 1).ToArray(); await _groupRepo.AddUsersToGroup(initialSourceUsers, _sourceGroup); await _groupRepo.AddUsersToGroup(inititalDestinationUsers, _destinationGroup); await Task.Delay(_waitForGraph); // Sometimes you have to wait for the graph to catch up. var sourceGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_sourceGroup.ObjectId); Assert.IsTrue(SequencesMatch(initialSourceUsers, sourceGroupMembers)); var destinationGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_destinationGroup.ObjectId); Assert.IsTrue(SequencesMatch(inititalDestinationUsers, destinationGroupMembers)); var calc = new MembershipDifferenceCalculator <AzureADUser>(); var membershipDelta = calc.CalculateDifference(sourceGroupMembers, destinationGroupMembers); Assert.IsTrue(SequencesMatch(initialSourceUsers, membershipDelta.ToAdd)); Assert.IsTrue(SequencesMatch(inititalDestinationUsers, membershipDelta.ToRemove)); await _groupRepo.AddUsersToGroup(membershipDelta.ToAdd, _destinationGroup); await _groupRepo.RemoveUsersFromGroup(membershipDelta.ToRemove, _destinationGroup); await Task.Delay(_waitForGraph); // Sometimes you have to wait for the graph to catch up. destinationGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_destinationGroup.ObjectId); Assert.IsTrue(SequencesMatch(initialSourceUsers, destinationGroupMembers)); }
public async Task SendNotificationToSupportAsFallBack() { var calculator = new MembershipDifferenceCalculator <AzureADUser>(); var senderRecipients = new EmailSenderRecipient { SupportEmailAddresses = "*****@*****.**" }; var syncjobRepository = new MockSyncJobRepository(); var loggingRepository = new MockLoggingRepository(); var mailRepository = new MockMailRepository(); var dryRun = new DryRunValue(); var thresholdConfig = new ThresholdConfig(5, 3, 3, 10); var graphUpdaterService = new MockGraphUpdaterService(mailRepository); var deltaCalculator = new DeltaCalculatorService( calculator, syncjobRepository, loggingRepository, senderRecipients, graphUpdaterService, dryRun, thresholdConfig, _gmmResources, _localizationRepository); var targetGroupUsers = new List <AzureADUser>(); var ownersPage = new GroupOwnersPage(); var owners = new List <User>(GenerateGraphUsers(10)); owners.ForEach(ownersPage.Add); _job.LastRunTime = DateTime.UtcNow.AddDays(-1); _job.ThresholdViolations = 2; syncjobRepository.ExistingSyncJobs.Add((_partitionKey, _rowKey), _job); graphUpdaterService.GroupsToUsers.Add(_sources[0].ObjectId, _users); graphUpdaterService.GroupsToUsers.Add(_targetGroupId, targetGroupUsers); graphUpdaterService.Groups.Add(_sources[0].ObjectId, new Group { Id = _sources[0].ObjectId.ToString(), DisplayName = "Source Group" }); graphUpdaterService.Groups.Add(_targetGroupId, new Group { Id = _targetGroupId.ToString(), DisplayName = "Target Group", Owners = ownersPage }); var response = await deltaCalculator.CalculateDifferenceAsync(_membership, targetGroupUsers); var emailMessage = mailRepository.SentEmails.Single(); Assert.AreEqual(SyncStatus.Idle, response.SyncStatus); Assert.AreEqual(GraphUpdaterStatus.ThresholdExceeded, response.GraphUpdaterStatus); Assert.AreEqual(targetGroupUsers.Count, graphUpdaterService.GroupsToUsers[_targetGroupId].Count); Assert.IsTrue(loggingRepository.MessagesLogged.Any(x => x.Message.Contains("is greater than threshold value"))); Assert.AreEqual(SyncThresholdBothEmailBody, emailMessage.Content); Assert.AreEqual(_targetGroupId.ToString(), emailMessage.AdditionalContentParams[1]); Assert.AreEqual(5, emailMessage.AdditionalContentParams.Length); Assert.AreEqual(senderRecipients.SupportEmailAddresses, emailMessage.ToEmailAddresses); }
public async Task CanGroupSyncWithNestedGroups() { // the bottom half is in the source // the upper two thirds are in the destination var initialSourceUsers = _testUsers.Where((_, idx) => idx < (UserCount / 2)).ToArray(); var initialDestinationUsers = _testUsers.Where((_, idx) => idx > (UserCount / 3)).ToArray(); await _groupRepo.AddUsersToGroup(initialDestinationUsers, _destinationGroup); const int testGroupCount = 5; var testGroups = new AzureADGroup[testGroupCount]; for (int i = 0; i < testGroupCount; i++) { testGroups[i] = await CreateOrClearGroup( new Group { DisplayName = $"TestSourceGroup{i}", MailEnabled = false, MailNickname = $"testsourcegroup{i}", SecurityEnabled = true }); _groupsToRemove.Add(testGroups[i]); // add all the users to the first group, every other user to the second group, etc. await _groupRepo.AddUsersToGroup(initialSourceUsers.Where((_, idx) => idx % (i + 1) == 0), testGroups[i]); await _graphServiceClient.Groups[_sourceGroup.ObjectId.ToString()].Members.References.Request().AddAsync(new DirectoryObject { Id = testGroups[i].ObjectId.ToString() }); } await Task.Delay(_waitForGraph); // Sometimes you have to wait for the graph to catch up. var sourceGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_sourceGroup.ObjectId); Assert.IsTrue(SequencesMatch(initialSourceUsers, sourceGroupMembers)); var destinationGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_destinationGroup.ObjectId); Assert.IsTrue(SequencesMatch(initialDestinationUsers, destinationGroupMembers)); var calc = new MembershipDifferenceCalculator <AzureADUser>(); var membershipDelta = calc.CalculateDifference(sourceGroupMembers, destinationGroupMembers); // Have to add the bottom third and remove the top half Assert.IsTrue(SequencesMatch(_testUsers.Where((_, idx) => idx <= (UserCount / 3)), membershipDelta.ToAdd)); Assert.IsTrue(SequencesMatch(_testUsers.Where((_, idx) => idx >= (UserCount / 2)), membershipDelta.ToRemove)); await _groupRepo.AddUsersToGroup(membershipDelta.ToAdd, _destinationGroup); await _groupRepo.RemoveUsersFromGroup(membershipDelta.ToRemove, _destinationGroup); await Task.Delay(_waitForGraph); // Sometimes you have to wait for the graph to catch up. destinationGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_destinationGroup.ObjectId); Assert.IsTrue(SequencesMatch(initialSourceUsers, destinationGroupMembers)); }
public async Task CalculateDeltaForNonInitialGroupSyncExceedingBothThresholds() { var calculator = new MembershipDifferenceCalculator <AzureADUser>(); var senderRecipients = new EmailSenderRecipient(); var syncjobRepository = new MockSyncJobRepository(); var loggingRepository = new MockLoggingRepository(); var mailRepository = new MockMailRepository(); var dryRun = new DryRunValue(); var thresholdConfig = new ThresholdConfig(5, 3, 3, 10); var graphUpdaterService = new MockGraphUpdaterService(mailRepository); var deltaCalculator = new DeltaCalculatorService( calculator, syncjobRepository, loggingRepository, senderRecipients, graphUpdaterService, dryRun, thresholdConfig, _gmmResources, _localizationRepository); var users = _membership.SourceMembers; _membership.SourceMembers = users.Take(2).ToList(); _job.LastRunTime = DateTime.UtcNow.AddDays(-1); _job.ThresholdViolations = 2; var targetGroupUsers = users.Skip(2).Take(2).ToList(); syncjobRepository.ExistingSyncJobs.Add((_partitionKey, _rowKey), _job); graphUpdaterService.GroupsToUsers.Add(_sources[0].ObjectId, _membership.SourceMembers); graphUpdaterService.GroupsToUsers.Add(_targetGroupId, targetGroupUsers); graphUpdaterService.Groups.Add(_sources[0].ObjectId, new Microsoft.Graph.Group { Id = _sources[0].ObjectId.ToString(), DisplayName = "Source Group" }); graphUpdaterService.Groups.Add(_targetGroupId, new Microsoft.Graph.Group { Id = _targetGroupId.ToString(), DisplayName = "Target Group" }); var response = await deltaCalculator.CalculateDifferenceAsync(_membership, targetGroupUsers); var emailMessage = mailRepository.SentEmails.Single(); Assert.AreEqual(SyncStatus.Idle, response.SyncStatus); Assert.AreEqual(GraphUpdaterStatus.ThresholdExceeded, response.GraphUpdaterStatus); Assert.AreEqual(targetGroupUsers.Count, graphUpdaterService.GroupsToUsers[_targetGroupId].Count); Assert.IsTrue(loggingRepository.MessagesLogged.Any(x => x.Message.Contains("is lesser than threshold value"))); Assert.AreEqual(SyncThresholdBothEmailBody, emailMessage.Content); Assert.AreEqual(_targetGroupId.ToString(), emailMessage.AdditionalContentParams[1]); Assert.AreEqual(5, emailMessage.AdditionalContentParams.Length); }
public async Task CalculateDeltaForInitialGroupSync() { var calculator = new MembershipDifferenceCalculator <AzureADUser>(); var senderRecipients = new EmailSenderRecipient(); var syncjobRepository = new MockSyncJobRepository(); var loggingRepository = new MockLoggingRepository(); var mailRepository = new MockMailRepository(); var graphUpdaterService = new MockGraphUpdaterService(mailRepository); var dryRun = new DryRunValue(); var thresholdConfig = new ThresholdConfig(5, 3, 3, 10); dryRun.DryRunEnabled = false; var deltaCalculator = new DeltaCalculatorService( calculator, syncjobRepository, loggingRepository, senderRecipients, graphUpdaterService, dryRun, thresholdConfig, _gmmResources, _localizationRepository); var targetGroupUsers = new List <AzureADUser>(); syncjobRepository.ExistingSyncJobs.Add((_partitionKey, _rowKey), _job); graphUpdaterService.GroupsToUsers.Add(_sources[0].ObjectId, _users); graphUpdaterService.GroupsToUsers.Add(_targetGroupId, targetGroupUsers); graphUpdaterService.Groups.Add(_sources[0].ObjectId, new Microsoft.Graph.Group { Id = _sources[0].ObjectId.ToString(), DisplayName = "Source Group" }); graphUpdaterService.Groups.Add(_targetGroupId, new Microsoft.Graph.Group { Id = _targetGroupId.ToString(), DisplayName = "Target Group" }); var response = await deltaCalculator.CalculateDifferenceAsync(_membership, targetGroupUsers); Assert.AreEqual(SyncStatus.Idle, response.SyncStatus); Assert.AreEqual(_users.Count, response.MembersToAdd.Count); Assert.IsTrue(response.IsInitialSync); Assert.AreEqual(GraphUpdaterStatus.Ok, response.GraphUpdaterStatus); }
public async Task CanGroupSyncIntoOverlappingGroup() { // the bottom half is in the source // the upper two thirds are in the destination var initialSourceUsers = _testUsers.Where((_, idx) => idx < (UserCount / 2)).ToArray(); var initialDestinationUsers = _testUsers.Where((_, idx) => idx > (UserCount / 3)).ToArray(); await _groupRepo.AddUsersToGroup(initialSourceUsers, _sourceGroup); await _groupRepo.AddUsersToGroup(initialDestinationUsers, _destinationGroup); await Task.Delay(_waitForGraph); // Sometimes you have to wait for the graph to catch up. var sourceGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_sourceGroup.ObjectId); Assert.IsTrue(SequencesMatch(initialSourceUsers, sourceGroupMembers)); var destinationGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_destinationGroup.ObjectId); Assert.IsTrue(SequencesMatch(initialDestinationUsers, destinationGroupMembers)); var calc = new MembershipDifferenceCalculator <AzureADUser>(); var membershipDelta = calc.CalculateDifference(sourceGroupMembers, destinationGroupMembers); // Have to add the bottom third and remove the top half Assert.IsTrue(SequencesMatch(_testUsers.Where((_, idx) => idx <= (UserCount / 3)), membershipDelta.ToAdd)); Assert.IsTrue(SequencesMatch(_testUsers.Where((_, idx) => idx >= (UserCount / 2)), membershipDelta.ToRemove)); await _groupRepo.AddUsersToGroup(membershipDelta.ToAdd, _destinationGroup); await _groupRepo.RemoveUsersFromGroup(membershipDelta.ToRemove, _destinationGroup); await Task.Delay(_waitForGraph); // Sometimes you have to wait for the graph to catch up. destinationGroupMembers = await _groupRepo.GetUsersInGroupTransitively(_destinationGroup.ObjectId); Assert.IsTrue(SequencesMatch(initialSourceUsers, destinationGroupMembers)); }
public async Task DoNotSendNotificationToRequestor(int currentThresoldViolations) { var calculator = new MembershipDifferenceCalculator <AzureADUser>(); var senderRecipients = new EmailSenderRecipient { SyncDisabledCCAddresses = "*****@*****.**" }; var syncjobRepository = new MockSyncJobRepository(); var loggingRepository = new MockLoggingRepository(); var mailRepository = new MockMailRepository(); var dryRun = new DryRunValue(); var thresholdConfig = new ThresholdConfig(5, 3, 3, 10); var graphUpdaterService = new MockGraphUpdaterService(mailRepository); var deltaCalculator = new DeltaCalculatorService( calculator, syncjobRepository, loggingRepository, senderRecipients, graphUpdaterService, dryRun, thresholdConfig, _gmmResources, _localizationRepository); var targetGroupUsers = new List <AzureADUser>(); var ownersPage = new GroupOwnersPage(); var owners = new List <User>(); foreach (var email in _job.Requestor.Split(",", StringSplitOptions.RemoveEmptyEntries)) { owners.Add(new User { Mail = email }); } owners.AddRange(GenerateGraphUsers(3)); owners.ForEach(ownersPage.Add); _job.LastRunTime = DateTime.UtcNow.AddDays(-1); _job.ThresholdViolations = currentThresoldViolations; syncjobRepository.ExistingSyncJobs.Add((_partitionKey, _rowKey), _job); graphUpdaterService.GroupsToUsers.Add(_sources[0].ObjectId, _users); graphUpdaterService.GroupsToUsers.Add(_targetGroupId, targetGroupUsers); graphUpdaterService.Groups.Add(_sources[0].ObjectId, new Group { Id = _sources[0].ObjectId.ToString(), DisplayName = "Source Group" }); graphUpdaterService.Groups.Add(_targetGroupId, new Group { Id = _targetGroupId.ToString(), DisplayName = "Target Group", Owners = ownersPage }); var response = await deltaCalculator.CalculateDifferenceAsync(_membership, targetGroupUsers); var emailMessage = mailRepository.SentEmails.Count(); Assert.AreEqual(SyncStatus.Idle, response.SyncStatus); Assert.AreEqual(GraphUpdaterStatus.ThresholdExceeded, response.GraphUpdaterStatus); Assert.AreEqual(targetGroupUsers.Count, graphUpdaterService.GroupsToUsers[_targetGroupId].Count); Assert.IsTrue(loggingRepository.MessagesLogged.Any(x => x.Message.Contains("is greater than threshold value"))); Assert.AreEqual(0, mailRepository.SentEmails.Count); }