Skip to content

Commit e102a74

Browse files
[PM-26967] Added new metric properties (#6519)
1 parent b832541 commit e102a74

17 files changed

Lines changed: 359 additions & 39 deletions

src/Api/Dirt/Controllers/OrganizationReportsController.cs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Bit.Core.Context;
1+
using Bit.Api.Dirt.Models.Response;
2+
using Bit.Core.Context;
23
using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
34
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
45
using Bit.Core.Exceptions;
@@ -61,8 +62,9 @@ public async Task<IActionResult> GetLatestOrganizationReportAsync(Guid organizat
6162
}
6263

6364
var latestReport = await _getOrganizationReportQuery.GetLatestOrganizationReportAsync(organizationId);
65+
var response = latestReport == null ? null : new OrganizationReportResponseModel(latestReport);
6466

65-
return Ok(latestReport);
67+
return Ok(response);
6668
}
6769

6870
[HttpGet("{organizationId}/{reportId}")]
@@ -102,7 +104,8 @@ public async Task<IActionResult> CreateOrganizationReportAsync(Guid organization
102104
}
103105

104106
var report = await _addOrganizationReportCommand.AddOrganizationReportAsync(request);
105-
return Ok(report);
107+
var response = report == null ? null : new OrganizationReportResponseModel(report);
108+
return Ok(response);
106109
}
107110

108111
[HttpPatch("{organizationId}/{reportId}")]
@@ -119,7 +122,8 @@ public async Task<IActionResult> UpdateOrganizationReportAsync(Guid organization
119122
}
120123

121124
var updatedReport = await _updateOrganizationReportCommand.UpdateOrganizationReportAsync(request);
122-
return Ok(updatedReport);
125+
var response = new OrganizationReportResponseModel(updatedReport);
126+
return Ok(response);
123127
}
124128

125129
#endregion
@@ -182,10 +186,10 @@ public async Task<IActionResult> UpdateOrganizationReportSummaryAsync(Guid organ
182186
{
183187
throw new BadRequestException("Report ID in the request body must match the route parameter");
184188
}
185-
186189
var updatedReport = await _updateOrganizationReportSummaryCommand.UpdateOrganizationReportSummaryAsync(request);
190+
var response = new OrganizationReportResponseModel(updatedReport);
187191

188-
return Ok(updatedReport);
192+
return Ok(response);
189193
}
190194
#endregion
191195

@@ -228,7 +232,9 @@ public async Task<IActionResult> UpdateOrganizationReportDataAsync(Guid organiza
228232
}
229233

230234
var updatedReport = await _updateOrganizationReportDataCommand.UpdateOrganizationReportDataAsync(request);
231-
return Ok(updatedReport);
235+
var response = new OrganizationReportResponseModel(updatedReport);
236+
237+
return Ok(response);
232238
}
233239

