1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-17 07:30:59 -05:00

[PM-20092] Refactor OrganizationUsersController Get to return account recovery users (#5756)

* wip

* wip

* add dict conversion to Get

* wip

* clean up

* clean up

* continue refactor

* Fix feature flag

Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>

---------

Co-authored-by: Rui Tomé <108268980+r-tome@users.noreply.github.com>
This commit is contained in:
Brandon Treston
2025-05-06 13:45:05 -04:00
committed by GitHub
parent 10fcff58b2
commit 28467fc8f6
6 changed files with 137 additions and 3 deletions

View File

@ -6,4 +6,8 @@ namespace Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
public interface IOrganizationUserUserDetailsQuery
{
Task<IEnumerable<OrganizationUserUserDetails>> GetOrganizationUserUserDetails(OrganizationUserUserDetailsQueryRequest request);
Task<IEnumerable<(OrganizationUserUserDetails OrgUser, bool TwoFactorEnabled, bool ClaimedByOrganization)>> Get(OrganizationUserUserDetailsQueryRequest request);
Task<IEnumerable<(OrganizationUserUserDetails OrgUser, bool TwoFactorEnabled, bool ClaimedByOrganization)>> GetAccountRecoveryEnrolledUsers(OrganizationUserUserDetailsQueryRequest request);
}

View File

@ -1,5 +1,9 @@
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
using Bit.Core.Enums;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Utilities;
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Requests;
@ -9,12 +13,21 @@ namespace Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
public class OrganizationUserUserDetailsQuery : IOrganizationUserUserDetailsQuery
{
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ITwoFactorIsEnabledQuery _twoFactorIsEnabledQuery;
private readonly IFeatureService _featureService;
private readonly IGetOrganizationUsersClaimedStatusQuery _getOrganizationUsersClaimedStatusQuery;
public OrganizationUserUserDetailsQuery(
IOrganizationUserRepository organizationUserRepository
IOrganizationUserRepository organizationUserRepository,
ITwoFactorIsEnabledQuery twoFactorIsEnabledQuery,
IFeatureService featureService,
IGetOrganizationUsersClaimedStatusQuery getOrganizationUsersClaimedStatusQuery
)
{
_organizationUserRepository = organizationUserRepository;
_twoFactorIsEnabledQuery = twoFactorIsEnabledQuery;
_featureService = featureService;
_getOrganizationUsersClaimedStatusQuery = getOrganizationUsersClaimedStatusQuery;
}
/// <summary>
@ -37,4 +50,42 @@ public class OrganizationUserUserDetailsQuery : IOrganizationUserUserDetailsQuer
return o;
});
}
/// <summary>
/// Get the organization user user details, two factor enabled status, and
/// claimed status for the provided request.
/// </summary>
/// <param name="request">Request details for the query</param>
/// <returns>List of OrganizationUserUserDetails</returns>
public async Task<IEnumerable<(OrganizationUserUserDetails OrgUser, bool TwoFactorEnabled, bool ClaimedByOrganization)>> Get(OrganizationUserUserDetailsQueryRequest request)
{
var organizationUsers = await GetOrganizationUserUserDetails(request);
var organizationUsersTwoFactorEnabled = (await _twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(organizationUsers)).ToDictionary(u => u.user.Id);
var organizationUsersClaimedStatus = await _getOrganizationUsersClaimedStatusQuery.GetUsersOrganizationClaimedStatusAsync(request.OrganizationId, organizationUsers.Select(o => o.Id));
var responses = organizationUsers.Select(o => (o, organizationUsersTwoFactorEnabled[o.Id].twoFactorIsEnabled, organizationUsersClaimedStatus[o.Id]));
return responses;
}
/// <summary>
/// Get the organization users user details, two factor enabled status, and
/// claimed status for confirmed users that are enrolled in account recovery
/// </summary>
/// <param name="request">Request details for the query</param>
/// <returns>List of OrganizationUserUserDetails</returns>
public async Task<IEnumerable<(OrganizationUserUserDetails OrgUser, bool TwoFactorEnabled, bool ClaimedByOrganization)>> GetAccountRecoveryEnrolledUsers(OrganizationUserUserDetailsQueryRequest request)
{
var organizationUsers = (await GetOrganizationUserUserDetails(request))
.Where(o => o.Status.Equals(OrganizationUserStatusType.Confirmed) && o.UsesKeyConnector == false && !String.IsNullOrEmpty(o.ResetPasswordKey));
var organizationUsersTwoFactorEnabled = (await _twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(organizationUsers)).ToDictionary(u => u.user.Id);
var organizationUsersClaimedStatus = await _getOrganizationUsersClaimedStatusQuery.GetUsersOrganizationClaimedStatusAsync(request.OrganizationId, organizationUsers.Select(o => o.Id));
var responses = organizationUsers
.Select(o => (o, organizationUsersTwoFactorEnabled[o.Id].twoFactorIsEnabled, organizationUsersClaimedStatus[o.Id]));
return responses;
}
}

View File

@ -205,6 +205,7 @@ public static class FeatureFlagKeys
public const string DesktopCipherForms = "pm-18520-desktop-cipher-forms";
public const string PM19941MigrateCipherDomainToSdk = "pm-19941-migrate-cipher-domain-to-sdk";
public const string EndUserNotifications = "pm-10609-end-user-notifications";
public const string SeparateCustomRolePermissions = "pm-19917-separate-custom-role-permissions";
public const string PhishingDetection = "phishing-detection";
public static List<string> GetAllKeys()