PM-24436 Add logging to backend for Member Access Report (#6159)

* pm-24436 inital commit

* PM-24436 updating logsto bypass event filter
This commit is contained in:
Graham Walker 2025-09-03 10:39:12 -05:00 committed by GitHub
parent ef8c7f656d
commit 3731c7c40c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 34 additions and 19 deletions

View File

@ -1,6 +1,7 @@
using Bit.Api.Dirt.Models;
using Bit.Api.Dirt.Models.Response;
using Bit.Api.Tools.Models.Response;
using Bit.Core;
using Bit.Core.Context;
using Bit.Core.Dirt.Entities;
using Bit.Core.Dirt.Reports.Models.Data;
@ -26,6 +27,7 @@ public class ReportsController : Controller
private readonly IAddOrganizationReportCommand _addOrganizationReportCommand;
private readonly IDropOrganizationReportCommand _dropOrganizationReportCommand;
private readonly IGetOrganizationReportQuery _getOrganizationReportQuery;
private readonly ILogger<ReportsController> _logger;
public ReportsController(
ICurrentContext currentContext,
@ -36,7 +38,8 @@ public class ReportsController : Controller
IDropPasswordHealthReportApplicationCommand dropPwdHealthReportAppCommand,
IGetOrganizationReportQuery getOrganizationReportQuery,
IAddOrganizationReportCommand addOrganizationReportCommand,
IDropOrganizationReportCommand dropOrganizationReportCommand
IDropOrganizationReportCommand dropOrganizationReportCommand,
ILogger<ReportsController> logger
)
{
_currentContext = currentContext;
@ -48,6 +51,7 @@ public class ReportsController : Controller
_getOrganizationReportQuery = getOrganizationReportQuery;
_addOrganizationReportCommand = addOrganizationReportCommand;
_dropOrganizationReportCommand = dropOrganizationReportCommand;
_logger = logger;
}
/// <summary>
@ -86,32 +90,24 @@ public class ReportsController : Controller
{
if (!await _currentContext.AccessReports(orgId))
{
_logger.LogInformation(Constants.BypassFiltersEventId,
"AccessReports Check - UserId: {userId} OrgId: {orgId} DeviceType: {deviceType}",
_currentContext.UserId, orgId, _currentContext.DeviceType);
throw new NotFoundException();
}
var accessDetails = await GetMemberAccessDetails(new MemberAccessReportRequest { OrganizationId = orgId });
_logger.LogInformation(Constants.BypassFiltersEventId,
"MemberAccessReportQuery starts - UserId: {userId} OrgId: {orgId} DeviceType: {deviceType}",
_currentContext.UserId, orgId, _currentContext.DeviceType);
var accessDetails = await _memberAccessReportQuery
.GetMemberAccessReportsAsync(new MemberAccessReportRequest { OrganizationId = orgId });
var responses = accessDetails.Select(x => new MemberAccessDetailReportResponseModel(x));
return responses;
}
/// <summary>
/// Contains the organization member info, the cipher ids associated with the member,
/// and details on their collections, groups, and permissions
/// </summary>
/// <param name="request">Request parameters</param>
/// <returns>
/// List of a user's permissions at a group and collection level as well as the number of ciphers
/// associated with that group/collection
/// </returns>
private async Task<IEnumerable<MemberAccessReportDetail>> GetMemberAccessDetails(
MemberAccessReportRequest request)
{
var accessDetails = await _memberAccessReportQuery.GetMemberAccessReportsAsync(request);
return accessDetails;
}
/// <summary>
/// Gets the risk insights report details from the risk insights query. Associates a user to their cipher ids
/// </summary>

View File

@ -7,25 +7,40 @@ using Bit.Core.Dirt.Reports.ReportFeatures.OrganizationReportMembers.Interfaces;
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
using Bit.Core.Dirt.Reports.Repositories;
using Bit.Core.Services;
using Microsoft.Extensions.Logging;
namespace Bit.Core.Dirt.Reports.ReportFeatures;
public class MemberAccessReportQuery(
IOrganizationMemberBaseDetailRepository organizationMemberBaseDetailRepository,
ITwoFactorIsEnabledQuery twoFactorIsEnabledQuery,
IApplicationCacheService applicationCacheService) : IMemberAccessReportQuery
IApplicationCacheService applicationCacheService,
ILogger<MemberAccessReportQuery> logger) : IMemberAccessReportQuery
{
public async Task<IEnumerable<MemberAccessReportDetail>> GetMemberAccessReportsAsync(
MemberAccessReportRequest request)
{
logger.LogInformation(Constants.BypassFiltersEventId, "Starting MemberAccessReport generation for OrganizationId: {OrganizationId}", request.OrganizationId);
var baseDetails =
await organizationMemberBaseDetailRepository.GetOrganizationMemberBaseDetailsByOrganizationId(
request.OrganizationId);
logger.LogInformation(Constants.BypassFiltersEventId, "Retrieved {BaseDetailsCount} base details for OrganizationId: {OrganizationId}",
baseDetails.Count(), request.OrganizationId);
var orgUsers = baseDetails.Select(x => x.UserGuid.GetValueOrDefault()).Distinct();
var orgUsersCount = orgUsers.Count();
logger.LogInformation(Constants.BypassFiltersEventId, "Found {UniqueUsersCount} unique users for OrganizationId: {OrganizationId}",
orgUsersCount, request.OrganizationId);
var orgUsersTwoFactorEnabled = await twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(orgUsers);
logger.LogInformation(Constants.BypassFiltersEventId, "Retrieved two-factor status for {UsersCount} users for OrganizationId: {OrganizationId}",
orgUsersTwoFactorEnabled.Count(), request.OrganizationId);
var orgAbility = await applicationCacheService.GetOrganizationAbilityAsync(request.OrganizationId);
logger.LogInformation(Constants.BypassFiltersEventId, "Retrieved organization ability (UseResetPassword: {UseResetPassword}) for OrganizationId: {OrganizationId}",
orgAbility?.UseResetPassword, request.OrganizationId);
var accessDetails = baseDetails
.GroupBy(b => new
@ -62,6 +77,10 @@ public class MemberAccessReportQuery(
CipherIds = g.Select(c => c.CipherId)
});
var accessDetailsCount = accessDetails.Count();
logger.LogInformation(Constants.BypassFiltersEventId, "Completed MemberAccessReport generation for OrganizationId: {OrganizationId}. Generated {AccessDetailsCount} access detail records",
request.OrganizationId, accessDetailsCount);
return accessDetails;
}
}