234240
#endregion
@@ -265,7 +271,6 @@ public async Task<IActionResult> UpdateOrganizationReportApplicationDataAsync(Gu
265271
{
266272
try
267273
{
268-
269274
if (!await _currentContext.AccessReports(organizationId))
270275
{
271276
throw new NotFoundException();
@@ -282,10 +287,9 @@ public async Task<IActionResult> UpdateOrganizationReportApplicationDataAsync(Gu
282287
}
283288

284289
var updatedReport = await _updateOrganizationReportApplicationDataCommand.UpdateOrganizationReportApplicationDataAsync(request);
290+
var response = new OrganizationReportResponseModel(updatedReport);
285291

286-
287-
288-
return Ok(updatedReport);
292+
return Ok(response);
289293
}
290294
catch (Exception ex) when (!(ex is BadRequestException || ex is NotFoundException))
291295
{
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using Bit.Core.Dirt.Entities;
2+
3+
namespace Bit.Api.Dirt.Models.Response;
4+
5+
public class OrganizationReportResponseModel
6+
{
7+
public Guid Id { get; set; }
8+
public Guid OrganizationId { get; set; }
9+
public string? ReportData { get; set; }
10+
public string? ContentEncryptionKey { get; set; }
11+
public string? SummaryData { get; set; }
12+
public string? ApplicationData { get; set; }
13+
public int? PasswordCount { get; set; }
14+
public int? PasswordAtRiskCount { get; set; }
15+
public int? MemberCount { get; set; }
16+
public DateTime? CreationDate { get; set; } = null;
17+
public DateTime? RevisionDate { get; set; } = null;
18+
19+
public OrganizationReportResponseModel(OrganizationReport organizationReport)
20+
{
21+
if (organizationReport == null)
22+
{
23+
return;
24+
}
25+
26+
Id = organizationReport.Id;
27+
OrganizationId = organizationReport.OrganizationId;
28+
ReportData = organizationReport.ReportData;
29+
ContentEncryptionKey = organizationReport.ContentEncryptionKey;
30+
SummaryData = organizationReport.SummaryData;
31+
ApplicationData = organizationReport.ApplicationData;
32+
PasswordCount = organizationReport.PasswordCount;
33+
PasswordAtRiskCount = organizationReport.PasswordAtRiskCount;
34+
MemberCount = organizationReport.MemberCount;
35+
CreationDate = organizationReport.CreationDate;
36+
RevisionDate = organizationReport.RevisionDate;
37+
}
38+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
2+
3+
namespace Bit.Core.Dirt.Reports.Models.Data;
4+
5+
public class OrganizationReportMetricsData
6+
{
7+
public Guid OrganizationId { get; set; }
8+
public int? ApplicationCount { get; set; }
9+
public int? ApplicationAtRiskCount { get; set; }
10+
public int? CriticalApplicationCount { get; set; }
11+
public int? CriticalApplicationAtRiskCount { get; set; }
12+
public int? MemberCount { get; set; }
13+
public int? MemberAtRiskCount { get; set; }
14+
public int? CriticalMemberCount { get; set; }
15+
public int? CriticalMemberAtRiskCount { get; set; }
16+
public int? PasswordCount { get; set; }
17+
public int? PasswordAtRiskCount { get; set; }
18+
public int? CriticalPasswordCount { get; set; }
19+
public int? CriticalPasswordAtRiskCount { get; set; }
20+
21+
public static OrganizationReportMetricsData From(Guid organizationId, OrganizationReportMetricsRequest? request)
22+
{
23+
if (request == null)
24+
{
25+
return new OrganizationReportMetricsData
26+
{
27+
OrganizationId = organizationId
28+
};
29+
}
30+
31+
return new OrganizationReportMetricsData
32+
{
33+
OrganizationId = organizationId,
34+
ApplicationCount = request.ApplicationCount,
35+
ApplicationAtRiskCount = request.ApplicationAtRiskCount,
36+
CriticalApplicationCount = request.CriticalApplicationCount,
37+
CriticalApplicationAtRiskCount = request.CriticalApplicationAtRiskCount,
38+
MemberCount = request.MemberCount,
39+
MemberAtRiskCount = request.MemberAtRiskCount,
40+
CriticalMemberCount = request.CriticalMemberCount,
41+
CriticalMemberAtRiskCount = request.CriticalMemberAtRiskCount,
42+
PasswordCount = request.PasswordCount,
43+
PasswordAtRiskCount = request.PasswordAtRiskCount,
44+
CriticalPasswordCount = request.CriticalPasswordCount,
45+
CriticalPasswordAtRiskCount = request.CriticalPasswordAtRiskCount
46+
};
47+
}
48+
}

src/Core/Dirt/Reports/ReportFeatures/AddOrganizationReportCommand.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,28 @@ public async Task<OrganizationReport> AddOrganizationReportAsync(AddOrganization
3535
throw new BadRequestException(errorMessage);
3636
}
3737

38+
var requestMetrics = request.Metrics ?? new OrganizationReportMetricsRequest();
39+
3840
var organizationReport = new OrganizationReport
3941
{
4042
OrganizationId = request.OrganizationId,
41-
ReportData = request.ReportData,
43+
ReportData = request.ReportData ?? string.Empty,
4244
CreationDate = DateTime.UtcNow,
43-
ContentEncryptionKey = request.ContentEncryptionKey,
45+
ContentEncryptionKey = request.ContentEncryptionKey ?? string.Empty,
4446
SummaryData = request.SummaryData,
4547
ApplicationData = request.ApplicationData,
48+
ApplicationCount = requestMetrics.ApplicationCount,
49+
ApplicationAtRiskCount = requestMetrics.ApplicationAtRiskCount,
50+
CriticalApplicationCount = requestMetrics.CriticalApplicationCount,
51+
CriticalApplicationAtRiskCount = requestMetrics.CriticalApplicationAtRiskCount,
52+
MemberCount = requestMetrics.MemberCount,
53+
MemberAtRiskCount = requestMetrics.MemberAtRiskCount,
54+
CriticalMemberCount = requestMetrics.CriticalMemberCount,
55+
CriticalMemberAtRiskCount = requestMetrics.CriticalMemberAtRiskCount,
56+
PasswordCount = requestMetrics.PasswordCount,
57+
PasswordAtRiskCount = requestMetrics.PasswordAtRiskCount,
58+
CriticalPasswordCount = requestMetrics.CriticalPasswordCount,
59+
CriticalPasswordAtRiskCount = requestMetrics.CriticalPasswordAtRiskCount,
4660
RevisionDate = DateTime.UtcNow
4761
};
4862

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
// FIXME: Update this file to be null safe and then delete the line below
2-
#nullable disable
3-
4-
namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests;
1+
namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests;
52

63
public class AddOrganizationReportRequest
74
{
85
public Guid OrganizationId { get; set; }
9-
public string ReportData { get; set; }
6+
public string? ReportData { get; set; }
7+
8+
public string? ContentEncryptionKey { get; set; }
109

11-
public string ContentEncryptionKey { get; set; }
10+
public string? SummaryData { get; set; }
1211

13-
public string SummaryData { get; set; }
12+
public string? ApplicationData { get; set; }
1413

15-
public string ApplicationData { get; set; }
14+
public OrganizationReportMetricsRequest? Metrics { get; set; }
1615
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests;
4+
5+
public class OrganizationReportMetricsRequest
6+
{
7+
[JsonPropertyName("totalApplicationCount")]
8+
public int? ApplicationCount { get; set; } = null;
9+
[JsonPropertyName("totalAtRiskApplicationCount")]
10+
public int? ApplicationAtRiskCount { get; set; } = null;
11+
[JsonPropertyName("totalCriticalApplicationCount")]
12+
public int? CriticalApplicationCount { get; set; } = null;
13+
[JsonPropertyName("totalCriticalAtRiskApplicationCount")]
14+
public int? CriticalApplicationAtRiskCount { get; set; } = null;
15+
[JsonPropertyName("totalMemberCount")]
16+
public int? MemberCount { get; set; } = null;
17+
[JsonPropertyName("totalAtRiskMemberCount")]
18+
public int? MemberAtRiskCount { get; set; } = null;
19+
[JsonPropertyName("totalCriticalMemberCount")]
20+
public int? CriticalMemberCount { get; set; } = null;
21+
[JsonPropertyName("totalCriticalAtRiskMemberCount")]
22+
public int? CriticalMemberAtRiskCount { get; set; } = null;
23+
[JsonPropertyName("totalPasswordCount")]
24+
public int? PasswordCount { get; set; } = null;
25+
[JsonPropertyName("totalAtRiskPasswordCount")]
26+
public int? PasswordAtRiskCount { get; set; } = null;
27+
[JsonPropertyName("totalCriticalPasswordCount")]
28+
public int? CriticalPasswordCount { get; set; } = null;
29+
[JsonPropertyName("totalCriticalAtRiskPasswordCount")]
30+
public int? CriticalPasswordAtRiskCount { get; set; } = null;
31+
}
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
1-
// FIXME: Update this file to be null safe and then delete the line below
2-
#nullable disable
3-
4-
namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests;
1+
namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests;
52

63
public class UpdateOrganizationReportApplicationDataRequest
74
{
85
public Guid Id { get; set; }
96
public Guid OrganizationId { get; set; }
10-
public string ApplicationData { get; set; }
7+
public string? ApplicationData { get; set; }
118
}
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
// FIXME: Update this file to be null safe and then delete the line below
2-
#nullable disable
3-
4-
namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests;
1+
namespace Bit.Core.Dirt.Reports.ReportFeatures.Requests;
52

63
public class UpdateOrganizationReportSummaryRequest
74
{
85
public Guid OrganizationId { get; set; }
96
public Guid ReportId { get; set; }
10-
public string SummaryData { get; set; }
7+
public string? SummaryData { get; set; }
8+
public OrganizationReportMetricsRequest? Metrics { get; set; }
119
}

src/Core/Dirt/Reports/ReportFeatures/UpdateOrganizationReportApplicationDataCommand.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public async Task<OrganizationReport> UpdateOrganizationReportApplicationDataAsy
5353
throw new BadRequestException("Organization report does not belong to the specified organization");
5454
}
5555

56-
var updatedReport = await _organizationReportRepo.UpdateApplicationDataAsync(request.OrganizationId, request.Id, request.ApplicationData);
56+
var updatedReport = await _organizationReportRepo.UpdateApplicationDataAsync(request.OrganizationId, request.Id, request.ApplicationData ?? string.Empty);
5757

5858
_logger.LogInformation(Constants.BypassFiltersEventId, "Successfully updated organization report application data {reportId} for organization {organizationId}",
5959
request.Id, request.OrganizationId);

src/Core/Dirt/Reports/ReportFeatures/UpdateOrganizationReportSummaryCommand.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Bit.Core.Dirt.Entities;
2+
using Bit.Core.Dirt.Reports.Models.Data;
23
using Bit.Core.Dirt.Reports.ReportFeatures.Interfaces;
34
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
45
using Bit.Core.Dirt.Repositories;
@@ -53,7 +54,8 @@ public async Task<OrganizationReport> UpdateOrganizationReportSummaryAsync(Updat
5354
throw new BadRequestException("Organization report does not belong to the specified organization");
5455
}
5556

56-
var updatedReport = await _organizationReportRepo.UpdateSummaryDataAsync(request.OrganizationId, request.ReportId, request.SummaryData);
57+
await _organizationReportRepo.UpdateMetricsAsync(request.ReportId, OrganizationReportMetricsData.From(request.OrganizationId, request.Metrics));
58+
var updatedReport = await _organizationReportRepo.UpdateSummaryDataAsync(request.OrganizationId, request.ReportId, request.SummaryData ?? string.Empty);
5759

5860
_logger.LogInformation(Constants.BypassFiltersEventId, "Successfully updated organization report summary {reportId} for organization {organizationId}",
5961
request.ReportId, request.OrganizationId);

0 commit comments

Comments
 (0)