public async Task UpdatePermissionForUser_WhenPermissionsAreSetOnAFundingStreamAndNoneHaveBeenSetBefore_ThenPermissionsSaved() { // Arrange IUserRepository userRepository = CreateUserRepository(); User user = new User() { UserId = UserId }; userRepository .GetUserById(Arg.Is(UserId)) .Returns(user); FundingStreamPermission existingPermission = null; userRepository .GetFundingStreamPermission(Arg.Is(UserId), Arg.Is(FundingStreamId)) .Returns(existingPermission); userRepository .UpdateFundingStreamPermission(Arg.Any <FundingStreamPermission>()) .Returns(HttpStatusCode.Created); ICacheProvider cacheProvider = CreateCacheProvider(); FundingStreamPermissionUpdateModel updateModel = new FundingStreamPermissionUpdateModel() { CanApproveFunding = true, CanChooseFunding = false, CanCreateSpecification = false, CanEditCalculations = false, CanEditSpecification = false, CanMapDatasets = false, CanReleaseFunding = false, CanCreateTemplates = true, CanEditTemplates = true, CanDeleteTemplates = true, CanApproveTemplates = true, CanCreateProfilePattern = true, CanEditProfilePattern = true, CanDeleteProfilePattern = true, CanAssignProfilePattern = false, CanApplyCustomProfilePattern = false, CanApproveCalculations = true, CanApproveAnyCalculations = false, CanApproveAllCalculations = false }; IVersionRepository <FundingStreamPermissionVersion> versionRepository = CreateFundingStreamPermissionRepository(); versionRepository .GetNextVersionNumber(Arg.Any <FundingStreamPermissionVersion>(), 0, Arg.Is(UserId)) .Returns(1); FundingStreamPermissionService service = CreateService( userRepository, cacheProvider: cacheProvider, fundingStreamPermissionVersionRepository: versionRepository); // Act IActionResult result = await service.UpdatePermissionForUser(UserId, FundingStreamId, updateModel, null); // Assert result .Should() .BeOfType <OkObjectResult>() .Which .Value .Should() .BeEquivalentTo <FundingStreamPermissionCurrent>(new FundingStreamPermissionCurrent() { UserId = UserId, FundingStreamId = FundingStreamId, CanApproveFunding = true, CanChooseFunding = false, CanCreateSpecification = false, CanEditCalculations = false, CanEditSpecification = false, CanMapDatasets = false, CanReleaseFunding = false, CanCreateTemplates = true, CanEditTemplates = true, CanDeleteTemplates = true, CanApproveTemplates = true, CanCreateProfilePattern = true, CanEditProfilePattern = true, CanDeleteProfilePattern = true, CanAssignProfilePattern = false, CanApplyCustomProfilePattern = false, CanApproveCalculations = true, CanApproveAnyCalculations = false, CanApproveAllCalculations = false, }); await userRepository .Received(1) .UpdateFundingStreamPermission(Arg.Is <FundingStreamPermission>(p => p.FundingStreamId == FundingStreamId && p.UserId == UserId && p.CanApproveFunding && !p.CanChooseFunding && !p.CanCreateSpecification && !p.CanEditCalculations && !p.CanEditSpecification && !p.CanMapDatasets && !p.CanReleaseFunding && p.CanCreateTemplates && p.CanEditTemplates && p.CanDeleteTemplates && p.CanApproveTemplates && p.CanCreateProfilePattern && p.CanEditProfilePattern && p.CanDeleteProfilePattern && !p.CanAssignProfilePattern && !p.CanApplyCustomProfilePattern && p.CanApproveCalculations && !p.CanApproveAnyCalculations && !p.CanApproveAllCalculations )); await cacheProvider .Received(1) .DeleteHashSet(Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}")); await versionRepository .Received(1) .GetNextVersionNumber(Arg.Is <FundingStreamPermissionVersion>(v => v.EntityId == $"{UserId}_{FundingStreamId}"), partitionKeyId: Arg.Is(UserId)); await versionRepository .Received(1) .SaveVersion(Arg.Is <FundingStreamPermissionVersion>(v => v.EntityId == $"{UserId}_{FundingStreamId}" && v.Version == 1 ), Arg.Is(UserId)); }
public async Task UpdatePermissionForUser_WhenPermissionsAreSetOnAFundingStreamAndNoneHaveBeenSetBefore_ThenPermissionsSaved() { // Arrange IUserRepository userRepository = CreateUserRepository(); User user = new User() { UserId = UserId }; userRepository .GetUserById(Arg.Is(UserId)) .Returns(user); FundingStreamPermission existingPermission = null; userRepository .GetFundingStreamPermission(Arg.Is(UserId), Arg.Is(FundingStreamId)) .Returns(existingPermission); userRepository .UpdateFundingStreamPermission(Arg.Any <FundingStreamPermission>()) .Returns(HttpStatusCode.Created); ICacheProvider cacheProvider = CreateCacheProvider(); FundingStreamPermissionUpdateModel updateModel = new FundingStreamPermissionUpdateModel() { CanApproveFunding = true, CanChooseFunding = false, CanCreateSpecification = false, CanEditCalculations = false, CanEditSpecification = false, CanMapDatasets = false, CanPublishFunding = false, }; string json = JsonConvert.SerializeObject(updateModel); byte[] byteArray = Encoding.UTF8.GetBytes(json); MemoryStream stream = new MemoryStream(byteArray); HttpRequest request = Substitute.For <HttpRequest>(); request .Body .Returns(stream); IVersionRepository <FundingStreamPermissionVersion> versionRepository = CreateFundingStreamPermissionRepository(); versionRepository .GetNextVersionNumber(Arg.Any <FundingStreamPermissionVersion>(), 0, Arg.Is(UserId)) .Returns(1); FundingStreamPermissionService service = CreateService( userRepository, cacheProvider: cacheProvider, fundingStreamPermissionVersionRepository: versionRepository); // Act IActionResult result = await service.UpdatePermissionForUser(UserId, FundingStreamId, request); // Assert result .Should() .BeOfType <OkObjectResult>() .Which .Value .Should() .BeEquivalentTo <FundingStreamPermissionCurrent>(new FundingStreamPermissionCurrent() { UserId = UserId, FundingStreamId = FundingStreamId, CanApproveFunding = true, CanChooseFunding = false, CanCreateSpecification = false, CanEditCalculations = false, CanEditSpecification = false, CanMapDatasets = false, CanPublishFunding = false, }); await userRepository .Received(1) .UpdateFundingStreamPermission(Arg.Is <FundingStreamPermission>(p => p.FundingStreamId == FundingStreamId && p.UserId == UserId && p.CanApproveFunding && !p.CanChooseFunding && !p.CanCreateSpecification && !p.CanEditCalculations && !p.CanEditSpecification && !p.CanMapDatasets && !p.CanPublishFunding )); await cacheProvider .Received(1) .DeleteHashSet(Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}")); await versionRepository .Received(1) .GetNextVersionNumber(Arg.Is <FundingStreamPermissionVersion>(v => v.EntityId == $"{UserId}_{FundingStreamId}"), partitionKeyId: Arg.Is(UserId)); await versionRepository .Received(1) .SaveVersion(Arg.Is <FundingStreamPermissionVersion>(v => v.EntityId == $"{UserId}_{FundingStreamId}" && v.Version == 1 ), Arg.Is(UserId)); }
public async Task <IActionResult> UpdatePermissionForUser(string userId, string fundingStreamId, FundingStreamPermissionUpdateModel updateModel, Reference author) { if (string.IsNullOrWhiteSpace(userId)) { return(new BadRequestObjectResult($"{nameof(userId)} is empty or null")); } if (string.IsNullOrWhiteSpace(fundingStreamId)) { return(new BadRequestObjectResult($"{nameof(fundingStreamId)} is empty or null")); } User user = await _userRepositoryPolicy.ExecuteAsync(() => _userRepository.GetUserById(userId)); if (user == null) { return(new PreconditionFailedResult("userId not found")); } FundingStreamPermission existingPermissions = await _userRepositoryPolicy.ExecuteAsync(() => _userRepository.GetFundingStreamPermission(userId, fundingStreamId)); FundingStreamPermission newPermissions = _mapper.Map <FundingStreamPermissionUpdateModel, FundingStreamPermission>(updateModel); newPermissions.FundingStreamId = fundingStreamId; newPermissions.UserId = userId; if (existingPermissions == null || !existingPermissions.HasSamePermissions(newPermissions)) { HttpStatusCode saveResult = await _userRepositoryPolicy.ExecuteAsync(() => _userRepository.UpdateFundingStreamPermission(newPermissions)); if (saveResult != HttpStatusCode.OK && saveResult != HttpStatusCode.Created) { return(new InternalServerErrorResult($"Saving funding stream permission to repository returned '{saveResult}'")); } FundingStreamPermissionVersion version = new FundingStreamPermissionVersion() { Author = author, Permission = newPermissions, PublishStatus = Models.Versioning.PublishStatus.Updated, Date = DateTimeOffset.Now, UserId = userId, }; version.Version = await _fundingStreamPermissionVersionRepositoryPolicy.ExecuteAsync(() => _fundingStreamPermissionVersionRepository.GetNextVersionNumber(version, partitionKeyId: userId)); await _fundingStreamPermissionVersionRepositoryPolicy.ExecuteAsync(() => _fundingStreamPermissionVersionRepository.SaveVersion(version, userId)); await ClearEffectivePermissionsForUser(userId); } return(new OkObjectResult(_mapper.Map <FundingStreamPermissionCurrent>(newPermissions))); }
public async Task <(IEnumerable <PublishedProviderResult>, IEnumerable <PublishedProviderResultExisting>)> GeneratePublishedProviderResultsToSave(IEnumerable <PublishedProviderResult> providerResults, IEnumerable <PublishedProviderResultExisting> existingResults) { Guard.ArgumentNotNull(providerResults, nameof(providerResults)); Guard.ArgumentNotNull(existingResults, nameof(existingResults)); ConcurrentBag <PublishedProviderResult> publishedProviderResultsToSave = new ConcurrentBag <PublishedProviderResult>(); ConcurrentDictionary <string, ConcurrentDictionary <string, PublishedProviderResultExisting> > existingProviderResults = new ConcurrentDictionary <string, ConcurrentDictionary <string, PublishedProviderResultExisting> >(); foreach (PublishedProviderResultExisting providerResult in existingResults) { if (!existingProviderResults.ContainsKey(providerResult.ProviderId)) { existingProviderResults.TryAdd(providerResult.ProviderId, new ConcurrentDictionary <string, PublishedProviderResultExisting>()); } existingProviderResults[providerResult.ProviderId].TryAdd(providerResult.AllocationLineId, providerResult); } List <Task> allTasks = new List <Task>(); SemaphoreSlim throttler = new SemaphoreSlim(initialCount: 30); foreach (PublishedProviderResult providerResult in providerResults) { await throttler.WaitAsync(); allTasks.Add( Task.Run(async() => { try { if (existingProviderResults.ContainsKey(providerResult.ProviderId)) { ConcurrentDictionary <string, PublishedProviderResultExisting> existingResultsForProvider = existingProviderResults[providerResult.ProviderId]; if (existingResultsForProvider.TryGetValue(providerResult.FundingStreamResult.AllocationLineResult.AllocationLine.Id, out PublishedProviderResultExisting existingResult)) { existingResultsForProvider.TryRemove(providerResult.FundingStreamResult.AllocationLineResult.AllocationLine.Id, out var removedExistingResult); if (!existingResultsForProvider.Any()) { existingProviderResults.TryRemove(providerResult.ProviderId, out var removedProviderResult); } if (providerResult.FundingStreamResult.AllocationLineResult.Current.Value == existingResult.Value) { existingProviderResults.TryRemove(providerResult.ProviderId, out var removedProviderResult); return; } providerResult.FundingStreamResult.AllocationLineResult.Current.Version = await _allocationResultsVersionRepository.GetNextVersionNumber(providerResult.FundingStreamResult.AllocationLineResult.Current, existingResult.Version, incrementFromCurrentVersion: true); providerResult.FundingStreamResult.AllocationLineResult.HasResultBeenVaried = existingResult.HasResultBeenVaried; if (existingResult.Status != AllocationLineStatus.Held) { providerResult.FundingStreamResult.AllocationLineResult.Current.Status = AllocationLineStatus.Updated; } if (existingResult.Published != null) { providerResult.FundingStreamResult.AllocationLineResult.Published = existingResult.Published; } providerResult.FundingStreamResult.AllocationLineResult.Current.Major = existingResult.Major; providerResult.FundingStreamResult.AllocationLineResult.Current.Minor = existingResult.Minor; } else { providerResult.FundingStreamResult.AllocationLineResult.Current.Version = 1; } } else { providerResult.FundingStreamResult.AllocationLineResult.Current.Version = 1; } publishedProviderResultsToSave.Add(providerResult); } finally { throttler.Release(); } })); } await TaskHelper.WhenAllAndThrow(allTasks.ToArray()); // Need to remove results that have been varied List <PublishedProviderResult> publishedProviderResultsToSaveList = publishedProviderResultsToSave.ToList(); publishedProviderResultsToSaveList.RemoveAll(r => r.FundingStreamResult.AllocationLineResult.HasResultBeenVaried); List <PublishedProviderResultExisting> existingRecordsExclude = new List <PublishedProviderResultExisting>(existingProviderResults.Values.Count); foreach (ConcurrentDictionary <string, PublishedProviderResultExisting> existingList in existingProviderResults.Values) { existingRecordsExclude.AddRange(existingList.Values.Where(r => !r.HasResultBeenVaried)); } return(publishedProviderResultsToSaveList, existingRecordsExclude); }