1
0
mirror of https://github.com/bitwarden/server synced 2026-01-26 14:23:21 +00:00

refactor(emergency-access) [PM-29584]: Move Emergency Access to Auth/UserFeatures.

This commit is contained in:
enmande
2025-12-30 17:38:23 -05:00
parent f68e2797b8
commit e238bb0a8c
8 changed files with 20 additions and 21 deletions

View File

@@ -7,7 +7,7 @@ using Bit.Api.Auth.Models.Request;
using Bit.Api.Auth.Models.Response;
using Bit.Api.Models.Response;
using Bit.Api.Vault.Models.Response;
using Bit.Core.Auth.Services;
using Bit.Core.Auth.UserFeatures.EmergencyAccess;
using Bit.Core.Exceptions;
using Bit.Core.Repositories;
using Bit.Core.Services;

View File

@@ -1,7 +1,7 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using Bit.Core.Auth.Services;
using Bit.Core.Auth.UserFeatures.EmergencyAccess;
using Bit.Core.Jobs;
using Quartz;

View File

@@ -1,7 +1,7 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using Bit.Core.Auth.Services;
using Bit.Core.Auth.UserFeatures.EmergencyAccess;
using Bit.Core.Jobs;
using Quartz;

View File

@@ -4,7 +4,6 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Auth.Entities;
using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Models.Business.Tokenables;
using Bit.Core.Auth.Models.Data;
@@ -19,7 +18,7 @@ using Bit.Core.Vault.Models.Data;
using Bit.Core.Vault.Repositories;
using Bit.Core.Vault.Services;
namespace Bit.Core.Auth.Services;
namespace Bit.Core.Auth.UserFeatures.EmergencyAccess;
public class EmergencyAccessService : IEmergencyAccessService
{
@@ -61,7 +60,7 @@ public class EmergencyAccessService : IEmergencyAccessService
_removeOrganizationUserCommand = removeOrganizationUserCommand;
}
public async Task<EmergencyAccess> InviteAsync(User grantorUser, string emergencyContactEmail, EmergencyAccessType accessType, int waitTime)
public async Task<Entities.EmergencyAccess> InviteAsync(User grantorUser, string emergencyContactEmail, EmergencyAccessType accessType, int waitTime)
{
if (!await _userService.CanAccessPremium(grantorUser))
{
@@ -73,7 +72,7 @@ public class EmergencyAccessService : IEmergencyAccessService
throw new BadRequestException("You cannot use Emergency Access Takeover because you are using Key Connector.");
}
var emergencyAccess = new EmergencyAccess
var emergencyAccess = new Entities.EmergencyAccess
{
GrantorId = grantorUser.Id,
Email = emergencyContactEmail.ToLowerInvariant(),
@@ -113,7 +112,7 @@ public class EmergencyAccessService : IEmergencyAccessService
await SendInviteAsync(emergencyAccess, NameOrEmail(grantorUser));
}
public async Task<EmergencyAccess> AcceptUserAsync(Guid emergencyAccessId, User granteeUser, string token, IUserService userService)
public async Task<Entities.EmergencyAccess> AcceptUserAsync(Guid emergencyAccessId, User granteeUser, string token, IUserService userService)
{
var emergencyAccess = await _emergencyAccessRepository.GetByIdAsync(emergencyAccessId);
if (emergencyAccess == null)
@@ -175,7 +174,7 @@ public class EmergencyAccessService : IEmergencyAccessService
await _emergencyAccessRepository.DeleteAsync(emergencyAccess);
}
public async Task<EmergencyAccess> ConfirmUserAsync(Guid emergencyAccessId, string key, Guid grantorId)
public async Task<Entities.EmergencyAccess> ConfirmUserAsync(Guid emergencyAccessId, string key, Guid grantorId)
{
var emergencyAccess = await _emergencyAccessRepository.GetByIdAsync(emergencyAccessId);
if (emergencyAccess == null || emergencyAccess.Status != EmergencyAccessStatusType.Accepted ||
@@ -201,7 +200,7 @@ public class EmergencyAccessService : IEmergencyAccessService
return emergencyAccess;
}
public async Task SaveAsync(EmergencyAccess emergencyAccess, User grantorUser)
public async Task SaveAsync(Entities.EmergencyAccess emergencyAccess, User grantorUser)
{
if (!await _userService.CanAccessPremium(grantorUser))
{
@@ -311,7 +310,7 @@ public class EmergencyAccessService : IEmergencyAccessService
}
// TODO PM-21687: rename this to something like InitiateRecoveryTakeoverAsync
public async Task<(EmergencyAccess, User)> TakeoverAsync(Guid emergencyAccessId, User granteeUser)
public async Task<(Entities.EmergencyAccess, User)> TakeoverAsync(Guid emergencyAccessId, User granteeUser)
{
var emergencyAccess = await _emergencyAccessRepository.GetByIdAsync(emergencyAccessId);
@@ -429,7 +428,7 @@ public class EmergencyAccessService : IEmergencyAccessService
return await _cipherService.GetAttachmentDownloadDataAsync(cipher, attachmentId);
}
private async Task SendInviteAsync(EmergencyAccess emergencyAccess, string invitingUsersName)
private async Task SendInviteAsync(Entities.EmergencyAccess emergencyAccess, string invitingUsersName)
{
var token = _dataProtectorTokenizer.Protect(new EmergencyAccessInviteTokenable(emergencyAccess, _globalSettings.OrganizationInviteExpirationHours));
await _mailService.SendEmergencyAccessInviteEmailAsync(emergencyAccess, invitingUsersName, token);
@@ -449,7 +448,7 @@ public class EmergencyAccessService : IEmergencyAccessService
*/
//TODO PM-21687: this IsValidRequest() checks the validity based on the granteeUser. There should be a complementary method for the grantorUser
private static bool IsValidRequest(
EmergencyAccess availableAccess,
Entities.EmergencyAccess availableAccess,
User requestingUser,
EmergencyAccessType requestedAccessType)
{

View File

@@ -1,5 +1,4 @@
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Auth.Entities;
using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Models.Data;
using Bit.Core.Entities;
@@ -7,7 +6,7 @@ using Bit.Core.Enums;
using Bit.Core.Services;
using Bit.Core.Vault.Models.Data;
namespace Bit.Core.Auth.Services;
namespace Bit.Core.Auth.UserFeatures.EmergencyAccess;
public interface IEmergencyAccessService
{
@@ -20,7 +19,7 @@ public interface IEmergencyAccessService
/// <param name="accessType">Type of emergency access allowed to the emergency contact</param>
/// <param name="waitTime">The amount of time to pass before the invite is auto confirmed</param>
/// <returns>a new Emergency Access object</returns>
Task<EmergencyAccess> InviteAsync(User grantorUser, string emergencyContactEmail, EmergencyAccessType accessType, int waitTime);
Task<Entities.EmergencyAccess> InviteAsync(User grantorUser, string emergencyContactEmail, EmergencyAccessType accessType, int waitTime);
/// <summary>
/// Sends an invite to the emergency contact associated with the emergency access id.
/// </summary>
@@ -37,7 +36,7 @@ public interface IEmergencyAccessService
/// <param name="token">the tokenable that was sent via email</param>
/// <param name="userService">service dependency</param>
/// <returns>void</returns>
Task<EmergencyAccess> AcceptUserAsync(Guid emergencyAccessId, User granteeUser, string token, IUserService userService);
Task<Entities.EmergencyAccess> AcceptUserAsync(Guid emergencyAccessId, User granteeUser, string token, IUserService userService);
/// <summary>
/// The creator of the emergency access request can delete the request.
/// </summary>
@@ -53,7 +52,7 @@ public interface IEmergencyAccessService
/// <param name="key">The grantor user key encrypted by the grantee public key; grantee.PubicKey(grantor.User.Key)</param>
/// <param name="grantorId">Id of grantor user</param>
/// <returns>emergency access object associated with the Id passed in</returns>
Task<EmergencyAccess> ConfirmUserAsync(Guid emergencyAccessId, string key, Guid grantorId);
Task<Entities.EmergencyAccess> ConfirmUserAsync(Guid emergencyAccessId, string key, Guid grantorId);
/// <summary>
/// Fetches an emergency access object. The grantor user must own the object being fetched.
/// </summary>
@@ -67,7 +66,7 @@ public interface IEmergencyAccessService
/// <param name="emergencyAccess">emergency access entity being updated</param>
/// <param name="grantorUser">grantor user</param>
/// <returns>void</returns>
Task SaveAsync(EmergencyAccess emergencyAccess, User grantorUser);
Task SaveAsync(Entities.EmergencyAccess emergencyAccess, User grantorUser);
/// <summary>
/// Initiates the recovery process. For either Takeover or view. Will send an email to the Grantor User notifying of the initiation.
/// </summary>
@@ -107,7 +106,7 @@ public interface IEmergencyAccessService
/// <param name="emergencyAccessId">Id of entity being accessed</param>
/// <param name="granteeUser">grantee user of the emergency access entity</param>
/// <returns>emergency access entity and the grantorUser</returns>
Task<(EmergencyAccess, User)> TakeoverAsync(Guid emergencyAccessId, User granteeUser);
Task<(Entities.EmergencyAccess, User)> TakeoverAsync(Guid emergencyAccessId, User granteeUser);
/// <summary>
/// Updates the grantor's password hash and updates the key for the EmergencyAccess entity.
/// </summary>

View File

@@ -22,6 +22,7 @@ using Bit.Core.Auth.Repositories;
using Bit.Core.Auth.Services;
using Bit.Core.Auth.Services.Implementations;
using Bit.Core.Auth.UserFeatures;
using Bit.Core.Auth.UserFeatures.EmergencyAccess;
using Bit.Core.Auth.UserFeatures.PasswordValidation;
using Bit.Core.Billing.Services;
using Bit.Core.Billing.Services.Implementations;

View File

@@ -5,7 +5,7 @@ using Bit.Core.Auth.Enums;
using Bit.Core.Auth.Models;
using Bit.Core.Auth.Models.Business.Tokenables;
using Bit.Core.Auth.Models.Data;
using Bit.Core.Auth.Services;
using Bit.Core.Auth.UserFeatures.EmergencyAccess;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Exceptions;