diff --git a/src/Api/Dirt/Controllers/ReportsController.cs b/src/Api/Dirt/Controllers/ReportsController.cs index 4f2697dcc5..8bb8b5e487 100644 --- a/src/Api/Dirt/Controllers/ReportsController.cs +++ b/src/Api/Dirt/Controllers/ReportsController.cs @@ -23,6 +23,9 @@ public class ReportsController : Controller private readonly IAddPasswordHealthReportApplicationCommand _addPwdHealthReportAppCommand; private readonly IGetPasswordHealthReportApplicationQuery _getPwdHealthReportAppQuery; private readonly IDropPasswordHealthReportApplicationCommand _dropPwdHealthReportAppCommand; + private readonly IAddOrganizationReportCommand _addOrganizationReportCommand; + private readonly IDropOrganizationReportCommand _dropOrganizationReportCommand; + private readonly IGetOrganizationReportQuery _getOrganizationReportQuery; public ReportsController( ICurrentContext currentContext, @@ -30,7 +33,10 @@ public class ReportsController : Controller IRiskInsightsReportQuery riskInsightsReportQuery, IAddPasswordHealthReportApplicationCommand addPasswordHealthReportApplicationCommand, IGetPasswordHealthReportApplicationQuery getPasswordHealthReportApplicationQuery, - IDropPasswordHealthReportApplicationCommand dropPwdHealthReportAppCommand + IDropPasswordHealthReportApplicationCommand dropPwdHealthReportAppCommand, + IGetOrganizationReportQuery getOrganizationReportQuery, + IAddOrganizationReportCommand addOrganizationReportCommand, + IDropOrganizationReportCommand dropOrganizationReportCommand ) { _currentContext = currentContext; @@ -39,6 +45,9 @@ public class ReportsController : Controller _addPwdHealthReportAppCommand = addPasswordHealthReportApplicationCommand; _getPwdHealthReportAppQuery = getPasswordHealthReportApplicationQuery; _dropPwdHealthReportAppCommand = dropPwdHealthReportAppCommand; + _getOrganizationReportQuery = getOrganizationReportQuery; + _addOrganizationReportCommand = addOrganizationReportCommand; + _dropOrganizationReportCommand = dropOrganizationReportCommand; } /// @@ -204,4 +213,72 @@ public class ReportsController : Controller await _dropPwdHealthReportAppCommand.DropPasswordHealthReportApplicationAsync(request); } + + /// + /// Adds a new organization report + /// + /// A single instance of AddOrganizationReportRequest + /// A single instance of OrganizationReport + /// If user does not have access to the organization + /// If the organization Id is not valid + [HttpPost("organization-reports")] + public async Task AddOrganizationReport([FromBody] AddOrganizationReportRequest request) + { + if (!await _currentContext.AccessReports(request.OrganizationId)) + { + throw new NotFoundException(); + } + return await _addOrganizationReportCommand.AddOrganizationReportAsync(request); + } + + /// + /// Drops organization reports for an organization + /// + /// A single instance of DropOrganizationReportRequest + /// + /// If user does not have access to the organization + /// If the organization does not have any records + [HttpDelete("organization-reports")] + public async Task DropOrganizationReport([FromBody] DropOrganizationReportRequest request) + { + if (!await _currentContext.AccessReports(request.OrganizationId)) + { + throw new NotFoundException(); + } + await _dropOrganizationReportCommand.DropOrganizationReportAsync(request); + } + + /// + /// Gets organization reports for an organization + /// + /// A valid Organization Id + /// An Enumerable of OrganizationReport + /// If user does not have access to the organization + /// If the organization Id is not valid + [HttpGet("organization-reports/{orgId}")] + public async Task> GetOrganizationReports(Guid orgId) + { + if (!await _currentContext.AccessReports(orgId)) + { + throw new NotFoundException(); + } + return await _getOrganizationReportQuery.GetOrganizationReportAsync(orgId); + } + + /// + /// Gets the latest organization report for an organization + /// + /// A valid Organization Id + /// A single instance of OrganizationReport + /// If user does not have access to the organization + /// If the organization Id is not valid + [HttpGet("organization-reports/latest/{orgId}")] + public async Task GetLatestOrganizationReport(Guid orgId) + { + if (!await _currentContext.AccessReports(orgId)) + { + throw new NotFoundException(); + } + return await _getOrganizationReportQuery.GetLatestOrganizationReportAsync(orgId); + } } diff --git a/src/Core/Dirt/Reports/ReportFeatures/DropOrganizationReportCommand.cs b/src/Core/Dirt/Reports/ReportFeatures/DropOrganizationReportCommand.cs index e382788273..8fe206c1f1 100644 --- a/src/Core/Dirt/Reports/ReportFeatures/DropOrganizationReportCommand.cs +++ b/src/Core/Dirt/Reports/ReportFeatures/DropOrganizationReportCommand.cs @@ -31,12 +31,15 @@ public class DropOrganizationReportCommand : IDropOrganizationReportCommand throw new BadRequestException("No data found."); } - data.Where(_ => request.OrganizationReportIds.Contains(_.Id)).ToList().ForEach(async _ => - { - _logger.LogInformation("Dropping organization report {organizationReportId} for organization {organizationId}", - _.Id, request.OrganizationId); + data + .Where(_ => request.OrganizationReportIds.Contains(_.Id)) + .ToList() + .ForEach(async reportId => + { + _logger.LogInformation("Dropping organization report {organizationReportId} for organization {organizationId}", + reportId, request.OrganizationId); - await _organizationReportRepo.DeleteAsync(_); - }); + await _organizationReportRepo.DeleteAsync(reportId); + }); } } diff --git a/test/Api.Test/Dirt/ReportsControllerTests.cs b/test/Api.Test/Dirt/ReportsControllerTests.cs index 37a6cb79c3..af285d8b85 100644 --- a/test/Api.Test/Dirt/ReportsControllerTests.cs +++ b/test/Api.Test/Dirt/ReportsControllerTests.cs @@ -142,4 +142,142 @@ public class ReportsControllerTests _.OrganizationId == request.OrganizationId && _.PasswordHealthReportApplicationIds == request.PasswordHealthReportApplicationIds)); } + + [Theory, BitAutoData] + public async Task AddOrganizationReportAsync_withAccess_success(SutProvider sutProvider) + { + // Arrange + sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(true); + + // Act + var request = new AddOrganizationReportRequest + { + OrganizationId = Guid.NewGuid(), + ReportData = "Report Data", + Date = DateTime.UtcNow + }; + await sutProvider.Sut.AddOrganizationReport(request); + + // Assert + _ = sutProvider.GetDependency() + .Received(1) + .AddOrganizationReportAsync(Arg.Is(_ => + _.OrganizationId == request.OrganizationId && + _.ReportData == request.ReportData && + _.Date == request.Date)); + } + + [Theory, BitAutoData] + public async Task AddOrganizationReportAsync_withoutAccess(SutProvider sutProvider) + { + // Arrange + sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(false); + // Act + var request = new AddOrganizationReportRequest + { + OrganizationId = Guid.NewGuid(), + ReportData = "Report Data", + Date = DateTime.UtcNow + }; + await Assert.ThrowsAsync(async () => + await sutProvider.Sut.AddOrganizationReport(request)); + // Assert + _ = sutProvider.GetDependency() + .Received(0); + } + + [Theory, BitAutoData] + public async Task DropOrganizationReportAsync_withAccess_success(SutProvider sutProvider) + { + // Arrange + sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(true); + // Act + var request = new DropOrganizationReportRequest + { + OrganizationId = Guid.NewGuid(), + OrganizationReportIds = new List { Guid.NewGuid(), Guid.NewGuid() } + }; + await sutProvider.Sut.DropOrganizationReport(request); + // Assert + _ = sutProvider.GetDependency() + .Received(1) + .DropOrganizationReportAsync(Arg.Is(_ => + _.OrganizationId == request.OrganizationId && + _.OrganizationReportIds.SequenceEqual(request.OrganizationReportIds))); + } + [Theory, BitAutoData] + public async Task DropOrganizationReportAsync_withoutAccess(SutProvider sutProvider) + { + // Arrange + sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(false); + // Act + var request = new DropOrganizationReportRequest + { + OrganizationId = Guid.NewGuid(), + OrganizationReportIds = new List { Guid.NewGuid(), Guid.NewGuid() } + }; + await Assert.ThrowsAsync(async () => + await sutProvider.Sut.DropOrganizationReport(request)); + // Assert + _ = sutProvider.GetDependency() + .Received(0); + } + [Theory, BitAutoData] + public async Task GetOrganizationReportAsync_withAccess_success(SutProvider sutProvider) + { + // Arrange + sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(true); + // Act + var orgId = Guid.NewGuid(); + var result = await sutProvider.Sut.GetOrganizationReports(orgId); + // Assert + _ = sutProvider.GetDependency() + .Received(1) + .GetOrganizationReportAsync(Arg.Is(_ => _ == orgId)); + } + + [Theory, BitAutoData] + public async Task GetOrganizationReportAsync_withoutAccess(SutProvider sutProvider) + { + // Arrange + sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(false); + // Act + var orgId = Guid.NewGuid(); + await Assert.ThrowsAsync(async () => await sutProvider.Sut.GetOrganizationReports(orgId)); + // Assert + _ = sutProvider.GetDependency() + .Received(0); + + } + + [Theory, BitAutoData] + public async Task GetLastestOrganizationReportAsync_withAccess_success(SutProvider sutProvider) + { + // Arrange + sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(true); + + // Act + var orgId = Guid.NewGuid(); + var result = await sutProvider.Sut.GetLatestOrganizationReport(orgId); + + // Assert + _ = sutProvider.GetDependency() + .Received(1) + .GetLatestOrganizationReportAsync(Arg.Is(_ => _ == orgId)); + } + + [Theory, BitAutoData] + public async Task GetLastestOrganizationReportAsync_withoutAccess(SutProvider sutProvider) + { + // Arrange + sutProvider.GetDependency().AccessReports(Arg.Any()).Returns(false); + + // Act + var orgId = Guid.NewGuid(); + await Assert.ThrowsAsync(async () => await sutProvider.Sut.GetLatestOrganizationReport(orgId)); + + // Assert + _ = sutProvider.GetDependency() + .Received(0); + } }