public async Task WhenUserCanAdministerFundingStream_ShouldSucceed()
        {
            // Arrange
            string          userId    = Guid.NewGuid().ToString();
            ClaimsPrincipal principal = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(Constants.ObjectIdentifierClaimType, userId) }));
            ISpecificationAuthorizationEntity specification = Substitute.For <ISpecificationAuthorizationEntity>();

            specification.GetSpecificationId().Returns(WellKnownSpecificationId);
            AuthorizationHandlerContext authContext = CreateAuthenticationContext(principal, SpecificationActionTypes.CanAdministerFundingStream, specification);

            EffectiveSpecificationPermission actualPermission = new EffectiveSpecificationPermission
            {
                CanAdministerFundingStream = true
            };

            IUsersApiClient usersApiClient = Substitute.For <IUsersApiClient>();

            usersApiClient.GetEffectivePermissionsForUser(Arg.Is(userId), Arg.Is(WellKnownSpecificationId)).Returns(new ApiResponse <EffectiveSpecificationPermission>(HttpStatusCode.OK, actualPermission));

            IOptions <PermissionOptions> options = Substitute.For <IOptions <PermissionOptions> >();

            options.Value.Returns(actualOptions);

            IFeatureToggle features = Substitute.For <IFeatureToggle>();

            features.IsRoleBasedAccessEnabled().Returns(true);

            SpecificationPermissionHandler authHandler = new SpecificationPermissionHandler(usersApiClient, options, features);

            // Act
            await authHandler.HandleAsync(authContext);

            // Assert
            authContext.HasSucceeded.Should().BeTrue();
        }
        public async Task WhenUserCanRefreshPublishedQaForSpecification_ShouldSucceed()
        {
            // Arrange
            string                      userId        = Guid.NewGuid().ToString();
            ClaimsPrincipal             principal     = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim(Constants.ObjectIdentifierClaimType, userId) }));
            string                      specification = WellKnownSpecificationId;
            AuthorizationHandlerContext authContext   = CreateAuthenticationContext(principal, SpecificationActionTypes.CanRefreshPublishedQa, specification);

            EffectiveSpecificationPermission actualPermission = new EffectiveSpecificationPermission
            {
                CanRefreshPublishedQa = true
            };

            IUsersApiClient usersApiClient = Substitute.For <IUsersApiClient>();

            usersApiClient.GetEffectivePermissionsForUser(Arg.Is(userId), Arg.Is(WellKnownSpecificationId)).Returns(new ApiResponse <EffectiveSpecificationPermission>(HttpStatusCode.OK, actualPermission));

            IOptions <PermissionOptions> options = Substitute.For <IOptions <PermissionOptions> >();

            options.Value.Returns(actualOptions);

            SpecificationPermissionHandler authHandler = new SpecificationPermissionHandler(usersApiClient, options);

            // Act
            await authHandler.HandleAsync(authContext);

            // Assert
            authContext.HasSucceeded.Should().BeTrue();
        }
