Skip to content

Commit

Permalink
CSP-1392: POST Permissions Endpoint (#25)
Browse files Browse the repository at this point in the history
* CSP-1392: POST Permissions endpoint and relevant unit test coverage.
  • Loading branch information
shaun-downey-education committed Jun 21, 2024
1 parent 29b9b8f commit cf23603
Show file tree
Hide file tree
Showing 60 changed files with 1,386 additions and 142 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
using SFA.DAS.PR.Application.Permissions.Queries.GetPermissions;
using SFA.DAS.Testing.AutoFixture;

namespace SFA.DAS.PR.Api.UnitTests.Controllers.Permissions;
namespace SFA.DAS.PR.Api.UnitTests.Controllers.PermissionsControllerTests;
public class PermissionsControllerGetTests
{
[Test, MoqAutoData]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
using SFA.DAS.PR.Domain.Entities;
using SFA.DAS.Testing.AutoFixture;

namespace SFA.DAS.PR.Api.UnitTests.Controllers.Permissions;
namespace SFA.DAS.PR.Api.UnitTests.Controllers.PermissionsControllerTests;
public class PermissionsControllerHasPermissionsTests
{
[Test, MoqAutoData]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using AutoFixture.NUnit3;
using FluentAssertions;
using FluentValidation.Results;
using MediatR;
using Microsoft.AspNetCore.Mvc;
using Moq;
using SFA.DAS.PR.Api.Common;
using SFA.DAS.PR.Api.Controllers;
using SFA.DAS.PR.Application.Mediatr.Responses;
using SFA.DAS.PR.Application.Permissions.Commands.PostPermissions;
using SFA.DAS.Testing.AutoFixture;

namespace SFA.DAS.PR.Api.UnitTests.Controllers.PermissionsControllerTests;

public class PermissionsControllerPostTests
{
[Test]
[MoqAutoData]
public async Task PostPermission_InvokesQueryHandler(
[Frozen] Mock<IMediator> mediatorMock,
[Greedy] PermissionsController sut,
PostPermissionsCommand command,
CancellationToken cancellationToken
)
{
await sut.PostPermission(command, cancellationToken);

mediatorMock.Verify(m =>
m.Send(It.Is<PostPermissionsCommand>(q =>
q.AccountLegalEntityId == command.AccountLegalEntityId &&
q.Ukprn == command.Ukprn &&
q.Operations == command.Operations &&
q.UserRef == command.UserRef
),
cancellationToken)
);
}

[Test, MoqAutoData]
public async Task PostPermission_HandlerReturnsData_ReturnsOkResponse(
[Frozen] Mock<IMediator> mediatorMock,
[Greedy] PermissionsController sut,
PostPermissionsCommand command,
PostPermissionsCommandResult postPermissionsCommandResult,
CancellationToken cancellationToken
)
{
var response = new ValidatedResponse<PostPermissionsCommandResult>(postPermissionsCommandResult);

mediatorMock.Setup(m => m.Send(
It.Is<PostPermissionsCommand>(q =>
q.AccountLegalEntityId == command.AccountLegalEntityId &&
q.Ukprn == command.Ukprn &&
q.Operations == command.Operations &&
q.UserRef == command.UserRef
),
cancellationToken)
).ReturnsAsync(response);

var result = await sut.PostPermission(command, cancellationToken);
result.As<OkObjectResult>().Should().NotBeNull();
result.As<OkObjectResult>().Value.Should().Be(postPermissionsCommandResult);
}

[Test, MoqAutoData]
public async Task PostPermission_HandlerReturnsData_ReturnsBadRequest(
[Frozen] Mock<IMediator> mediatorMock,
[Greedy] PermissionsController sut,
PostPermissionsCommand command,
IList<ValidationFailure> validationErrors,
CancellationToken cancellationToken
)
{
var response = new ValidatedResponse<PostPermissionsCommandResult>(validationErrors);

mediatorMock.Setup(m => m.Send(
It.Is<PostPermissionsCommand>(q =>
q.AccountLegalEntityId == command.AccountLegalEntityId &&
q.Ukprn == command.Ukprn &&
q.Operations == command.Operations &&
q.UserRef == command.UserRef
),
cancellationToken)
).ReturnsAsync(response);

var result = await sut.PostPermission(command, cancellationToken);
result.As<BadRequestObjectResult>().Should().NotBeNull();
result.As<BadRequestObjectResult>().Value.As<List<ValidationError>>().Count.Should().Be(validationErrors.Count);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
using SFA.DAS.PR.Domain.Entities;
using SFA.DAS.Testing.AutoFixture;

namespace SFA.DAS.PR.Api.UnitTests.Controllers.Permissions;
namespace SFA.DAS.PR.Api.UnitTests.Controllers.PermissionsControllerTests;

public class PermissionsControllerTests
{
Expand Down
11 changes: 11 additions & 0 deletions src/SFA.DAS.PR.Api/Controllers/PermissionsController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using SFA.DAS.PR.Api.Common;
using SFA.DAS.PR.Api.SwaggerExamples;
using SFA.DAS.PR.Application.Mediatr.Responses;
using SFA.DAS.PR.Application.Permissions.Commands.PostPermissions;
using SFA.DAS.PR.Application.Permissions.Queries.GetHasPermissions;
using SFA.DAS.PR.Application.Permissions.Queries.GetPermissions;
using SFA.DAS.PR.Application.Permissions.Queries.HasRelationshipWithPermission;
Expand Down Expand Up @@ -53,4 +54,14 @@ public async Task<IActionResult> HasPermission([FromQuery] GetHasPermissionsQuer
ValidatedResponse<bool> result = await _mediator.Send(query, cancellationToken);
return GetResponse(result);
}

[HttpPost]
[Authorize(Policy = Policies.Management)]
[ProducesResponseType(typeof(bool), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(List<ValidationError>), StatusCodes.Status400BadRequest)]
public async Task<IActionResult> PostPermission([FromBody] PostPermissionsCommand command, CancellationToken cancellationToken)
{
ValidatedResponse<PostPermissionsCommandResult> result = await _mediator.Send(command, cancellationToken);
return GetResponse(result);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ CancellationToken cancellationToken
)
{
accountLegalEntityReadRepository.Setup(a =>
a.GetAccountLegalEntiies(accountId, cancellationToken)
a.GetAccountLegalEntities(accountId, cancellationToken)
).ReturnsAsync(legalEntities);

GetAccountProvidersQueryResult expectedResult = new(accountId, AccountProviderModel.BuildAccountProviderModels(legalEntities));
Expand All @@ -44,7 +44,7 @@ CancellationToken cancellationToken
)
{
accountLegalEntityReadRepository.Setup(a =>
a.GetAccountLegalEntiies(accountId, cancellationToken)
a.GetAccountLegalEntities(accountId, cancellationToken)
).ReturnsAsync(() => new List<AccountLegalEntity>());

GetAccountProvidersQueryResult expectedResult = new(accountId, []);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using FluentValidation;
using Moq;
using SFA.DAS.PR.Application.Common.Validators;
using SFA.DAS.PR.Domain.Interfaces;

namespace SFA.DAS.PR.Application.UnitTests.Common.Validators;

public class AccountLegalEntityValidatorTests
{
public class TestAccountLegalEntityIdEntity : IAccountLegalEntityIdEntity
{
public long AccountLegalEntityId { get; set; }
}

[Test]
public async Task ValidateAccountLegalEntityExists_ValidEntity_ReturnsValid()
{
var entity = new TestAccountLegalEntityIdEntity { AccountLegalEntityId = 1 };

var mockRepository = new Mock<IAccountLegalEntityReadRepository>();
mockRepository.Setup(r => r.AccountLegalEntityExists(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(true);

var validator = new InlineValidator<TestAccountLegalEntityIdEntity>();
validator.RuleFor(x => x.AccountLegalEntityId)
.ValidateAccountLegalEntityExists(mockRepository.Object);

var validationResult = await validator.ValidateAsync(entity);

Assert.That(validationResult.IsValid, Is.True);
}

[Test]
public async Task ValidateAccountLegalEntity_Null_AccountLegalEntityId_ReturnsInvalid()
{
var entity = new TestAccountLegalEntityIdEntity { AccountLegalEntityId = 0 };

var mockRepository = new Mock<IAccountLegalEntityReadRepository>();
mockRepository.Setup(r => r.AccountLegalEntityExists(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(true);

var validator = new InlineValidator<TestAccountLegalEntityIdEntity>();
validator.RuleFor(x => x.AccountLegalEntityId)
.ValidateAccountLegalEntityExists(mockRepository.Object);

var validationResult = await validator.ValidateAsync(entity);

Assert.Multiple(() =>
{
Assert.That(validationResult.IsValid, Is.False);
Assert.That(validationResult.Errors[0].ErrorMessage, Is.EqualTo(AccountLegalEntityValidator.AccountLegalEntityIdValidationMessage));
});
}

[Test]
public async Task ValidateAccountLegalEntity_AccountLegalEntityExists_ReturnsInvalid()
{
var entity = new TestAccountLegalEntityIdEntity { AccountLegalEntityId = 1 };

var mockRepository = new Mock<IAccountLegalEntityReadRepository>();
mockRepository.Setup(r => r.AccountLegalEntityExists(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(false);

var validator = new InlineValidator<TestAccountLegalEntityIdEntity>();
validator.RuleFor(x => x.AccountLegalEntityId)
.ValidateAccountLegalEntityExists(mockRepository.Object);

var validationResult = await validator.ValidateAsync(entity);

Assert.Multiple(() =>
{
Assert.That(validationResult.IsValid, Is.False);
Assert.That(validationResult.Errors[0].ErrorMessage, Is.EqualTo(AccountLegalEntityValidator.AccountLegalEntityExistValidationMessage));
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using FluentValidation;
using SFA.DAS.PR.Application.Common.Validators;
using SFA.DAS.PR.Domain.Interfaces;

namespace SFA.DAS.PR.Application.UnitTests.Common.Validators;

public class UkprnFormatValidatorTests
{
public class TestUkprnEntity : IUkprnEntity
{
public long? Ukprn { get; set; }
}

[Test]
public async Task ValidateUkrpn_Ukprn_ReturnsValid()
{
var entity = new TestUkprnEntity { Ukprn = 10000003 };

var validator = new InlineValidator<TestUkprnEntity>();
validator.RuleFor(x => x.Ukprn)
.CheckUkprnFormat();

var validationResult = await validator.ValidateAsync(entity);

Assert.That(validationResult.IsValid, Is.True);
}

[Test]
public async Task ValidateUkrpn_Ukprn_ReturnsInvalid()
{
var entity = new TestUkprnEntity { Ukprn = 1 };

var validator = new InlineValidator<TestUkprnEntity>();
validator.RuleFor(x => x.Ukprn)
.CheckUkprnFormat();

var validationResult = await validator.ValidateAsync(entity);

Assert.Multiple(() =>
{
Assert.That(validationResult.IsValid, Is.False);
Assert.That(validationResult.Errors[0].ErrorMessage, Is.EqualTo(UkprnFormatValidator.UkprnFormatValidationMessage));
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ CancellationToken cancellationToken

ValidatedResponse<GetEmployerRelationshipsQueryResult> result = await sut.Handle(query, cancellationToken);

Assert.That(result.Result.AccountLegalEntities, !Is.Empty);
Assert.That(result.Result!.AccountLegalEntities, !Is.Empty);
}

[Test]
Expand All @@ -46,6 +46,6 @@ CancellationToken cancellationToken

ValidatedResponse<GetEmployerRelationshipsQueryResult> result = await sut.Handle(query, cancellationToken);

Assert.That(result.Result.AccountLegalEntities, Is.Empty);
Assert.That(result.Result!.AccountLegalEntities, Is.Empty);
}
}
Loading

0 comments on commit cf23603

Please sign in to comment.