mirror of
https://github.com/bitwarden/server.git
synced 2025-12-11 03:37:11 -06:00
fix(user-decryption-options) [PM-23174]: ManageAccountRecovery Permission Forces Master Password Set (#6230)
* fix(user-decryption-options): ManageAccountRecovery Permission Forces MP Set - Update tests, add OrganizationUser fixture customization for Permissions * fix(user-decryption-options): ManageAccountRecovery Permission Forces MP Set - Update hasManageResetPasswordPermission evaluation. * PM-23174 - Add TODO for endpoint per sync discussion with Dave * fix(user-decryption-options): ManageAccountRecovery Permission Forces MP Set - Clean up comments. * fix(user-decryption-options): ManageAccountRecovery Permission Forces MP Set - Remove an outdated comment. * fix(user-decryption-options): ManageAccountRecovery Permission Forces MP Set - Elaborate on comments around Organization User invite-time evaluation. * fix(user-decryption-options): Use currentContext for Provider relationships, update comments, and feature flag the change. * fix(user-decryption-options): Update test suite and provide additional comments for future flag removal. --------- Co-authored-by: Jared Snider <jsnider@bitwarden.com>
This commit is contained in:
parent
222436589c
commit
6466c00acd
@ -144,6 +144,8 @@ public static class FeatureFlagKeys
|
|||||||
public const string Otp6Digits = "pm-18612-otp-6-digits";
|
public const string Otp6Digits = "pm-18612-otp-6-digits";
|
||||||
public const string FailedTwoFactorEmail = "pm-24425-send-2fa-failed-email";
|
public const string FailedTwoFactorEmail = "pm-24425-send-2fa-failed-email";
|
||||||
public const string DisableAlternateLoginMethods = "pm-22110-disable-alternate-login-methods";
|
public const string DisableAlternateLoginMethods = "pm-22110-disable-alternate-login-methods";
|
||||||
|
public const string PM23174ManageAccountRecoveryPermissionDrivesTheNeedToSetMasterPassword =
|
||||||
|
"pm-23174-manage-account-recovery-permission-drives-the-need-to-set-master-password";
|
||||||
|
|
||||||
/* Autofill Team */
|
/* Autofill Team */
|
||||||
public const string IdpAutoSubmitLogin = "idp-auto-submit-login";
|
public const string IdpAutoSubmitLogin = "idp-auto-submit-login";
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Bit.Core.Auth.Entities;
|
using Bit.Core;
|
||||||
|
using Bit.Core.Auth.Entities;
|
||||||
using Bit.Core.Auth.Enums;
|
using Bit.Core.Auth.Enums;
|
||||||
using Bit.Core.Auth.Models.Api.Response;
|
using Bit.Core.Auth.Models.Api.Response;
|
||||||
using Bit.Core.Auth.Utilities;
|
using Bit.Core.Auth.Utilities;
|
||||||
@ -7,6 +8,7 @@ using Bit.Core.Entities;
|
|||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
using Bit.Core.KeyManagement.Models.Response;
|
using Bit.Core.KeyManagement.Models.Response;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Bit.Identity.Utilities;
|
using Bit.Identity.Utilities;
|
||||||
|
|
||||||
@ -24,6 +26,7 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder
|
|||||||
private readonly IDeviceRepository _deviceRepository;
|
private readonly IDeviceRepository _deviceRepository;
|
||||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||||
private readonly ILoginApprovingClientTypes _loginApprovingClientTypes;
|
private readonly ILoginApprovingClientTypes _loginApprovingClientTypes;
|
||||||
|
private readonly IFeatureService _featureService;
|
||||||
|
|
||||||
private UserDecryptionOptions _options = new UserDecryptionOptions();
|
private UserDecryptionOptions _options = new UserDecryptionOptions();
|
||||||
private User _user = null!;
|
private User _user = null!;
|
||||||
@ -34,13 +37,15 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder
|
|||||||
ICurrentContext currentContext,
|
ICurrentContext currentContext,
|
||||||
IDeviceRepository deviceRepository,
|
IDeviceRepository deviceRepository,
|
||||||
IOrganizationUserRepository organizationUserRepository,
|
IOrganizationUserRepository organizationUserRepository,
|
||||||
ILoginApprovingClientTypes loginApprovingClientTypes
|
ILoginApprovingClientTypes loginApprovingClientTypes,
|
||||||
|
IFeatureService featureService
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
_currentContext = currentContext;
|
_currentContext = currentContext;
|
||||||
_deviceRepository = deviceRepository;
|
_deviceRepository = deviceRepository;
|
||||||
_organizationUserRepository = organizationUserRepository;
|
_organizationUserRepository = organizationUserRepository;
|
||||||
_loginApprovingClientTypes = loginApprovingClientTypes;
|
_loginApprovingClientTypes = loginApprovingClientTypes;
|
||||||
|
_featureService = featureService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IUserDecryptionOptionsBuilder ForUser(User user)
|
public IUserDecryptionOptionsBuilder ForUser(User user)
|
||||||
@ -65,8 +70,10 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder
|
|||||||
{
|
{
|
||||||
if (credential.GetPrfStatus() == WebAuthnPrfStatus.Enabled)
|
if (credential.GetPrfStatus() == WebAuthnPrfStatus.Enabled)
|
||||||
{
|
{
|
||||||
_options.WebAuthnPrfOption = new WebAuthnPrfDecryptionOption(credential.EncryptedPrivateKey, credential.EncryptedUserKey);
|
_options.WebAuthnPrfOption =
|
||||||
|
new WebAuthnPrfDecryptionOption(credential.EncryptedPrivateKey, credential.EncryptedUserKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +81,7 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder
|
|||||||
{
|
{
|
||||||
BuildMasterPasswordUnlock();
|
BuildMasterPasswordUnlock();
|
||||||
BuildKeyConnectorOptions();
|
BuildKeyConnectorOptions();
|
||||||
await BuildTrustedDeviceOptions();
|
await BuildTrustedDeviceOptionsAsync();
|
||||||
|
|
||||||
return _options;
|
return _options;
|
||||||
}
|
}
|
||||||
@ -87,13 +94,14 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
var ssoConfigurationData = _ssoConfig.GetData();
|
var ssoConfigurationData = _ssoConfig.GetData();
|
||||||
if (ssoConfigurationData is { MemberDecryptionType: MemberDecryptionType.KeyConnector } && !string.IsNullOrEmpty(ssoConfigurationData.KeyConnectorUrl))
|
if (ssoConfigurationData is { MemberDecryptionType: MemberDecryptionType.KeyConnector } &&
|
||||||
|
!string.IsNullOrEmpty(ssoConfigurationData.KeyConnectorUrl))
|
||||||
{
|
{
|
||||||
_options.KeyConnectorOption = new KeyConnectorUserDecryptionOption(ssoConfigurationData.KeyConnectorUrl);
|
_options.KeyConnectorOption = new KeyConnectorUserDecryptionOption(ssoConfigurationData.KeyConnectorUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task BuildTrustedDeviceOptions()
|
private async Task BuildTrustedDeviceOptionsAsync()
|
||||||
{
|
{
|
||||||
// TrustedDeviceEncryption only exists for SSO, if that changes then these guards should change
|
// TrustedDeviceEncryption only exists for SSO, if that changes then these guards should change
|
||||||
if (_ssoConfig == null)
|
if (_ssoConfig == null)
|
||||||
@ -101,7 +109,8 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var isTdeActive = _ssoConfig.GetData() is { MemberDecryptionType: MemberDecryptionType.TrustedDeviceEncryption };
|
var isTdeActive = _ssoConfig.GetData() is
|
||||||
|
{ MemberDecryptionType: MemberDecryptionType.TrustedDeviceEncryption };
|
||||||
var isTdeOffboarding = !_user.HasMasterPassword() && _device != null && _device.IsTrusted() && !isTdeActive;
|
var isTdeOffboarding = !_user.HasMasterPassword() && _device != null && _device.IsTrusted() && !isTdeActive;
|
||||||
if (!isTdeActive && !isTdeOffboarding)
|
if (!isTdeActive && !isTdeOffboarding)
|
||||||
{
|
{
|
||||||
@ -120,25 +129,51 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder
|
|||||||
if (_device != null)
|
if (_device != null)
|
||||||
{
|
{
|
||||||
var allDevices = await _deviceRepository.GetManyByUserIdAsync(_user.Id);
|
var allDevices = await _deviceRepository.GetManyByUserIdAsync(_user.Id);
|
||||||
// Checks if the current user has any devices that are capable of approving login with device requests except for
|
// Checks if the current user has any devices that are capable of approving login with device requests
|
||||||
// their current device.
|
// except for their current device.
|
||||||
// NOTE: this doesn't check for if the users have configured the devices to be capable of approving requests as that is a client side setting.
|
hasLoginApprovingDevice = allDevices.Any(d =>
|
||||||
hasLoginApprovingDevice = allDevices.Any(d => d.Identifier != _device.Identifier && _loginApprovingClientTypes.TypesThatCanApprove.Contains(DeviceTypes.ToClientType(d.Type)));
|
d.Identifier != _device.Identifier &&
|
||||||
|
_loginApprovingClientTypes.TypesThatCanApprove.Contains(DeviceTypes.ToClientType(d.Type)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine if user has manage reset password permission as post sso logic requires it for forcing users with this permission to set a MP
|
// Just-in-time-provisioned users, which can include users invited to a TDE organization with SSO and granted
|
||||||
var hasManageResetPasswordPermission = false;
|
// the Admin/Owner role or Custom user role with ManageResetPassword permission, will not have claims available
|
||||||
// when a user is being created via JIT provisioning, they will not have any orgs so we can't assume we will have orgs here
|
// in context to reflect this permission if granted as part of an invite for the current organization.
|
||||||
if (_currentContext.Organizations != null && _currentContext.Organizations.Any(o => o.Id == _ssoConfig.OrganizationId))
|
// Therefore, as written today, CurrentContext will not surface those permissions for those users.
|
||||||
{
|
// In order to make this check accurate at first login for all applicable cases, we have to go back to the
|
||||||
// TDE requires single org so grabbing first org & id is fine.
|
// database record.
|
||||||
hasManageResetPasswordPermission = await _currentContext.ManageResetPassword(_ssoConfig!.OrganizationId);
|
// In the TDE flow, the users will have been JIT-provisioned at SSO callback time, and the relationship between
|
||||||
}
|
// user and organization user will have been codified.
|
||||||
|
|
||||||
// If sso configuration data is not null then I know for sure that ssoConfiguration isn't null
|
|
||||||
var organizationUser = await _organizationUserRepository.GetByOrganizationAsync(_ssoConfig.OrganizationId, _user.Id);
|
var organizationUser = await _organizationUserRepository.GetByOrganizationAsync(_ssoConfig.OrganizationId, _user.Id);
|
||||||
|
var hasManageResetPasswordPermission = false;
|
||||||
|
if (_featureService.IsEnabled(FeatureFlagKeys.PM23174ManageAccountRecoveryPermissionDrivesTheNeedToSetMasterPassword))
|
||||||
|
{
|
||||||
|
hasManageResetPasswordPermission = await EvaluateHasManageResetPasswordPermission();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: PM-26065 remove use of above feature flag from the server, and remove this branching logic, which
|
||||||
|
// has been replaced by EvaluateHasManageResetPasswordPermission.
|
||||||
|
// Determine if user has manage reset password permission as post sso logic requires it for forcing users with this permission to set a MP.
|
||||||
|
// When removing feature flags, please also see notes and removals intended for test suite in
|
||||||
|
// Build_WhenManageResetPasswordPermissions_ShouldReturnHasManageResetPasswordPermissionTrue.
|
||||||
|
|
||||||
|
// when a user is being created via JIT provisioning, they will not have any orgs so we can't assume we will have orgs here
|
||||||
|
if (_currentContext.Organizations != null && _currentContext.Organizations.Any(o => o.Id == _ssoConfig.OrganizationId))
|
||||||
|
{
|
||||||
|
// TDE requires single org so grabbing first org & id is fine.
|
||||||
|
hasManageResetPasswordPermission = await _currentContext.ManageResetPassword(_ssoConfig!.OrganizationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If sso configuration data is not null then I know for sure that ssoConfiguration isn't null
|
||||||
|
|
||||||
|
// NOTE: Commented from original impl because the organization user repository call has been hoisted to support
|
||||||
|
// branching paths through flagging.
|
||||||
|
//organizationUser = await _organizationUserRepository.GetByOrganizationAsync(_ssoConfig.OrganizationId, _user.Id);
|
||||||
|
|
||||||
|
hasManageResetPasswordPermission |= organizationUser != null && (organizationUser.Type == OrganizationUserType.Owner || organizationUser.Type == OrganizationUserType.Admin);
|
||||||
|
}
|
||||||
|
|
||||||
hasManageResetPasswordPermission |= organizationUser != null && (organizationUser.Type == OrganizationUserType.Owner || organizationUser.Type == OrganizationUserType.Admin);
|
|
||||||
// They are only able to be approved by an admin if they have enrolled is reset password
|
// They are only able to be approved by an admin if they have enrolled is reset password
|
||||||
var hasAdminApproval = organizationUser != null && !string.IsNullOrEmpty(organizationUser.ResetPasswordKey);
|
var hasAdminApproval = organizationUser != null && !string.IsNullOrEmpty(organizationUser.ResetPasswordKey);
|
||||||
|
|
||||||
@ -149,6 +184,31 @@ public class UserDecryptionOptionsBuilder : IUserDecryptionOptionsBuilder
|
|||||||
isTdeOffboarding,
|
isTdeOffboarding,
|
||||||
encryptedPrivateKey,
|
encryptedPrivateKey,
|
||||||
encryptedUserKey);
|
encryptedUserKey);
|
||||||
|
return;
|
||||||
|
|
||||||
|
async Task<bool> EvaluateHasManageResetPasswordPermission()
|
||||||
|
{
|
||||||
|
// PM-23174
|
||||||
|
// Determine if user has manage reset password permission as post sso logic requires it for forcing users with this permission to set a MP
|
||||||
|
if (organizationUser == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var organizationUserHasResetPasswordPermission =
|
||||||
|
// The repository will pull users in all statuses, so we also need to ensure that revoked-status users do not have
|
||||||
|
// permissions sent down.
|
||||||
|
organizationUser.Status is OrganizationUserStatusType.Invited or OrganizationUserStatusType.Accepted or
|
||||||
|
OrganizationUserStatusType.Confirmed &&
|
||||||
|
// Admins and owners get ManageResetPassword functionally "for free" through their role.
|
||||||
|
(organizationUser.Type is OrganizationUserType.Admin or OrganizationUserType.Owner ||
|
||||||
|
// Custom users can have the ManagePasswordReset permission assigned directly.
|
||||||
|
organizationUser.GetPermissions() is { ManageResetPassword: true });
|
||||||
|
|
||||||
|
return organizationUserHasResetPasswordPermission ||
|
||||||
|
// A provider user for the given organization gets ManageResetPassword through that relationship.
|
||||||
|
await _currentContext.ProviderUserForOrgAsync(_ssoConfig.OrganizationId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BuildMasterPasswordUnlock()
|
private void BuildMasterPasswordUnlock()
|
||||||
|
|||||||
26
test/Identity.Test/AutoFixture/OrganizationUserFixtures.cs
Normal file
26
test/Identity.Test/AutoFixture/OrganizationUserFixtures.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using AutoFixture;
|
||||||
|
using AutoFixture.Xunit2;
|
||||||
|
using Bit.Core.Entities;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
|
using Bit.Core.Utilities;
|
||||||
|
|
||||||
|
namespace Bit.Identity.Test.AutoFixture;
|
||||||
|
|
||||||
|
internal class OrganizationUserWithDefaultPermissionsCustomization : ICustomization
|
||||||
|
{
|
||||||
|
public void Customize(IFixture fixture)
|
||||||
|
{
|
||||||
|
fixture.Customize<OrganizationUser>(composer => composer
|
||||||
|
// On OrganizationUser, Permissions can be JSON data (as string) or sometimes null.
|
||||||
|
// Entity APIs should prevent it from being anything else.
|
||||||
|
// An un-modified fixture for OrganizationUser will return a bare string Permissions{guid}
|
||||||
|
// in the member, throwing a JsonException on deserialization of a bare string.
|
||||||
|
.With(organizationUser => organizationUser.Permissions, CoreHelpers.ClassToJsonData(new Permissions())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OrganizationUserWithDefaultPermissionsAttribute : CustomizeAttribute
|
||||||
|
{
|
||||||
|
public override ICustomization GetCustomization(ParameterInfo parameter) => new OrganizationUserWithDefaultPermissionsCustomization();
|
||||||
|
}
|
||||||
@ -1,15 +1,20 @@
|
|||||||
using Bit.Core.Auth.Entities;
|
using Bit.Core;
|
||||||
|
using Bit.Core.Auth.Entities;
|
||||||
using Bit.Core.Auth.Enums;
|
using Bit.Core.Auth.Enums;
|
||||||
using Bit.Core.Auth.Models.Data;
|
using Bit.Core.Auth.Models.Data;
|
||||||
using Bit.Core.Context;
|
using Bit.Core.Context;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
using Bit.Core.Enums;
|
using Bit.Core.Enums;
|
||||||
|
using Bit.Core.Models.Data;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
|
using Bit.Core.Services;
|
||||||
using Bit.Identity.IdentityServer;
|
using Bit.Identity.IdentityServer;
|
||||||
|
using Bit.Identity.Test.AutoFixture;
|
||||||
using Bit.Identity.Utilities;
|
using Bit.Identity.Utilities;
|
||||||
using Bit.Test.Common.AutoFixture.Attributes;
|
using Bit.Test.Common.AutoFixture.Attributes;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using User = Bit.Core.Entities.User;
|
||||||
|
|
||||||
namespace Bit.Identity.Test.IdentityServer;
|
namespace Bit.Identity.Test.IdentityServer;
|
||||||
|
|
||||||
@ -20,6 +25,7 @@ public class UserDecryptionOptionsBuilderTests
|
|||||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||||
private readonly ILoginApprovingClientTypes _loginApprovingClientTypes;
|
private readonly ILoginApprovingClientTypes _loginApprovingClientTypes;
|
||||||
private readonly UserDecryptionOptionsBuilder _builder;
|
private readonly UserDecryptionOptionsBuilder _builder;
|
||||||
|
private readonly IFeatureService _featureService;
|
||||||
|
|
||||||
public UserDecryptionOptionsBuilderTests()
|
public UserDecryptionOptionsBuilderTests()
|
||||||
{
|
{
|
||||||
@ -27,7 +33,8 @@ public class UserDecryptionOptionsBuilderTests
|
|||||||
_deviceRepository = Substitute.For<IDeviceRepository>();
|
_deviceRepository = Substitute.For<IDeviceRepository>();
|
||||||
_organizationUserRepository = Substitute.For<IOrganizationUserRepository>();
|
_organizationUserRepository = Substitute.For<IOrganizationUserRepository>();
|
||||||
_loginApprovingClientTypes = Substitute.For<ILoginApprovingClientTypes>();
|
_loginApprovingClientTypes = Substitute.For<ILoginApprovingClientTypes>();
|
||||||
_builder = new UserDecryptionOptionsBuilder(_currentContext, _deviceRepository, _organizationUserRepository, _loginApprovingClientTypes);
|
_featureService = Substitute.For<IFeatureService>();
|
||||||
|
_builder = new UserDecryptionOptionsBuilder(_currentContext, _deviceRepository, _organizationUserRepository, _loginApprovingClientTypes, _featureService);
|
||||||
var user = new User();
|
var user = new User();
|
||||||
_builder.ForUser(user);
|
_builder.ForUser(user);
|
||||||
}
|
}
|
||||||
@ -220,19 +227,65 @@ public class UserDecryptionOptionsBuilderTests
|
|||||||
Assert.False(result.TrustedDeviceOption?.HasLoginApprovingDevice);
|
Assert.False(result.TrustedDeviceOption?.HasLoginApprovingDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Theory, BitAutoData]
|
/// <summary>
|
||||||
|
/// This logic has been flagged as part of PM-23174.
|
||||||
|
/// When removing the server flag, please also remove this test, and remove the FeatureService
|
||||||
|
/// dependency from this suite and the following test.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="organizationUserType"></param>
|
||||||
|
/// <param name="ssoConfig"></param>
|
||||||
|
/// <param name="configurationData"></param>
|
||||||
|
/// <param name="organization"></param>
|
||||||
|
/// <param name="organizationUser"></param>
|
||||||
|
/// <param name="user"></param>
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData(OrganizationUserType.Custom)]
|
||||||
public async Task Build_WhenManageResetPasswordPermissions_ShouldReturnHasManageResetPasswordPermissionTrue(
|
public async Task Build_WhenManageResetPasswordPermissions_ShouldReturnHasManageResetPasswordPermissionTrue(
|
||||||
|
OrganizationUserType organizationUserType,
|
||||||
SsoConfig ssoConfig,
|
SsoConfig ssoConfig,
|
||||||
SsoConfigurationData configurationData,
|
SsoConfigurationData configurationData,
|
||||||
CurrentContextOrganization organization)
|
CurrentContextOrganization organization,
|
||||||
|
[OrganizationUserWithDefaultPermissions] OrganizationUser organizationUser,
|
||||||
|
User user)
|
||||||
{
|
{
|
||||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||||
ssoConfig.Data = configurationData.Serialize();
|
ssoConfig.Data = configurationData.Serialize();
|
||||||
ssoConfig.OrganizationId = organization.Id;
|
ssoConfig.OrganizationId = organization.Id;
|
||||||
_currentContext.Organizations.Returns(new List<CurrentContextOrganization>(new CurrentContextOrganization[] { organization }));
|
_currentContext.Organizations.Returns([organization]);
|
||||||
_currentContext.ManageResetPassword(organization.Id).Returns(true);
|
_currentContext.ManageResetPassword(organization.Id).Returns(true);
|
||||||
|
organizationUser.Type = organizationUserType;
|
||||||
|
organizationUser.OrganizationId = organization.Id;
|
||||||
|
organizationUser.UserId = user.Id;
|
||||||
|
organizationUser.SetPermissions(new Permissions() { ManageResetPassword = true });
|
||||||
|
_organizationUserRepository.GetByOrganizationAsync(ssoConfig.OrganizationId, user.Id).Returns(organizationUser);
|
||||||
|
|
||||||
var result = await _builder.WithSso(ssoConfig).BuildAsync();
|
var result = await _builder.ForUser(user).WithSso(ssoConfig).BuildAsync();
|
||||||
|
|
||||||
|
Assert.True(result.TrustedDeviceOption?.HasManageResetPasswordPermission);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData(OrganizationUserType.Custom)]
|
||||||
|
public async Task Build_WhenManageResetPasswordPermissions_ShouldFetchUserFromRepositoryAndReturnHasManageResetPasswordPermissionTrue(
|
||||||
|
OrganizationUserType organizationUserType,
|
||||||
|
SsoConfig ssoConfig,
|
||||||
|
SsoConfigurationData configurationData,
|
||||||
|
CurrentContextOrganization organization,
|
||||||
|
[OrganizationUserWithDefaultPermissions] OrganizationUser organizationUser,
|
||||||
|
User user)
|
||||||
|
{
|
||||||
|
_featureService.IsEnabled(FeatureFlagKeys.PM23174ManageAccountRecoveryPermissionDrivesTheNeedToSetMasterPassword)
|
||||||
|
.Returns(true);
|
||||||
|
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||||
|
ssoConfig.Data = configurationData.Serialize();
|
||||||
|
ssoConfig.OrganizationId = organization.Id;
|
||||||
|
organizationUser.Type = organizationUserType;
|
||||||
|
organizationUser.OrganizationId = organization.Id;
|
||||||
|
organizationUser.UserId = user.Id;
|
||||||
|
organizationUser.SetPermissions(new Permissions() { ManageResetPassword = true });
|
||||||
|
_organizationUserRepository.GetByOrganizationAsync(ssoConfig.OrganizationId, user.Id).Returns(organizationUser);
|
||||||
|
|
||||||
|
var result = await _builder.ForUser(user).WithSso(ssoConfig).BuildAsync();
|
||||||
|
|
||||||
Assert.True(result.TrustedDeviceOption?.HasManageResetPasswordPermission);
|
Assert.True(result.TrustedDeviceOption?.HasManageResetPasswordPermission);
|
||||||
}
|
}
|
||||||
@ -241,7 +294,7 @@ public class UserDecryptionOptionsBuilderTests
|
|||||||
public async Task Build_WhenIsOwnerInvite_ShouldReturnHasManageResetPasswordPermissionTrue(
|
public async Task Build_WhenIsOwnerInvite_ShouldReturnHasManageResetPasswordPermissionTrue(
|
||||||
SsoConfig ssoConfig,
|
SsoConfig ssoConfig,
|
||||||
SsoConfigurationData configurationData,
|
SsoConfigurationData configurationData,
|
||||||
OrganizationUser organizationUser,
|
[OrganizationUserWithDefaultPermissions] OrganizationUser organizationUser,
|
||||||
User user)
|
User user)
|
||||||
{
|
{
|
||||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||||
@ -258,7 +311,7 @@ public class UserDecryptionOptionsBuilderTests
|
|||||||
public async Task Build_WhenIsAdminInvite_ShouldReturnHasManageResetPasswordPermissionTrue(
|
public async Task Build_WhenIsAdminInvite_ShouldReturnHasManageResetPasswordPermissionTrue(
|
||||||
SsoConfig ssoConfig,
|
SsoConfig ssoConfig,
|
||||||
SsoConfigurationData configurationData,
|
SsoConfigurationData configurationData,
|
||||||
OrganizationUser organizationUser,
|
[OrganizationUserWithDefaultPermissions] OrganizationUser organizationUser,
|
||||||
User user)
|
User user)
|
||||||
{
|
{
|
||||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||||
@ -275,7 +328,7 @@ public class UserDecryptionOptionsBuilderTests
|
|||||||
public async Task Build_WhenUserHasEnrolledIntoPasswordReset_ShouldReturnHasAdminApprovalTrue(
|
public async Task Build_WhenUserHasEnrolledIntoPasswordReset_ShouldReturnHasAdminApprovalTrue(
|
||||||
SsoConfig ssoConfig,
|
SsoConfig ssoConfig,
|
||||||
SsoConfigurationData configurationData,
|
SsoConfigurationData configurationData,
|
||||||
OrganizationUser organizationUser,
|
[OrganizationUserWithDefaultPermissions] OrganizationUser organizationUser,
|
||||||
User user)
|
User user)
|
||||||
{
|
{
|
||||||
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
configurationData.MemberDecryptionType = MemberDecryptionType.TrustedDeviceEncryption;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user