mirror of
https://github.com/bitwarden/server
synced 2026-02-25 17:03:22 +00:00
[PM-21179] Add interface to check if user is enrolled in account recovery (#6993)
* Add validation for reset password key and account recovery enrollment in OrganizationUser * Update admin approval logic to check account recovery enrollment and add tests for reset password key validation * Enhance UserService validation to include account recovery enrollment and add unit test for empty or whitespace reset password key handling * Refactor OrganizationUserUserDetailsQuery to validate reset password keys and add unit tests for filtering out invalid keys * Update AdminRecoverAccountCommand to validate account recovery enrollment and adjust tests for whitespace reset password keys * Enhance OrganizationUserRotationValidator to validate reset password keys, including filtering out whitespace-only keys, and add corresponding unit tests for validation logic. * Refactor OrganizationUserUserDetailsQueryTests to remove unnecessary whitespace-only test cases for account recovery key validation. * Refactor MemberResponseModel to use OrganizationUser's validation method for ResetPasswordEnrolled status and update corresponding unit test for clarity. * Refactor OrganizationUsersController and response models to utilize OrganizationUser's validation method for ResetPasswordKey, ensuring consistent validation across the application. Add unit tests for OrganizationUser to verify key validation logic. * Update OrganizationUserRotationValidator to handle null reset password keys and adjust tests for client-side bug. Add comments for future migration after resolving PM-31001. * Fix whitespace issue in UserServiceTests.cs by removing BOM character from the file header.
This commit is contained in:
@@ -81,6 +81,17 @@ public class OrganizationUser : ITableObject<Guid>, IExternal, IOrganizationUser
|
||||
/// </summary>
|
||||
public bool AccessSecretsManager { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the given reset password key is non-null and non-whitespace.
|
||||
/// </summary>
|
||||
public static bool IsValidResetPasswordKey(string? resetPasswordKey)
|
||||
=> !string.IsNullOrWhiteSpace(resetPasswordKey);
|
||||
|
||||
/// <summary>
|
||||
/// Whether this organization user is enrolled in account recovery.
|
||||
/// </summary>
|
||||
public bool IsEnrolledInAccountRecovery() => IsValidResetPasswordKey(ResetPasswordKey);
|
||||
|
||||
public void SetNewId()
|
||||
{
|
||||
Id = CoreHelpers.GenerateComb();
|
||||
|
||||
@@ -40,7 +40,7 @@ public class AdminRecoverAccountCommand(IOrganizationRepository organizationRepo
|
||||
if (organizationUser == null ||
|
||||
organizationUser.Status != OrganizationUserStatusType.Confirmed ||
|
||||
organizationUser.OrganizationId != orgId ||
|
||||
string.IsNullOrEmpty(organizationUser.ResetPasswordKey) ||
|
||||
!organizationUser.IsEnrolledInAccountRecovery() ||
|
||||
!organizationUser.UserId.HasValue)
|
||||
{
|
||||
throw new BadRequestException("Organization User not valid");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Repositories;
|
||||
@@ -96,7 +97,8 @@ public class OrganizationUserUserDetailsQuery : IOrganizationUserUserDetailsQuer
|
||||
{
|
||||
var organizationUsers = (await _organizationUserRepository
|
||||
.GetManyDetailsByOrganizationAsync_vNext(request.OrganizationId, request.IncludeGroups, request.IncludeCollections))
|
||||
.Where(o => o.Status.Equals(OrganizationUserStatusType.Confirmed) && o.UsesKeyConnector == false && !String.IsNullOrEmpty(o.ResetPasswordKey))
|
||||
.Where(o => o.Status.Equals(OrganizationUserStatusType.Confirmed) && o.UsesKeyConnector == false &&
|
||||
OrganizationUser.IsValidResetPasswordKey(o.ResetPasswordKey))
|
||||
.ToArray();
|
||||
|
||||
var twoFactorTask = _twoFactorIsEnabledQuery.TwoFactorIsEnabledAsync(organizationUsers);
|
||||
|
||||
@@ -6,6 +6,7 @@ using Bit.Core.Dirt.Reports.Models.Data;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.OrganizationReportMembers.Interfaces;
|
||||
using Bit.Core.Dirt.Reports.ReportFeatures.Requests;
|
||||
using Bit.Core.Dirt.Reports.Repositories;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Services;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
@@ -65,7 +66,7 @@ public class MemberAccessReportQuery(
|
||||
UserName = g.Key.UserName,
|
||||
Email = g.Key.Email,
|
||||
TwoFactorEnabled = orgUsersTwoFactorEnabled.FirstOrDefault(x => x.userId == g.Key.UserGuid).twoFactorIsEnabled,
|
||||
AccountRecoveryEnabled = !string.IsNullOrWhiteSpace(g.Key.ResetPasswordKey) && orgAbility.UseResetPassword,
|
||||
AccountRecoveryEnabled = OrganizationUser.IsValidResetPasswordKey(g.Key.ResetPasswordKey) && orgAbility.UseResetPassword,
|
||||
UsesKeyConnector = g.Key.UsesKeyConnector,
|
||||
GroupId = g.Key.GroupId,
|
||||
GroupName = g.Key.GroupName,
|
||||
|
||||
@@ -581,7 +581,8 @@ public class UserService : UserManager<User>, IUserService
|
||||
// Org User must be confirmed and have a ResetPasswordKey
|
||||
var orgUser = await _organizationUserRepository.GetByIdAsync(id);
|
||||
if (orgUser == null || orgUser.Status != OrganizationUserStatusType.Confirmed ||
|
||||
orgUser.OrganizationId != orgId || string.IsNullOrEmpty(orgUser.ResetPasswordKey) ||
|
||||
orgUser.OrganizationId != orgId ||
|
||||
!orgUser.IsEnrolledInAccountRecovery() ||
|
||||
!orgUser.UserId.HasValue)
|
||||
{
|
||||
throw new BadRequestException("Organization User not valid");
|
||||
|
||||
Reference in New Issue
Block a user