Ejemplo n.º 3
0
        public async Task GetEffectivePermissionsForUser_WhenCachedEffectivePermissionFound_ThenOkResultReturned()
        {
            // Arrange
            ICacheProvider cacheProvider = CreateCacheProvider();
            EffectiveSpecificationPermission cachedPermission = new EffectiveSpecificationPermission()
            {
                UserId                 = UserId,
                SpecificationId        = SpecificationId,
                CanApproveFunding      = true,
                CanCreateSpecification = true,
                CanMapDatasets         = false,
            };

            cacheProvider
            .GetHashValue <EffectiveSpecificationPermission>(Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"), Arg.Is(SpecificationId))
            .Returns(cachedPermission);

            FundingStreamPermissionService service = CreateService(cacheProvider: cacheProvider);


            // Act
            IActionResult result = await service.GetEffectivePermissionsForUser(UserId, SpecificationId, null);

            // Assert
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .BeEquivalentTo(new EffectiveSpecificationPermission()
            {
                UserId                     = UserId,
                SpecificationId            = SpecificationId,
                CanApproveFunding          = true,
                CanCreateSpecification     = true,
                CanMapDatasets             = false,
                CanChooseFunding           = false,
                CanEditCalculations        = false,
                CanEditSpecification       = false,
                CanPublishFunding          = false,
                CanAdministerFundingStream = false,
                CanApproveSpecification    = false,
                CanCreateQaTests           = false,
                CanEditQaTests             = false,
                CanRefreshFunding          = false,
                CanDeleteSpecification     = false
            });

            await cacheProvider
            .Received(1)
            .GetHashValue <EffectiveSpecificationPermission>(Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"), Arg.Is(SpecificationId));

            await cacheProvider
            .Received(0)
            .SetHashValue(
                Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"),
                Arg.Is(SpecificationId),
                Arg.Any <EffectiveSpecificationPermission>());
        }
Ejemplo n.º 4
0
        private bool HasPermission(SpecificationActionTypes requestedPermission, EffectiveSpecificationPermission actualPermissions)
        {
            if (actualPermissions == null)
            {
                return(false);
            }

            switch (requestedPermission)
            {
            case SpecificationActionTypes.CanApproveFunding:
                return(actualPermissions.CanApproveFunding);

            case SpecificationActionTypes.CanChooseFunding:
                return(actualPermissions.CanChooseFunding);

            case SpecificationActionTypes.CanEditCalculations:
                return(actualPermissions.CanEditCalculations);

            case SpecificationActionTypes.CanEditSpecification:
                return(actualPermissions.CanEditSpecification);

            case SpecificationActionTypes.CanMapDatasets:
                return(actualPermissions.CanMapDatasets);

            case SpecificationActionTypes.CanReleaseFunding:
                return(actualPermissions.CanReleaseFunding);

            case SpecificationActionTypes.CanRefreshFunding:
                return(actualPermissions.CanRefreshFunding);

            case SpecificationActionTypes.CanCreateQaTests:
                return(actualPermissions.CanCreateQaTests);

            case SpecificationActionTypes.CanEditQaTests:
                return(actualPermissions.CanEditQaTests);

            case SpecificationActionTypes.CanApproveSpecification:
                return(actualPermissions.CanApproveSpecification);

            case SpecificationActionTypes.CanAdministerFundingStream:
                return(actualPermissions.CanAdministerFundingStream);

            case SpecificationActionTypes.CanDeleteSpecification:
                return(actualPermissions.CanDeleteSpecification);

            case SpecificationActionTypes.CanDeleteCalculations:
                return(actualPermissions.CanDeleteCalculations);

            case SpecificationActionTypes.CanDeleteQaTests:
                return(actualPermissions.CanDeleteQaTests);

            default:
                return(false);
            }
        }
Ejemplo n.º 5
0
        public async Task GetEffectivePermissionsForUser_WhenNotFoundInCacheButSpecificationNotFound_ThenPreconditionFailedResultReturned()
        {
            // Arrange
            ICacheProvider cacheProvider = CreateCacheProvider();
            EffectiveSpecificationPermission cachedPermission = null;

            cacheProvider
            .GetHashValue <EffectiveSpecificationPermission>(Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"), Arg.Is(SpecificationId))
            .Returns(cachedPermission);

            ISpecificationRepository specificationRepository = CreateSpecificationRepository();

            SpecificationSummary specificationSummary = null;

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(SpecificationId))
            .Returns(specificationSummary);

            FundingStreamPermissionService service = CreateService(
                specificationRepository: specificationRepository,
                cacheProvider: cacheProvider);


            // Act
            IActionResult result = await service.GetEffectivePermissionsForUser(UserId, SpecificationId, null);

            // Assert
            result
            .Should()
            .BeOfType <PreconditionFailedResult>()
            .Which
            .Value
            .Should()
            .Be("Specification not found");

            await cacheProvider
            .Received(1)
            .GetHashValue <EffectiveSpecificationPermission>(Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"), Arg.Is(SpecificationId));

            await cacheProvider
            .Received(0)
            .SetHashValue(
                Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"),
                Arg.Is(SpecificationId),
                Arg.Any <EffectiveSpecificationPermission>());
        }
        public async Task <IActionResult> GetEffectivePermissionsForUser(string userId, string specificationId)
        {
            if (string.IsNullOrWhiteSpace(userId))
            {
                return(new BadRequestObjectResult($"{nameof(userId)} is empty or null"));
            }

            if (string.IsNullOrWhiteSpace(specificationId))
            {
                return(new BadRequestObjectResult($"{nameof(specificationId)} is empty or null"));
            }

            EffectiveSpecificationPermission cachedPermissions = await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.GetHashValue <EffectiveSpecificationPermission>($"{CacheKeys.EffectivePermissions}:{userId}", specificationId));

            if (cachedPermissions != null)
            {
                return(new OkObjectResult(cachedPermissions));
            }
            else
            {
                ApiResponse <SpecModel.SpecificationSummary> specificationApiResponse =
                    await _specificationsApiClientPolicy.ExecuteAsync(() => _specificationsApiClient.GetSpecificationSummaryById(specificationId));

                if (!specificationApiResponse.StatusCode.IsSuccess() || specificationApiResponse.Content == null)
                {
                    return(new PreconditionFailedResult("Specification not found"));
                }

                SpecModel.SpecificationSummary specification = specificationApiResponse.Content;

                List <FundingStreamPermission> permissionsForUser = new List <FundingStreamPermission>();
                foreach (Reference fundingStream in specification.FundingStreams)
                {
                    FundingStreamPermission permission = await _userRepositoryPolicy.ExecuteAsync(() => _userRepository.GetFundingStreamPermission(userId, fundingStream.Id));

                    if (permission != null)
                    {
                        permissionsForUser.Add(permission);
                    }
                    else
                    {
                        // Add permission for this funding stream with no permissions - used further down to calculate permissions (required for pessimistic permissions)
                        permissionsForUser.Add(new FundingStreamPermission
                        {
                            UserId                       = userId,
                            FundingStreamId              = fundingStream.Id,
                            CanApproveFunding            = false,
                            CanChooseFunding             = false,
                            CanCreateSpecification       = false,
                            CanEditCalculations          = false,
                            CanEditSpecification         = false,
                            CanMapDatasets               = false,
                            CanReleaseFunding            = false,
                            CanAdministerFundingStream   = false,
                            CanApproveSpecification      = false,
                            CanCreateQaTests             = false,
                            CanDeleteCalculations        = false,
                            CanDeleteSpecification       = false,
                            CanDeleteQaTests             = false,
                            CanEditQaTests               = false,
                            CanRefreshFunding            = false,
                            CanCreateTemplates           = false,
                            CanEditTemplates             = false,
                            CanDeleteTemplates           = false,
                            CanApproveTemplates          = false,
                            CanCreateProfilePattern      = false,
                            CanEditProfilePattern        = false,
                            CanDeleteProfilePattern      = false,
                            CanAssignProfilePattern      = false,
                            CanApplyCustomProfilePattern = false,
                            CanApproveCalculations       = false,
                            CanApproveAnyCalculations    = false,
                            CanApproveAllCalculations    = false
                        });
                    }
                }

                EffectiveSpecificationPermission specificationPermissions = GeneratePermissions(permissionsForUser, specificationId, userId);

                string userPermissionHashKey = $"{CacheKeys.EffectivePermissions}:{userId}";

                // Does the hash set for this user already exist - used to determine the timeout for the hash set below
                bool existingHashSetExists = await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.HashSetExists(userPermissionHashKey));

                // Cache effective permissions for the specification / user
                await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.SetHashValue(userPermissionHashKey, specificationId, specificationPermissions));

                // If the hash set does not exist, then set an expiry for the whole hash set. This stops the users permissions being stored indefinitely
                if (!existingHashSetExists)
                {
                    await _cacheProviderPolicy.ExecuteAsync(() => _cacheProvider.SetHashExpiry(userPermissionHashKey, DateTime.UtcNow.AddHours(12)));
                }

                return(new OkObjectResult(specificationPermissions));
            }
        }
