mirror of
https://github.com/bitwarden/server.git
synced 2025-07-18 16:11:28 -05:00
[PM-20576] OrganizationReport - Queries and Command (#5983)
This commit is contained in:
@ -0,0 +1,74 @@
|
||||
using Bit.Core.Dirt.Entities;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
|
||||
using Bit.Core.Dirt.Repositories;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Repositories;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Bit.Core.Dirt.Reports.ReportFeatures;
|
||||
|
||||
public class AddOrganizationReportCommand : IAddOrganizationReportCommand
|
||||
{
|
||||
private readonly IOrganizationRepository _organizationRepo;
|
||||
private readonly IOrganizationReportRepository _organizationReportRepo;
|
||||
private ILogger<AddOrganizationReportCommand> _logger;
|
||||
|
||||
public AddOrganizationReportCommand(
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationReportRepository organizationReportRepository,
|
||||
ILogger<AddOrganizationReportCommand> logger)
|
||||
{
|
||||
_organizationRepo = organizationRepository;
|
||||
_organizationReportRepo = organizationReportRepository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<OrganizationReport> AddOrganizationReportAsync(AddOrganizationReportRequest request)
|
||||
{
|
||||
_logger.LogInformation("Adding organization report for organization {organizationId}", request.OrganizationId);
|
||||
|
||||
var (isValid, errorMessage) = await ValidateRequestAsync(request);
|
||||
if (!isValid)
|
||||
{
|
||||
_logger.LogInformation("Failed to add organization {organizationId} report: {errorMessage}", request.OrganizationId, errorMessage);
|
||||
throw new BadRequestException(errorMessage);
|
||||
}
|
||||
|
||||
var organizationReport = new OrganizationReport
|
||||
{
|
||||
OrganizationId = request.OrganizationId,
|
||||
ReportData = request.ReportData,
|
||||
Date = request.Date == default ? DateTime.UtcNow : request.Date,
|
||||
CreationDate = DateTime.UtcNow,
|
||||
};
|
||||
|
||||
organizationReport.SetNewId();
|
||||
|
||||
var data = await _organizationReportRepo.CreateAsync(organizationReport);
|
||||
|
||||
_logger.LogInformation("Successfully added organization report for organization {organizationId}, {organizationReportId}",
|
||||
request.OrganizationId, data.Id);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private async Task<(bool IsValid, string errorMessage)> ValidateRequestAsync(
|
||||
AddOrganizationReportRequest request)
|
||||
{
|
||||
// verify that the organization exists
|
||||
var organization = await _organizationRepo.GetByIdAsync(request.OrganizationId);
|
||||
if (organization == null)
|
||||
{
|
||||
return (false, "Invalid Organization");
|
||||
}
|
||||
|
||||
// ensure that we have report data
|
||||
if (string.IsNullOrWhiteSpace(request.ReportData))
|
||||
{
|
||||
return (false, "Report Data is required");
|
||||
}
|
||||
|
||||
return (true, string.Empty);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
|
||||
using Bit.Core.Dirt.Repositories;
|
||||
using Bit.Core.Exceptions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Bit.Core.Dirt.Reports.ReportFeatures;
|
||||
|
||||
public class DropOrganizationReportCommand : IDropOrganizationReportCommand
|
||||
{
|
||||
private IOrganizationReportRepository _organizationReportRepo;
|
||||
private ILogger<DropOrganizationReportCommand> _logger;
|
||||
|
||||
public DropOrganizationReportCommand(
|
||||
IOrganizationReportRepository organizationReportRepository,
|
||||
ILogger<DropOrganizationReportCommand> logger)
|
||||
{
|
||||
_organizationReportRepo = organizationReportRepository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task DropOrganizationReportAsync(DropOrganizationReportRequest request)
|
||||
{
|
||||
_logger.LogInformation("Dropping organization report for organization {organizationId}",
|
||||
request.OrganizationId);
|
||||
|
||||
var data = await _organizationReportRepo.GetByOrganizationIdAsync(request.OrganizationId);
|
||||
if (data == null || data.Count() == 0)
|
||||
{
|
||||
_logger.LogInformation("No organization reports found for organization {organizationId}", request.OrganizationId);
|
||||
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);
|
||||
|
||||
await _organizationReportRepo.DeleteAsync(_);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
using Bit.Core.Dirt.Entities;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
|
||||
using Bit.Core.Dirt.Repositories;
|
||||
using Bit.Core.Exceptions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Bit.Core.Dirt.Reports.ReportFeatures;
|
||||
|
||||
public class GetOrganizationReportQuery : IGetOrganizationReportQuery
|
||||
{
|
||||
private IOrganizationReportRepository _organizationReportRepo;
|
||||
private ILogger<GetOrganizationReportQuery> _logger;
|
||||
|
||||
public GetOrganizationReportQuery(
|
||||
IOrganizationReportRepository organizationReportRepo,
|
||||
ILogger<GetOrganizationReportQuery> logger)
|
||||
{
|
||||
_organizationReportRepo = organizationReportRepo;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<OrganizationReport>> GetOrganizationReportAsync(Guid organizationId)
|
||||
{
|
||||
if (organizationId == Guid.Empty)
|
||||
{
|
||||
throw new BadRequestException("OrganizationId is required.");
|
||||
}
|
||||
|
||||
_logger.LogInformation("Fetching organization reports for organization {organizationId}", organizationId);
|
||||
return await _organizationReportRepo.GetByOrganizationIdAsync(organizationId);
|
||||
}
|
||||
|
||||
public async Task<OrganizationReport> GetLatestOrganizationReportAsync(Guid organizationId)
|
||||
{
|
||||
if (organizationId == Guid.Empty)
|
||||
{
|
||||
throw new BadRequestException("OrganizationId is required.");
|
||||
}
|
||||
|
||||
_logger.LogInformation("Fetching latest organization report for organization {organizationId}", organizationId);
|
||||
return await _organizationReportRepo.GetLatestByOrganizationIdAsync(organizationId);
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
|
||||
using Bit.Core.Dirt.Entities;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
|
||||
|
||||
namespace Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
|
||||
|
||||
public interface IAddOrganizationReportCommand
|
||||
{
|
||||
Task<OrganizationReport> AddOrganizationReportAsync(AddOrganizationReportRequest request);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
|
||||
|
||||
namespace Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
|
||||
|
||||
public interface IDropOrganizationReportCommand
|
||||
{
|
||||
Task DropOrganizationReportAsync(DropOrganizationReportRequest request);
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
using Bit.Core.Dirt.Entities;
|
||||
|
||||
namespace Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
|
||||
|
||||
public interface IGetOrganizationReportQuery
|
||||
{
|
||||
Task<IEnumerable<OrganizationReport>> GetOrganizationReportAsync(Guid organizationId);
|
||||
Task<OrganizationReport> GetLatestOrganizationReportAsync(Guid organizationId);
|
||||
}
|
@ -13,5 +13,8 @@ public static class ReportingServiceCollectionExtensions
|
||||
services.AddScoped<IAddPasswordHealthReportApplicationCommand, AddPasswordHealthReportApplicationCommand>();
|
||||
services.AddScoped<IGetPasswordHealthReportApplicationQuery, GetPasswordHealthReportApplicationQuery>();
|
||||
services.AddScoped<IDropPasswordHealthReportApplicationCommand, DropPasswordHealthReportApplicationCommand>();
|
||||
services.AddScoped<IAddOrganizationReportCommand, AddOrganizationReportCommand>();
|
||||
services.AddScoped<IDropOrganizationReportCommand, DropOrganizationReportCommand>();
|
||||
services.AddScoped<IGetOrganizationReportQuery, GetOrganizationReportQuery>();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,8 @@
|
||||
namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests;
|
||||
|
||||
public class AddOrganizationReportRequest
|
||||
{
|
||||
public Guid OrganizationId { get; set; }
|
||||
public string ReportData { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests;
|
||||
|
||||
public class DropOrganizationReportRequest
|
||||
{
|
||||
public Guid OrganizationId { get; set; }
|
||||
public IEnumerable<Guid> OrganizationReportIds { get; set; }
|
||||
}
|
@ -6,5 +6,7 @@ namespace Bit.Core.Dirt.Repositories;
|
||||
public interface IOrganizationReportRepository : IRepository<OrganizationReport, Guid>
|
||||
{
|
||||
Task<ICollection<OrganizationReport>> GetByOrganizationIdAsync(Guid organizationId);
|
||||
|
||||
Task<OrganizationReport> GetLatestByOrganizationIdAsync(Guid organizationId);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user