mirror of
https://github.com/bitwarden/server
synced 2026-01-06 02:23:51 +00:00
Organization report tables, repos, services, and endpoints (#6158)
* PM-23754 initial commit * pm-23754 fixing controller tests * pm-23754 adding commands and queries * pm-23754 adding endpoints, command/queries, repositories, and sql migrations * pm-23754 add new sql scripts * PM-23754 adding sql scripts * pm-23754 * PM-23754 fixing migration script * PM-23754 fixing migration script again * PM-23754 fixing migration script validation * PM-23754 fixing db validation script issue * PM-23754 fixing endpoint and db validation * PM-23754 fixing unit tests * PM-23754 fixing implementation based on comments and tests * PM-23754 updating logging statements * PM-23754 making changes based on PR comments. * updating migration scripts * removing old migration files * update code based testing for whole data object for OrganizationReport and add a stored procedure. * updating services, unit tests, repository tests * fixing unit tests * fixing migration script * fixing migration script again * fixing migration script * another fix * fixing sql file, updating controller to account for different orgIds in the url and body. * updating error message in controllers without a body * making a change to the command * Refactor ReportsController by removing organization reports The IDropOrganizationReportCommand is no longer needed * will code based on PR comments. * fixing unit test * fixing migration script based on last changes. * adding another check in endpoint and adding unit tests * fixing route parameter. * PM-23754 updating data fields to return just the column * PM-23754 fixing repository method signatures * PM-23754 making change to orgId parameter through out code to align with api naming --------- Co-authored-by: Tom <144813356+ttalty@users.noreply.github.com>
This commit is contained in:
297
src/Api/Dirt/Controllers/OrganizationReportsController.cs
Normal file
297
src/Api/Dirt/Controllers/OrganizationReportsController.cs
Normal file
@@ -0,0 +1,297 @@
|
||||
using Bit.Core.Context;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
|
||||
using Bit.Core.Exceptions;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Bit.Api.Dirt.Controllers;
|
||||
|
||||
[Route("reports/organizations")]
|
||||
[Authorize("Application")]
|
||||
public class OrganizationReportsController : Controller
|
||||
{
|
||||
private readonly ICurrentContext _currentContext;
|
||||
private readonly IGetOrganizationReportQuery _getOrganizationReportQuery;
|
||||
private readonly IAddOrganizationReportCommand _addOrganizationReportCommand;
|
||||
private readonly IUpdateOrganizationReportCommand _updateOrganizationReportCommand;
|
||||
private readonly IUpdateOrganizationReportSummaryCommand _updateOrganizationReportSummaryCommand;
|
||||
private readonly IGetOrganizationReportSummaryDataQuery _getOrganizationReportSummaryDataQuery;
|
||||
private readonly IGetOrganizationReportSummaryDataByDateRangeQuery _getOrganizationReportSummaryDataByDateRangeQuery;
|
||||
private readonly IGetOrganizationReportDataQuery _getOrganizationReportDataQuery;
|
||||
private readonly IUpdateOrganizationReportDataCommand _updateOrganizationReportDataCommand;
|
||||
private readonly IGetOrganizationReportApplicationDataQuery _getOrganizationReportApplicationDataQuery;
|
||||
private readonly IUpdateOrganizationReportApplicationDataCommand _updateOrganizationReportApplicationDataCommand;
|
||||
|
||||
public OrganizationReportsController(
|
||||
ICurrentContext currentContext,
|
||||
IGetOrganizationReportQuery getOrganizationReportQuery,
|
||||
IAddOrganizationReportCommand addOrganizationReportCommand,
|
||||
IUpdateOrganizationReportCommand updateOrganizationReportCommand,
|
||||
IUpdateOrganizationReportSummaryCommand updateOrganizationReportSummaryCommand,
|
||||
IGetOrganizationReportSummaryDataQuery getOrganizationReportSummaryDataQuery,
|
||||
IGetOrganizationReportSummaryDataByDateRangeQuery getOrganizationReportSummaryDataByDateRangeQuery,
|
||||
IGetOrganizationReportDataQuery getOrganizationReportDataQuery,
|
||||
IUpdateOrganizationReportDataCommand updateOrganizationReportDataCommand,
|
||||
IGetOrganizationReportApplicationDataQuery getOrganizationReportApplicationDataQuery,
|
||||
IUpdateOrganizationReportApplicationDataCommand updateOrganizationReportApplicationDataCommand
|
||||
)
|
||||
{
|
||||
_currentContext = currentContext;
|
||||
_getOrganizationReportQuery = getOrganizationReportQuery;
|
||||
_addOrganizationReportCommand = addOrganizationReportCommand;
|
||||
_updateOrganizationReportCommand = updateOrganizationReportCommand;
|
||||
_updateOrganizationReportSummaryCommand = updateOrganizationReportSummaryCommand;
|
||||
_getOrganizationReportSummaryDataQuery = getOrganizationReportSummaryDataQuery;
|
||||
_getOrganizationReportSummaryDataByDateRangeQuery = getOrganizationReportSummaryDataByDateRangeQuery;
|
||||
_getOrganizationReportDataQuery = getOrganizationReportDataQuery;
|
||||
_updateOrganizationReportDataCommand = updateOrganizationReportDataCommand;
|
||||
_getOrganizationReportApplicationDataQuery = getOrganizationReportApplicationDataQuery;
|
||||
_updateOrganizationReportApplicationDataCommand = updateOrganizationReportApplicationDataCommand;
|
||||
}
|
||||
|
||||
#region Whole OrganizationReport Endpoints
|
||||
|
||||
[HttpGet("{organizationId}/latest")]
|
||||
public async Task<IActionResult> GetLatestOrganizationReportAsync(Guid organizationId)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var latestReport = await _getOrganizationReportQuery.GetLatestOrganizationReportAsync(organizationId);
|
||||
|
||||
return Ok(latestReport);
|
||||
}
|
||||
|
||||
[HttpGet("{organizationId}/{reportId}")]
|
||||
public async Task<IActionResult> GetOrganizationReportAsync(Guid organizationId, Guid reportId)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var report = await _getOrganizationReportQuery.GetOrganizationReportAsync(reportId);
|
||||
|
||||
if (report == null)
|
||||
{
|
||||
throw new NotFoundException("Report not found for the specified organization.");
|
||||
}
|
||||
|
||||
if (report.OrganizationId != organizationId)
|
||||
{
|
||||
throw new BadRequestException("Invalid report ID");
|
||||
}
|
||||
|
||||
return Ok(report);
|
||||
}
|
||||
|
||||
[HttpPost("{organizationId}")]
|
||||
public async Task<IActionResult> CreateOrganizationReportAsync(Guid organizationId, [FromBody] AddOrganizationReportRequest request)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (request.OrganizationId != organizationId)
|
||||
{
|
||||
throw new BadRequestException("Organization ID in the request body must match the route parameter");
|
||||
}
|
||||
|
||||
var report = await _addOrganizationReportCommand.AddOrganizationReportAsync(request);
|
||||
return Ok(report);
|
||||
}
|
||||
|
||||
[HttpPatch("{organizationId}/{reportId}")]
|
||||
public async Task<IActionResult> UpdateOrganizationReportAsync(Guid organizationId, [FromBody] UpdateOrganizationReportRequest request)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (request.OrganizationId != organizationId)
|
||||
{
|
||||
throw new BadRequestException("Organization ID in the request body must match the route parameter");
|
||||
}
|
||||
|
||||
var updatedReport = await _updateOrganizationReportCommand.UpdateOrganizationReportAsync(request);
|
||||
return Ok(updatedReport);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
# region SummaryData Field Endpoints
|
||||
|
||||
[HttpGet("{organizationId}/data/summary")]
|
||||
public async Task<IActionResult> GetOrganizationReportSummaryDataByDateRangeAsync(
|
||||
Guid organizationId, [FromQuery] DateTime startDate, [FromQuery] DateTime endDate)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (organizationId.Equals(null))
|
||||
{
|
||||
throw new BadRequestException("Organization ID is required.");
|
||||
}
|
||||
|
||||
var summaryDataList = await _getOrganizationReportSummaryDataByDateRangeQuery
|
||||
.GetOrganizationReportSummaryDataByDateRangeAsync(organizationId, startDate, endDate);
|
||||
|
||||
return Ok(summaryDataList);
|
||||
}
|
||||
|
||||
[HttpGet("{organizationId}/data/summary/{reportId}")]
|
||||
public async Task<IActionResult> GetOrganizationReportSummaryAsync(Guid organizationId, Guid reportId)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var summaryData =
|
||||
await _getOrganizationReportSummaryDataQuery.GetOrganizationReportSummaryDataAsync(organizationId, reportId);
|
||||
|
||||
if (summaryData == null)
|
||||
{
|
||||
throw new NotFoundException("Report not found for the specified organization.");
|
||||
}
|
||||
|
||||
return Ok(summaryData);
|
||||
}
|
||||
|
||||
[HttpPatch("{organizationId}/data/summary/{reportId}")]
|
||||
public async Task<IActionResult> UpdateOrganizationReportSummaryAsync(Guid organizationId, Guid reportId, [FromBody] UpdateOrganizationReportSummaryRequest request)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (request.OrganizationId != organizationId)
|
||||
{
|
||||
throw new BadRequestException("Organization ID in the request body must match the route parameter");
|
||||
}
|
||||
|
||||
if (request.ReportId != reportId)
|
||||
{
|
||||
throw new BadRequestException("Report ID in the request body must match the route parameter");
|
||||
}
|
||||
|
||||
var updatedReport = await _updateOrganizationReportSummaryCommand.UpdateOrganizationReportSummaryAsync(request);
|
||||
|
||||
return Ok(updatedReport);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region ReportData Field Endpoints
|
||||
|
||||
[HttpGet("{organizationId}/data/report/{reportId}")]
|
||||
public async Task<IActionResult> GetOrganizationReportDataAsync(Guid organizationId, Guid reportId)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var reportData = await _getOrganizationReportDataQuery.GetOrganizationReportDataAsync(organizationId, reportId);
|
||||
|
||||
if (reportData == null)
|
||||
{
|
||||
throw new NotFoundException("Organization report data not found.");
|
||||
}
|
||||
|
||||
return Ok(reportData);
|
||||
}
|
||||
|
||||
[HttpPatch("{organizationId}/data/report/{reportId}")]
|
||||
public async Task<IActionResult> UpdateOrganizationReportDataAsync(Guid organizationId, Guid reportId, [FromBody] UpdateOrganizationReportDataRequest request)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (request.OrganizationId != organizationId)
|
||||
{
|
||||
throw new BadRequestException("Organization ID in the request body must match the route parameter");
|
||||
}
|
||||
|
||||
if (request.ReportId != reportId)
|
||||
{
|
||||
throw new BadRequestException("Report ID in the request body must match the route parameter");
|
||||
}
|
||||
|
||||
var updatedReport = await _updateOrganizationReportDataCommand.UpdateOrganizationReportDataAsync(request);
|
||||
return Ok(updatedReport);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ApplicationData Field Endpoints
|
||||
|
||||
[HttpGet("{organizationId}/data/application/{reportId}")]
|
||||
public async Task<IActionResult> GetOrganizationReportApplicationDataAsync(Guid organizationId, Guid reportId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var applicationData = await _getOrganizationReportApplicationDataQuery.GetOrganizationReportApplicationDataAsync(organizationId, reportId);
|
||||
|
||||
if (applicationData == null)
|
||||
{
|
||||
throw new NotFoundException("Organization report application data not found.");
|
||||
}
|
||||
|
||||
return Ok(applicationData);
|
||||
}
|
||||
catch (Exception ex) when (!(ex is BadRequestException || ex is NotFoundException))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPatch("{organizationId}/data/application/{reportId}")]
|
||||
public async Task<IActionResult> UpdateOrganizationReportApplicationDataAsync(Guid organizationId, Guid reportId, [FromBody] UpdateOrganizationReportApplicationDataRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
if (!await _currentContext.AccessReports(organizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (request.OrganizationId != organizationId)
|
||||
{
|
||||
throw new BadRequestException("Organization ID in the request body must match the route parameter");
|
||||
}
|
||||
|
||||
if (request.Id != reportId)
|
||||
{
|
||||
throw new BadRequestException("Report ID in the request body must match the route parameter");
|
||||
}
|
||||
|
||||
var updatedReport = await _updateOrganizationReportApplicationDataCommand.UpdateOrganizationReportApplicationDataAsync(request);
|
||||
|
||||
|
||||
|
||||
return Ok(updatedReport);
|
||||
}
|
||||
catch (Exception ex) when (!(ex is BadRequestException || ex is NotFoundException))
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -25,7 +25,6 @@ public class ReportsController : Controller
|
||||
private readonly IGetPasswordHealthReportApplicationQuery _getPwdHealthReportAppQuery;
|
||||
private readonly IDropPasswordHealthReportApplicationCommand _dropPwdHealthReportAppCommand;
|
||||
private readonly IAddOrganizationReportCommand _addOrganizationReportCommand;
|
||||
private readonly IDropOrganizationReportCommand _dropOrganizationReportCommand;
|
||||
private readonly IGetOrganizationReportQuery _getOrganizationReportQuery;
|
||||
private readonly ILogger<ReportsController> _logger;
|
||||
|
||||
@@ -38,7 +37,6 @@ public class ReportsController : Controller
|
||||
IDropPasswordHealthReportApplicationCommand dropPwdHealthReportAppCommand,
|
||||
IGetOrganizationReportQuery getOrganizationReportQuery,
|
||||
IAddOrganizationReportCommand addOrganizationReportCommand,
|
||||
IDropOrganizationReportCommand dropOrganizationReportCommand,
|
||||
ILogger<ReportsController> logger
|
||||
)
|
||||
{
|
||||
@@ -50,7 +48,6 @@ public class ReportsController : Controller
|
||||
_dropPwdHealthReportAppCommand = dropPwdHealthReportAppCommand;
|
||||
_getOrganizationReportQuery = getOrganizationReportQuery;
|
||||
_addOrganizationReportCommand = addOrganizationReportCommand;
|
||||
_dropOrganizationReportCommand = dropOrganizationReportCommand;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
@@ -209,195 +206,4 @@ public class ReportsController : Controller
|
||||
|
||||
await _dropPwdHealthReportAppCommand.DropPasswordHealthReportApplicationAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new organization report
|
||||
/// </summary>
|
||||
/// <param name="request">A single instance of AddOrganizationReportRequest</param>
|
||||
/// <returns>A single instance of OrganizationReport</returns>
|
||||
/// <exception cref="NotFoundException">If user does not have access to the organization</exception>
|
||||
/// <exception cref="BadRequestException">If the organization Id is not valid</exception>
|
||||
[HttpPost("organization-reports")]
|
||||
public async Task<OrganizationReport> AddOrganizationReport([FromBody] AddOrganizationReportRequest request)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(request.OrganizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return await _addOrganizationReportCommand.AddOrganizationReportAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Drops organization reports for an organization
|
||||
/// </summary>
|
||||
/// <param name="request">A single instance of DropOrganizationReportRequest</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException">If user does not have access to the organization</exception>
|
||||
/// <exception cref="BadRequestException">If the organization does not have any records</exception>
|
||||
[HttpDelete("organization-reports")]
|
||||
public async Task DropOrganizationReport([FromBody] DropOrganizationReportRequest request)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(request.OrganizationId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
await _dropOrganizationReportCommand.DropOrganizationReportAsync(request);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets organization reports for an organization
|
||||
/// </summary>
|
||||
/// <param name="orgId">A valid Organization Id</param>
|
||||
/// <returns>An Enumerable of OrganizationReport</returns>
|
||||
/// <exception cref="NotFoundException">If user does not have access to the organization</exception>
|
||||
/// <exception cref="BadRequestException">If the organization Id is not valid</exception>
|
||||
[HttpGet("organization-reports/{orgId}")]
|
||||
public async Task<IEnumerable<OrganizationReport>> GetOrganizationReports(Guid orgId)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(orgId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return await _getOrganizationReportQuery.GetOrganizationReportAsync(orgId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the latest organization report for an organization
|
||||
/// </summary>
|
||||
/// <param name="orgId">A valid Organization Id</param>
|
||||
/// <returns>A single instance of OrganizationReport</returns>
|
||||
/// <exception cref="NotFoundException">If user does not have access to the organization</exception>
|
||||
/// <exception cref="BadRequestException">If the organization Id is not valid</exception>
|
||||
[HttpGet("organization-reports/latest/{orgId}")]
|
||||
public async Task<OrganizationReport> GetLatestOrganizationReport(Guid orgId)
|
||||
{
|
||||
if (!await _currentContext.AccessReports(orgId))
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
return await _getOrganizationReportQuery.GetLatestOrganizationReportAsync(orgId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Organization Report Summary for an organization.
|
||||
/// This includes the latest report's encrypted data, encryption key, and date.
|
||||
/// This is a mock implementation and should be replaced with actual data retrieval logic.
|
||||
/// </summary>
|
||||
/// <param name="orgId"></param>
|
||||
/// <param name="from">Min date (example: 2023-01-01)</param>
|
||||
/// <param name="to">Max date (example: 2023-12-31)</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
[HttpGet("organization-report-summary/{orgId}")]
|
||||
public IEnumerable<OrganizationReportSummaryModel> GetOrganizationReportSummary(
|
||||
[FromRoute] Guid orgId,
|
||||
[FromQuery] DateOnly from,
|
||||
[FromQuery] DateOnly to)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
throw new BadRequestException(ModelState);
|
||||
}
|
||||
|
||||
GuardOrganizationAccess(orgId);
|
||||
|
||||
// FIXME: remove this mock class when actual data retrieval is implemented
|
||||
return MockOrganizationReportSummary.GetMockData()
|
||||
.Where(_ => _.OrganizationId == orgId
|
||||
&& _.Date >= from.ToDateTime(TimeOnly.MinValue)
|
||||
&& _.Date <= to.ToDateTime(TimeOnly.MaxValue));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new Organization Report Summary for an organization.
|
||||
/// This is a mock implementation and should be replaced with actual creation logic.
|
||||
/// </summary>
|
||||
/// <param name="model"></param>
|
||||
/// <returns>Returns 204 Created with the created OrganizationReportSummaryModel</returns>
|
||||
/// <exception cref="NotFoundException"></exception>
|
||||
[HttpPost("organization-report-summary")]
|
||||
public IActionResult CreateOrganizationReportSummary([FromBody] OrganizationReportSummaryModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
throw new BadRequestException(ModelState);
|
||||
}
|
||||
|
||||
GuardOrganizationAccess(model.OrganizationId);
|
||||
|
||||
// TODO: Implement actual creation logic
|
||||
|
||||
// Returns 204 No Content as a placeholder
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
[HttpPut("organization-report-summary")]
|
||||
public IActionResult UpdateOrganizationReportSummary([FromBody] OrganizationReportSummaryModel model)
|
||||
{
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
throw new BadRequestException(ModelState);
|
||||
}
|
||||
|
||||
GuardOrganizationAccess(model.OrganizationId);
|
||||
|
||||
// TODO: Implement actual update logic
|
||||
|
||||
// Returns 204 No Content as a placeholder
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
private void GuardOrganizationAccess(Guid organizationId)
|
||||
{
|
||||
if (!_currentContext.AccessReports(organizationId).Result)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: remove this mock class when actual data retrieval is implemented
|
||||
private class MockOrganizationReportSummary
|
||||
{
|
||||
public static List<OrganizationReportSummaryModel> GetMockData()
|
||||
{
|
||||
return new List<OrganizationReportSummaryModel>
|
||||
{
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.EtCcxDEBoF1MYChYHC4Q1w==|RyZ07R7qEFBbc/ICLFpEMockL9K+PD6rOod6DGHHrkaRLHUDqDwmxbu3jnD0cg8s7GIYmp0jApHXC+82QdApk87pA0Kr8fN2Rj0+8bDQCjhKfoRTipAB25S/n2E+ttjvlFfag92S66XqUH9S/eZw/Q==|0bPfykHk3SqS/biLNcNoYtH6YTstBEKu3AhvdZZLxhU=",
|
||||
EncryptionKey = "2.Dd/TtdNwxWdYg9+fRkxh6w==|8KAiK9SoadgFRmyVOchd4tNh2vErD1Rv9x1gqtsE5tzxKE/V/5kkr1WuVG+QpEj//YaQt221UEMESRSXicZ7a9cB6xXLBkbbFwmecQRJVBs=|902em44n9cwciZzYrYuX6MRzRa+4hh1HHfNAxyJx/IM=",
|
||||
Date = DateTime.UtcNow
|
||||
},
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.HvY4fAvbzYV1hqa3255m5Q==|WcKga2Wka5i8fVso8MgjzfBAwxaqdhZDL3bnvhDsisZ0r9lNKQcG3YUQSFpJxr74cgg5QRQaFieCUe2YppciHDT6bsaE2VzFce3cNNB821uTFqnlJClkGJpG1nGvPupdErrg4Ik57WenEzYesmR4pw==|F0aJfF+1MlPm+eAlQnDgFnwfv198N9VtPqFJa4+UFqk=",
|
||||
EncryptionKey = "2.ctMgLN4ycPusbQArG/uiag==|NtqiQsAoUxMSTBQsxAMyVLWdt5lVEUGZQNxZSBU4l76ywH2f6dx5FWFrcF3t3GBqy5yDoc5eBg0VlJDW9coqzp8j9n8h1iMrtmXPyBMAhbc=|pbH+w68BUdUKYCfNRpjd8NENw2lZ0vfxgMuTrsrRCTQ=",
|
||||
Date = DateTime.UtcNow.AddMonths(-1)
|
||||
},
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.NH4qLZYUkz/+qpB/mRsLTA==|LEFt05jJz0ngh+Hl5lqk6kebj7lZMefA3eFdL1kLJSGdD3uTOngRwH7GXLQNFeQOxutnLX9YUILbUEPwaM8gCwNQ1KWYdB1Z+Ky4nzKRb60N7L5aTA2za6zXTIdjv7Zwhg0jPZ6sPevTuvSyqjMCuA==|Uuu6gZaF0wvB2mHFwtvHegMxfe8DgsYWTRfGiVn4lkM=",
|
||||
EncryptionKey = "2.3YwG78ykSxAn44NcymdG4w==|4jfn0nLoFielicAFbmq27DNUUjV4SwGePnjYRmOa7hk4pEPnQRS3MsTJFbutVyXOgKFY9Yn2yGFZownY9EmXOMM+gHPD0t6TfzUKqQcRyuI=|wasP9zZEL9mFH5HzJYrMxnKUr/XlFKXCxG9uW66uaPU=",
|
||||
Date = DateTime.UtcNow.AddMonths(-1)
|
||||
},
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.YmKWj/707wDPONh+JXPBOw==|Fx4jcUHmnUnSMCU8vdThMSYpDyKPnC09TxpSbNxia0M6MFbd5WHElcVribrYgTENyU0HlqPW43hThJ6xXCM0EjEWP7/jb/0l07vMNkA7sDYq+czf0XnYZgZSGKh06wFVz8xkhaPTdsiO4CXuMsoH+w==|DDVwVFHzdfbPQe3ycCx82eYVHDW97V/eWTPsNpHX/+U=",
|
||||
EncryptionKey = "2.f/U45I7KF+JKfnvOArUyaw==|zNhhS2q2WwBl6SqLWMkxrXC8EX91Ra9LJExywkJhsRbxubRLt7fK+YWc8T1LUaDmMwJ3G8buSPGzyacKX0lnUR33dW6DIaLNgRZ/ekb/zkg=|qFoIZWwS0foiiIOyikFRwQKmmmI2HeyHcOVklJnIILI=",
|
||||
Date = DateTime.UtcNow.AddMonths(-1)
|
||||
},
|
||||
new OrganizationReportSummaryModel
|
||||
{
|
||||
OrganizationId = Guid.Parse("cf6cb873-4916-4b2b-aef0-b20d00e7f3e2"),
|
||||
EncryptedData = "2.WYauwooJUEY3kZsDPphmrA==|oguYW6h10A4GxK4KkRS0X32qSTekU2CkGqNDNGfisUgvJzsyoVTafO9sVcdPdg4BUM7YNkPMjYiKEc5jMHkIgLzbnM27jcGvMJrrccSrLHiWL6/mEiqQkV3TlfiZF9i3wqj1ITsYRzM454uNle6Wrg==|uR67aFYb1i5LSidWib0iTf8091l8GY5olHkVXse3CAw=",
|
||||
EncryptionKey = "2.ZyV9+9A2cxNaf8dfzfbnlA==|hhorBpVkcrrhTtNmd6SNHYI8gPNokGLOC22Vx8Qa/AotDAcyuYWw56zsawMnzpAdJGEJFtszKM2+VUVOcroCTMWHpy8yNf/kZA6uPk3Lz3s=|ASzVeJf+K1ZB8NXuypamRBGRuRq0GUHZBEy5r/O7ORY=",
|
||||
Date = DateTime.UtcNow.AddMonths(-1)
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user