Ejemplo n.º 7
0
        public async Task GetEffectivePermissionsForUser_WhenNotFoundInCacheResultsAreQueriedWithMultipleFundingStreamAndNoPermissionsAreInRepository_ThenOkResultReturnedWithNoPermissions()
        {
            // Arrange
            IUserRepository          userRepository          = CreateUserRepository();
            ISpecificationRepository specificationRepository = CreateSpecificationRepository();
            ICacheProvider           cacheProvider           = CreateCacheProvider();
            IMapper mapper = CreateMappingConfiguration();

            EffectiveSpecificationPermission cachedPermission = null;

            cacheProvider
            .GetHashValue <EffectiveSpecificationPermission>(Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"), Arg.Is(SpecificationId))
            .Returns(cachedPermission);

            SpecificationSummary specificationSummary = new SpecificationSummary()
            {
                Id             = SpecificationId,
                FundingStreams = new List <Reference>()
                {
                    new Reference("fs1", "Funding Stream 1"),
                    new Reference("fs2", "Funding Stream 2")
                }
            };

            specificationRepository
            .GetSpecificationSummaryById(Arg.Is(SpecificationId))
            .Returns(specificationSummary);

            FundingStreamPermission fs1Permission = null;

            userRepository
            .GetFundingStreamPermission(Arg.Is(UserId), Arg.Is("fs1"))
            .Returns(fs1Permission);

            FundingStreamPermission fs2Permission = null;

            userRepository
            .GetFundingStreamPermission(Arg.Is(UserId), Arg.Is("fs2"))
            .Returns(fs2Permission);

            FundingStreamPermissionService service = CreateService(userRepository, specificationRepository, cacheProvider: cacheProvider, mapper: mapper);


            // Act
            IActionResult result = await service.GetEffectivePermissionsForUser(UserId, SpecificationId, null);

            // Assert
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .BeEquivalentTo(new EffectiveSpecificationPermission()
            {
                UserId                     = UserId,
                SpecificationId            = SpecificationId,
                CanApproveFunding          = false,
                CanCreateSpecification     = false,
                CanMapDatasets             = false,
                CanChooseFunding           = false,
                CanEditCalculations        = false,
                CanEditSpecification       = false,
                CanPublishFunding          = false,
                CanAdministerFundingStream = false,
                CanApproveSpecification    = false,
                CanCreateQaTests           = false,
                CanEditQaTests             = false,
                CanRefreshFunding          = false,
            });

            await cacheProvider
            .Received(1)
            .SetHashValue(
                Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"),
                Arg.Is(SpecificationId),
                Arg.Is <EffectiveSpecificationPermission>(p =>
                                                          !p.CanApproveFunding &&
                                                          !p.CanChooseFunding &&
                                                          !p.CanCreateSpecification &&
                                                          !p.CanEditCalculations &&
                                                          !p.CanEditSpecification &&
                                                          !p.CanMapDatasets &&
                                                          !p.CanPublishFunding &&
                                                          !p.CanAdministerFundingStream &&
                                                          !p.CanApproveSpecification &&
                                                          !p.CanCreateQaTests &&
                                                          !p.CanEditQaTests &&
                                                          !p.CanRefreshFunding &&
                                                          p.SpecificationId == SpecificationId &&
                                                          p.UserId == UserId
                                                          ));
        }
Ejemplo n.º 8
0
        public async Task GetEffectivePermissionsForUser_WhenNotFoundInCacheResultsAreQueriedWithMultipleFundingStreamAndUserHasPermissionsButNotAcrossAllFundingStreams_ThenOkResultReturnedWithPermissionsThatOnlyAllFundingStreamsHave()
        {
            // Arrange
            IUserRepository          userRepository          = CreateUserRepository();
            ISpecificationsApiClient specificationsApiClient = CreateSpecificationsApiClient();
            ICacheProvider           cacheProvider           = CreateCacheProvider();
            IMapper mapper = CreateMappingConfiguration();

            EffectiveSpecificationPermission cachedPermission = null;

            cacheProvider
            .GetHashValue <EffectiveSpecificationPermission>(Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"), Arg.Is(SpecificationId))
            .Returns(cachedPermission);

            SpecModel.SpecificationSummary specificationSummary = new SpecModel.SpecificationSummary()
            {
                Id             = SpecificationId,
                FundingStreams = new List <Reference>()
                {
                    new Reference("fs1", "Funding Stream 1"),
                    new Reference("fs2", "Funding Stream 2"),
                }
            };

            specificationsApiClient
            .GetSpecificationSummaryById(Arg.Is(SpecificationId))
            .Returns(new ApiResponse <SpecModel.SpecificationSummary>(HttpStatusCode.OK, specificationSummary));

            FundingStreamPermission fs1Permission = new FundingStreamPermission()
            {
                UserId                       = UserId,
                FundingStreamId              = "fs1",
                CanChooseFunding             = false,
                CanCreateSpecification       = true,
                CanApproveFunding            = false,
                CanEditCalculations          = false,
                CanEditSpecification         = false,
                CanMapDatasets               = false,
                CanReleaseFunding            = false,
                CanAdministerFundingStream   = false,
                CanApproveSpecification      = false,
                CanCreateQaTests             = false,
                CanEditQaTests               = false,
                CanRefreshFunding            = false,
                CanCreateProfilePattern      = false,
                CanEditProfilePattern        = false,
                CanDeleteProfilePattern      = false,
                CanAssignProfilePattern      = false,
                CanApplyCustomProfilePattern = false,
                CanApproveCalculations       = true,
                CanApproveAnyCalculations    = false,
                CanApproveAllCalculations    = false
            };

            FundingStreamPermission fs2Permission = new FundingStreamPermission()
            {
                UserId                       = UserId,
                FundingStreamId              = "fs1",
                CanChooseFunding             = false,
                CanCreateSpecification       = true,
                CanApproveFunding            = true,
                CanEditCalculations          = false,
                CanEditSpecification         = false,
                CanMapDatasets               = false,
                CanReleaseFunding            = false,
                CanAdministerFundingStream   = false,
                CanApproveSpecification      = false,
                CanCreateQaTests             = false,
                CanEditQaTests               = false,
                CanRefreshFunding            = false,
                CanCreateProfilePattern      = false,
                CanEditProfilePattern        = false,
                CanDeleteProfilePattern      = false,
                CanAssignProfilePattern      = false,
                CanApplyCustomProfilePattern = false,
                CanApproveCalculations       = true,
                CanApproveAnyCalculations    = false,
                CanApproveTemplates          = false,
                CanCreateTemplates           = false,
                CanDeleteCalculations        = false,
                CanDeleteQaTests             = false,
                CanDeleteSpecification       = false,
                CanDeleteTemplates           = false,
                CanEditTemplates             = false,
                CanApproveAllCalculations    = false
            };

            userRepository
            .GetFundingStreamPermission(Arg.Is(UserId), Arg.Is("fs1"))
            .Returns(fs1Permission);

            userRepository
            .GetFundingStreamPermission(Arg.Is(UserId), Arg.Is("fs2"))
            .Returns(fs2Permission);

            FundingStreamPermissionService service = CreateService(userRepository, specificationsApiClient, cacheProvider: cacheProvider, mapper: mapper);


            // Act
            IActionResult result = await service.GetEffectivePermissionsForUser(UserId, SpecificationId);

            // Assert
            result
            .Should()
            .BeOfType <OkObjectResult>()
            .Which
            .Value
            .Should()
            .BeEquivalentTo(new EffectiveSpecificationPermission()
            {
                UserId                       = UserId,
                SpecificationId              = SpecificationId,
                CanApproveFunding            = false,
                CanCreateSpecification       = true,
                CanMapDatasets               = false,
                CanChooseFunding             = false,
                CanEditCalculations          = false,
                CanEditSpecification         = false,
                CanReleaseFunding            = false,
                CanAdministerFundingStream   = false,
                CanApproveSpecification      = false,
                CanCreateQaTests             = false,
                CanEditQaTests               = false,
                CanRefreshFunding            = false,
                CanApproveAnyCalculations    = false,
                CanAssignProfilePattern      = false,
                CanDeleteSpecification       = false,
                CanDeleteQaTests             = false,
                CanDeleteCalculations        = false,
                CanApplyCustomProfilePattern = false,
                CanApproveCalculations       = true,
                CanApproveAllCalculations    = false
            });

            await cacheProvider
            .Received(1)
            .SetHashValue(
                Arg.Is($"{CacheKeys.EffectivePermissions}:{UserId}"),
                Arg.Is(SpecificationId),
                Arg.Is <EffectiveSpecificationPermission>(p =>
                                                          !p.CanApproveFunding &&
                                                          !p.CanChooseFunding &&
                                                          p.CanCreateSpecification &&
                                                          !p.CanEditCalculations &&
                                                          !p.CanEditSpecification &&
                                                          !p.CanMapDatasets &&
                                                          !p.CanReleaseFunding &&
                                                          !p.CanAdministerFundingStream &&
                                                          !p.CanApproveSpecification &&
                                                          !p.CanCreateQaTests &&
                                                          !p.CanEditQaTests &&
                                                          !p.CanRefreshFunding &&
                                                          p.SpecificationId == SpecificationId &&
                                                          p.UserId == UserId
                                                          ));
        }