-
Notifications
You must be signed in to change notification settings - Fork 1.6k
PM-31923 adding the whole report endpoints v2 #7228
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
f7ff5b2
cffbbe0
5ca00bc
c98183d
24dd095
b2bdd8c
0020254
f5947e2
81d53b6
9fced60
d4a3f07
ba8c1a8
f12da24
48ce27b
2d81562
8cd48f8
be34ff2
b58003c
2463e26
2abe9b1
7c6d506
05ce54d
2783f20
76b702b
185a359
c94cb46
fa9e06e
b73d339
cac69fb
1304ef2
a35ff69
0cc149d
3e518ef
3e72e93
b60835f
de3ea38
d89cd8d
fae1faa
437f212
35aec44
36476bb
309f347
36c1696
0c37138
ef96d03
c29927f
1f5c359
3ff0b09
b16061c
e6e1785
f4c8ef4
2d4f3e0
cc3759b
32e7ead
f4af07d
d69638f
0ea6e6f
8b527a0
ded06cd
679de60
6231dd2
26a4a5d
a407296
f5ca678
893d061
93f2dab
8bb25fa
3b41713
ca50a40
4f88493
c8413e8
da9e4cc
69fc270
451ca9b
5794c3c
222d938
27a772e
5f19538
d8592f4
7d5ff28
01059fd
18956c9
642bdf0
829e2e1
fec7ac9
6aa0112
31fe66e
95fc7d8
3532a92
986f638
3ecd15b
d29fcff
2e3c71f
6d2acaf
cc12eca
6c27487
f448cc1
ced94d5
5bc720b
869ee0f
2412e74
96792af
86e5e12
5c7184a
276a218
2a9c5d6
24d9065
91c7972
80e7aea
9ce2987
e2e33a9
6bffcf1
16363f4
29c5089
a2fb475
5775f6f
c9f53a3
b3343cf
00584c1
a070867
4141d6a
8126bc3
58f68ce
48f3dfa
a828be9
3f2592e
567a53e
7af2830
11167a9
f7f69b1
7567108
6a9c2cb
84146be
92442b7
c5d05a4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| ο»Ώusing System.Text.Json.Serialization; | ||
| using Bit.Core.Dirt.Reports.ReportFeatures.Requests; | ||
|
|
||
| namespace Bit.Api.Dirt.Models.Request; | ||
|
|
||
| public class AddOrganizationReportRequestModel | ||
| { | ||
| public string? ReportData { get; set; } | ||
| public string? ContentEncryptionKey { get; set; } | ||
| public string? SummaryData { get; set; } | ||
| public string? ApplicationData { get; set; } | ||
| [JsonPropertyName("metrics")] | ||
| public OrganizationReportMetrics? ReportMetrics { get; set; } | ||
| public long? FileSize { get; set; } | ||
|
|
||
| public AddOrganizationReportRequest ToData(Guid organizationId) | ||
| { | ||
| return new AddOrganizationReportRequest | ||
| { | ||
| OrganizationId = organizationId, | ||
| ReportData = ReportData, | ||
| ContentEncryptionKey = ContentEncryptionKey, | ||
| SummaryData = SummaryData, | ||
| ApplicationData = ApplicationData, | ||
| ReportMetrics = ReportMetrics, | ||
| FileSize = FileSize | ||
| }; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| ο»Ώusing Bit.Core.Dirt.Reports.ReportFeatures.Requests; | ||
|
|
||
| namespace Bit.Api.Dirt.Models.Request; | ||
|
|
||
| public class UpdateOrganizationReportApplicationDataRequestModel | ||
| { | ||
| public string? ApplicationData { get; set; } | ||
|
|
||
| public UpdateOrganizationReportApplicationDataRequest ToData(Guid organizationId, Guid reportId) | ||
| { | ||
| return new UpdateOrganizationReportApplicationDataRequest | ||
| { | ||
| OrganizationId = organizationId, | ||
| Id = reportId, | ||
| ApplicationData = ApplicationData | ||
| }; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| ο»Ώusing System.Text.Json.Serialization; | ||
| using Bit.Core.Dirt.Reports.ReportFeatures.Requests; | ||
|
|
||
| namespace Bit.Api.Dirt.Models.Request; | ||
|
|
||
| public class UpdateOrganizationReportSummaryRequestModel | ||
| { | ||
| public string? SummaryData { get; set; } | ||
| [JsonPropertyName("metrics")] | ||
| public OrganizationReportMetrics? ReportMetrics { get; set; } | ||
|
|
||
| public UpdateOrganizationReportSummaryRequest ToData(Guid organizationId, Guid reportId) | ||
| { | ||
| return new UpdateOrganizationReportSummaryRequest | ||
| { | ||
| OrganizationId = organizationId, | ||
| ReportId = reportId, | ||
| SummaryData = SummaryData, | ||
| ReportMetrics = ReportMetrics | ||
| }; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| ο»Ώusing Bit.Core.Dirt.Reports.ReportFeatures.Requests; | ||
|
|
||
| namespace Bit.Api.Dirt.Models.Request; | ||
|
|
||
| public class UpdateOrganizationReportV2RequestModel | ||
| { | ||
| public required string ContentEncryptionKey { get; set; } | ||
| public required string SummaryData { get; set; } | ||
| public required string ApplicationData { get; set; } | ||
| public required OrganizationReportMetrics ReportMetrics { get; set; } | ||
|
Banrion marked this conversation as resolved.
|
||
|
|
||
| public UpdateOrganizationReportV2Request ToData(Guid organizationId, Guid reportId) | ||
| { | ||
| return new UpdateOrganizationReportV2Request | ||
| { | ||
| OrganizationId = organizationId, | ||
| ReportId = reportId, | ||
| ContentEncryptionKey = ContentEncryptionKey, | ||
| SummaryData = SummaryData, | ||
| ApplicationData = ApplicationData, | ||
| ReportMetrics = ReportMetrics | ||
| }; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| ο»Ώusing Bit.Core.Dirt.Models.Data; | ||
|
|
||
| namespace Bit.Api.Dirt.Models.Response; | ||
|
|
||
| public class OrganizationReportApplicationDataResponseModel | ||
| { | ||
| public OrganizationReportApplicationDataResponseModel(OrganizationReportApplicationDataResponse applicationDataResponse) | ||
| { | ||
| ApplicationData = applicationDataResponse.ApplicationData; | ||
| } | ||
|
|
||
| public string? ApplicationData { get; set; } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| ο»Ώusing Bit.Core.Enums; | ||
|
|
||
| namespace Bit.Api.Dirt.Models.Response; | ||
|
|
||
| public class OrganizationReportFileResponseModel | ||
| { | ||
| public OrganizationReportFileResponseModel() { } | ||
|
|
||
| public string ReportFileUploadUrl { get; set; } = string.Empty; | ||
| public OrganizationReportResponseModel ReportResponse { get; set; } = null!; | ||
| public FileUploadType FileUploadType { get; set; } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,6 @@ | ||
| ο»Ώusing Bit.Core.Dirt.Entities; | ||
| using Bit.Core.Dirt.Models.Data; | ||
| using Bit.Core.Enums; | ||
|
|
||
| namespace Bit.Api.Dirt.Models.Response; | ||
|
|
||
|
|
@@ -10,11 +12,11 @@ public class OrganizationReportResponseModel | |
| public string? ContentEncryptionKey { get; set; } | ||
| public string? SummaryData { get; set; } | ||
| public string? ApplicationData { get; set; } | ||
| public int? PasswordCount { get; set; } | ||
| public int? PasswordAtRiskCount { get; set; } | ||
| public int? MemberCount { get; set; } | ||
| public DateTime? CreationDate { get; set; } = null; | ||
| public DateTime? RevisionDate { get; set; } = null; | ||
| public ReportFile? ReportFile { get; set; } | ||
| public string? ReportFileDownloadUrl { get; set; } | ||
| public FileUploadType? FileUploadType { get; set; } | ||
|
Comment on lines
+16
to
+17
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. π These seem to be unused in |
||
| public DateTime? CreationDate { get; set; } | ||
| public DateTime? RevisionDate { get; set; } | ||
|
|
||
| public OrganizationReportResponseModel(OrganizationReport organizationReport) | ||
| { | ||
|
|
@@ -29,9 +31,7 @@ public OrganizationReportResponseModel(OrganizationReport organizationReport) | |
| ContentEncryptionKey = organizationReport.ContentEncryptionKey; | ||
| SummaryData = organizationReport.SummaryData; | ||
| ApplicationData = organizationReport.ApplicationData; | ||
| PasswordCount = organizationReport.PasswordCount; | ||
| PasswordAtRiskCount = organizationReport.PasswordAtRiskCount; | ||
| MemberCount = organizationReport.MemberCount; | ||
| ReportFile = organizationReport.GetReportFile(); | ||
| CreationDate = organizationReport.CreationDate; | ||
| RevisionDate = organizationReport.RevisionDate; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| ο»Ώusing System.Text.Json.Serialization; | ||
| using Bit.Core.Dirt.Models.Data; | ||
|
|
||
| namespace Bit.Api.Dirt.Models.Response; | ||
|
|
||
| public class OrganizationReportSummaryDataResponseModel | ||
| { | ||
| public OrganizationReportSummaryDataResponseModel(OrganizationReportSummaryDataResponse summaryDataResponse) | ||
| { | ||
| EncryptedData = summaryDataResponse.SummaryData; | ||
| EncryptionKey = summaryDataResponse.ContentEncryptionKey; | ||
| Date = summaryDataResponse.RevisionDate; | ||
| } | ||
|
|
||
| [JsonPropertyName("encryptedData")] | ||
| public string EncryptedData { get; set; } | ||
|
|
||
| [JsonPropertyName("encryptionKey")] | ||
| public string EncryptionKey { get; set; } | ||
|
|
||
| [JsonPropertyName("date")] | ||
| public DateTime Date { get; set; } | ||
| } |
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| ο»Ώusing Bit.Core.Dirt.Entities; | ||
| using Bit.Core.Dirt.Models.Data; | ||
| 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 Bit.Core.Utilities; | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Logging; | ||
| using ZiggyCreatures.Caching.Fusion; | ||
|
|
||
| namespace Bit.Core.Dirt.Reports.ReportFeatures; | ||
|
|
||
| public class CreateOrganizationReportCommand : ICreateOrganizationReportCommand | ||
| { | ||
| private readonly IOrganizationRepository _organizationRepo; | ||
| private readonly IOrganizationReportRepository _organizationReportRepo; | ||
| private readonly ILogger<CreateOrganizationReportCommand> _logger; | ||
| private readonly IFusionCache _cache; | ||
|
|
||
| public CreateOrganizationReportCommand( | ||
| IOrganizationRepository organizationRepository, | ||
| IOrganizationReportRepository organizationReportRepository, | ||
| ILogger<CreateOrganizationReportCommand> logger, | ||
| [FromKeyedServices(OrganizationReportCacheConstants.CacheName)] IFusionCache cache) | ||
| { | ||
| _organizationRepo = organizationRepository; | ||
| _organizationReportRepo = organizationReportRepository; | ||
| _logger = logger; | ||
| _cache = cache; | ||
| } | ||
|
|
||
| public async Task<OrganizationReport> CreateAsync(AddOrganizationReportRequest request) | ||
| { | ||
| _logger.LogInformation(Constants.BypassFiltersEventId, | ||
| "Creating organization report for organization {organizationId}", request.OrganizationId); | ||
|
|
||
| var (isValid, errorMessage) = await ValidateRequestAsync(request); | ||
| if (!isValid) | ||
| { | ||
| _logger.LogInformation(Constants.BypassFiltersEventId, | ||
| "Failed to create organization {organizationId} report: {errorMessage}", | ||
| request.OrganizationId, errorMessage); | ||
| throw new BadRequestException(errorMessage); | ||
| } | ||
|
|
||
| var fileData = new ReportFile | ||
| { | ||
| Id = CoreHelpers.SecureRandomString(32, upper: false, special: false), | ||
| FileName = "report-data.json", | ||
| Size = request.FileSize ?? 0, | ||
| Validated = false | ||
| }; | ||
|
|
||
| var organizationReport = new OrganizationReport | ||
| { | ||
| OrganizationId = request.OrganizationId, | ||
| CreationDate = DateTime.UtcNow, | ||
| ContentEncryptionKey = request.ContentEncryptionKey ?? string.Empty, | ||
| SummaryData = request.SummaryData, | ||
| ApplicationData = request.ApplicationData, | ||
| ApplicationCount = request.ReportMetrics?.ApplicationCount, | ||
| ApplicationAtRiskCount = request.ReportMetrics?.ApplicationAtRiskCount, | ||
| CriticalApplicationCount = request.ReportMetrics?.CriticalApplicationCount, | ||
| CriticalApplicationAtRiskCount = request.ReportMetrics?.CriticalApplicationAtRiskCount, | ||
| MemberCount = request.ReportMetrics?.MemberCount, | ||
| MemberAtRiskCount = request.ReportMetrics?.MemberAtRiskCount, | ||
| CriticalMemberCount = request.ReportMetrics?.CriticalMemberCount, | ||
| CriticalMemberAtRiskCount = request.ReportMetrics?.CriticalMemberAtRiskCount, | ||
| PasswordCount = request.ReportMetrics?.PasswordCount, | ||
| PasswordAtRiskCount = request.ReportMetrics?.PasswordAtRiskCount, | ||
| CriticalPasswordCount = request.ReportMetrics?.CriticalPasswordCount, | ||
| CriticalPasswordAtRiskCount = request.ReportMetrics?.CriticalPasswordAtRiskCount, | ||
| RevisionDate = DateTime.UtcNow | ||
| }; | ||
| organizationReport.SetReportFile(fileData); | ||
|
|
||
| var data = await _organizationReportRepo.CreateAsync(organizationReport); | ||
|
|
||
| await _cache.RemoveByTagAsync(OrganizationReportCacheConstants.BuildCacheTagForOrganizationReports(request.OrganizationId)); | ||
|
|
||
| _logger.LogInformation(Constants.BypassFiltersEventId, | ||
| "Successfully created organization report for organization {organizationId}, {organizationReportId}", | ||
| request.OrganizationId, data.Id); | ||
|
|
||
| return data; | ||
| } | ||
|
|
||
| private async Task<(bool IsValid, string errorMessage)> ValidateRequestAsync( | ||
| AddOrganizationReportRequest request) | ||
| { | ||
| var organization = await _organizationRepo.GetByIdAsync(request.OrganizationId); | ||
| if (organization == null) | ||
| { | ||
| return (false, "Invalid Organization"); | ||
| } | ||
|
|
||
| if (string.IsNullOrWhiteSpace(request.ContentEncryptionKey)) | ||
| { | ||
| return (false, "Content Encryption Key is required"); | ||
| } | ||
|
|
||
| if (string.IsNullOrWhiteSpace(request.SummaryData)) | ||
| { | ||
| return (false, "Summary Data is required"); | ||
| } | ||
|
|
||
| if (string.IsNullOrWhiteSpace(request.ApplicationData)) | ||
| { | ||
| return (false, "Application Data is required"); | ||
| } | ||
|
|
||
| if (request.ReportMetrics == null) | ||
| { | ||
| return (false, "Report Metrics is required"); | ||
| } | ||
|
|
||
| return (true, string.Empty); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
βοΈ Optional fields are Inconsistent with prior changes to remove optional fields from
UpdateOrganizationReportV2RequestModel. These optional fields may be required for use in the create route for backwards compatibility with v1. To be reviewed and followed up on with dead null checks.