mirror of
https://github.com/bitwarden/server
synced 2026-01-31 00:33:17 +00:00
* Initial implementation of new policy query * Remove unused using * Adjusts method name to better match repository method * Correct namespace * Initial refactor of policy loading * Add xml doc, incorporate shim data model * Updates usages to reflect new shim model * Prune extranneous data from policy detail response model, format code * Fix broken test, delete inapplicable test * Adds test cases covering query * Adjust codebase to use new PolicyQueryçˆ * Format code * Fix incorrect mock on test * Fix formatting * Adjust method name * More naming adjustments * Add PolicyData constructor, update test usages * Rename PolicyData -> PolicyStatus * Remove unused using
79 lines
3.0 KiB
C#
79 lines
3.0 KiB
C#
using Bit.Core.AdminConsole.Enums;
|
|
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
|
using Bit.Core.Entities;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Exceptions;
|
|
using Bit.Core.Platform.Push;
|
|
using Bit.Core.Repositories;
|
|
using Bit.Core.Services;
|
|
using Microsoft.AspNetCore.Identity;
|
|
|
|
namespace Bit.Core.AdminConsole.OrganizationFeatures.AccountRecovery;
|
|
|
|
public class AdminRecoverAccountCommand(IOrganizationRepository organizationRepository,
|
|
IPolicyQuery policyQuery,
|
|
IUserRepository userRepository,
|
|
IMailService mailService,
|
|
IEventService eventService,
|
|
IPushNotificationService pushNotificationService,
|
|
IUserService userService,
|
|
TimeProvider timeProvider) : IAdminRecoverAccountCommand
|
|
{
|
|
public async Task<IdentityResult> RecoverAccountAsync(Guid orgId,
|
|
OrganizationUser organizationUser, string newMasterPassword, string key)
|
|
{
|
|
// Org must be able to use reset password
|
|
var org = await organizationRepository.GetByIdAsync(orgId);
|
|
if (org == null || !org.UseResetPassword)
|
|
{
|
|
throw new BadRequestException("Organization does not allow password reset.");
|
|
}
|
|
|
|
// Enterprise policy must be enabled
|
|
var resetPasswordPolicy = await policyQuery.RunAsync(orgId, PolicyType.ResetPassword);
|
|
if (!resetPasswordPolicy.Enabled)
|
|
{
|
|
throw new BadRequestException("Organization does not have the password reset policy enabled.");
|
|
}
|
|
|
|
// Org User must be confirmed and have a ResetPasswordKey
|
|
if (organizationUser == null ||
|
|
organizationUser.Status != OrganizationUserStatusType.Confirmed ||
|
|
organizationUser.OrganizationId != orgId ||
|
|
string.IsNullOrEmpty(organizationUser.ResetPasswordKey) ||
|
|
!organizationUser.UserId.HasValue)
|
|
{
|
|
throw new BadRequestException("Organization User not valid");
|
|
}
|
|
|
|
var user = await userService.GetUserByIdAsync(organizationUser.UserId.Value);
|
|
if (user == null)
|
|
{
|
|
throw new NotFoundException();
|
|
}
|
|
|
|
if (user.UsesKeyConnector)
|
|
{
|
|
throw new BadRequestException("Cannot reset password of a user with Key Connector.");
|
|
}
|
|
|
|
var result = await userService.UpdatePasswordHash(user, newMasterPassword);
|
|
if (!result.Succeeded)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
user.RevisionDate = user.AccountRevisionDate = timeProvider.GetUtcNow().UtcDateTime;
|
|
user.LastPasswordChangeDate = user.RevisionDate;
|
|
user.ForcePasswordReset = true;
|
|
user.Key = key;
|
|
|
|
await userRepository.ReplaceAsync(user);
|
|
await mailService.SendAdminResetPasswordEmailAsync(user.Email, user.Name, org.DisplayName());
|
|
await eventService.LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_AdminResetPassword);
|
|
await pushNotificationService.PushLogOutAsync(user.Id);
|
|
|
|
return IdentityResult.Success;
|
|
}
|
|
}
|