mirror of
https://github.com/bitwarden/server
synced 2026-02-20 11:23:37 +00:00
[PM-29498] Remove Premium Feature Flagged Logic (#6967)
* Remove feature flag logic and fix unit tests * Simplify query * Fix test * Fix local review
This commit is contained in:
@@ -8,7 +8,6 @@ using Bit.Core.Billing.Premium.Queries;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
|
||||
namespace Bit.Core.Auth.UserFeatures.TwoFactorAuth.Implementations;
|
||||
|
||||
@@ -16,108 +15,16 @@ public class TwoFactorIsEnabledQuery : ITwoFactorIsEnabledQuery
|
||||
{
|
||||
private readonly IUserRepository _userRepository;
|
||||
private readonly IHasPremiumAccessQuery _hasPremiumAccessQuery;
|
||||
private readonly IFeatureService _featureService;
|
||||
|
||||
public TwoFactorIsEnabledQuery(
|
||||
IUserRepository userRepository,
|
||||
IHasPremiumAccessQuery hasPremiumAccessQuery,
|
||||
IFeatureService featureService)
|
||||
IHasPremiumAccessQuery hasPremiumAccessQuery)
|
||||
{
|
||||
_userRepository = userRepository;
|
||||
_hasPremiumAccessQuery = hasPremiumAccessQuery;
|
||||
_featureService = featureService;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<(Guid userId, bool twoFactorIsEnabled)>> TwoFactorIsEnabledAsync(IEnumerable<Guid> userIds)
|
||||
{
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.PremiumAccessQuery))
|
||||
{
|
||||
return await TwoFactorIsEnabledVNextAsync(userIds);
|
||||
}
|
||||
|
||||
var result = new List<(Guid userId, bool hasTwoFactor)>();
|
||||
if (userIds == null || !userIds.Any())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
var userDetails = await _userRepository.GetManyWithCalculatedPremiumAsync([.. userIds]);
|
||||
foreach (var userDetail in userDetails)
|
||||
{
|
||||
result.Add(
|
||||
(userDetail.Id,
|
||||
await TwoFactorEnabledAsync(userDetail.GetTwoFactorProviders(),
|
||||
() => Task.FromResult(userDetail.HasPremiumAccess))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<(T user, bool twoFactorIsEnabled)>> TwoFactorIsEnabledAsync<T>(IEnumerable<T> users) where T : ITwoFactorProvidersUser
|
||||
{
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.PremiumAccessQuery))
|
||||
{
|
||||
return await TwoFactorIsEnabledVNextAsync(users);
|
||||
}
|
||||
|
||||
var userIds = users
|
||||
.Select(u => u.GetUserId())
|
||||
.Where(u => u.HasValue)
|
||||
.Select(u => u.Value)
|
||||
.ToList();
|
||||
|
||||
var twoFactorResults = await TwoFactorIsEnabledAsync(userIds);
|
||||
|
||||
var result = new List<(T user, bool twoFactorIsEnabled)>();
|
||||
|
||||
foreach (var user in users)
|
||||
{
|
||||
var userId = user.GetUserId();
|
||||
if (userId.HasValue)
|
||||
{
|
||||
var hasTwoFactor = twoFactorResults.FirstOrDefault(res => res.userId == userId.Value).twoFactorIsEnabled;
|
||||
result.Add((user, hasTwoFactor));
|
||||
}
|
||||
else
|
||||
{
|
||||
result.Add((user, false));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<bool> TwoFactorIsEnabledAsync(ITwoFactorProvidersUser user)
|
||||
{
|
||||
var userId = user.GetUserId();
|
||||
if (!userId.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.PremiumAccessQuery))
|
||||
{
|
||||
var userEntity = user as User ?? await _userRepository.GetByIdAsync(userId.Value);
|
||||
if (userEntity == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
return await TwoFactorIsEnabledVNextAsync(userEntity);
|
||||
}
|
||||
|
||||
return await TwoFactorEnabledAsync(
|
||||
user.GetTwoFactorProviders(),
|
||||
async () =>
|
||||
{
|
||||
var calcUser = await _userRepository.GetCalculatedPremiumAsync(userId.Value);
|
||||
return calcUser?.HasPremiumAccess ?? false;
|
||||
});
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<(Guid userId, bool twoFactorIsEnabled)>> TwoFactorIsEnabledVNextAsync(IEnumerable<Guid> userIds)
|
||||
{
|
||||
var result = new List<(Guid userId, bool hasTwoFactor)>();
|
||||
if (userIds == null || !userIds.Any())
|
||||
@@ -158,8 +65,7 @@ public class TwoFactorIsEnabledQuery : ITwoFactorIsEnabledQuery
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<(T user, bool twoFactorIsEnabled)>> TwoFactorIsEnabledVNextAsync<T>(IEnumerable<T> users)
|
||||
where T : ITwoFactorProvidersUser
|
||||
public async Task<IEnumerable<(T user, bool twoFactorIsEnabled)>> TwoFactorIsEnabledAsync<T>(IEnumerable<T> users) where T : ITwoFactorProvidersUser
|
||||
{
|
||||
var userIds = users
|
||||
.Select(u => u.GetUserId())
|
||||
@@ -167,7 +73,7 @@ public class TwoFactorIsEnabledQuery : ITwoFactorIsEnabledQuery
|
||||
.Select(u => u.Value)
|
||||
.ToList();
|
||||
|
||||
var twoFactorResults = await TwoFactorIsEnabledVNextAsync(userIds);
|
||||
var twoFactorResults = await TwoFactorIsEnabledAsync(userIds);
|
||||
|
||||
var result = new List<(T user, bool twoFactorIsEnabled)>();
|
||||
|
||||
@@ -188,10 +94,21 @@ public class TwoFactorIsEnabledQuery : ITwoFactorIsEnabledQuery
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task<bool> TwoFactorIsEnabledVNextAsync(User user)
|
||||
public async Task<bool> TwoFactorIsEnabledAsync(ITwoFactorProvidersUser user)
|
||||
{
|
||||
var enabledProviders = GetEnabledTwoFactorProviders(user);
|
||||
var userId = user.GetUserId();
|
||||
if (!userId.HasValue)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var userEntity = user as User ?? await _userRepository.GetByIdAsync(userId.Value);
|
||||
if (userEntity == null)
|
||||
{
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var enabledProviders = GetEnabledTwoFactorProviders(userEntity);
|
||||
if (!enabledProviders.Any())
|
||||
{
|
||||
return false;
|
||||
@@ -200,7 +117,7 @@ public class TwoFactorIsEnabledQuery : ITwoFactorIsEnabledQuery
|
||||
// If all providers require premium, check if user has premium access
|
||||
if (enabledProviders.All(TwoFactorProvider.RequiresPremium))
|
||||
{
|
||||
return await _hasPremiumAccessQuery.HasPremiumAccessAsync(user.Id);
|
||||
return await _hasPremiumAccessQuery.HasPremiumAccessAsync(userId.Value);
|
||||
}
|
||||
|
||||
// User has at least one non-premium provider
|
||||
@@ -226,48 +143,4 @@ public class TwoFactorIsEnabledQuery : ITwoFactorIsEnabledQuery
|
||||
where provider.Value?.Enabled ?? false
|
||||
select provider.Key).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see what kind of two-factor is enabled.
|
||||
/// We use a delegate to check if the user has premium access, since there are multiple ways to
|
||||
/// determine if a user has premium access.
|
||||
/// </summary>
|
||||
/// <param name="providers">dictionary of two factor providers</param>
|
||||
/// <param name="hasPremiumAccessDelegate">function to check if the user has premium access</param>
|
||||
/// <returns> true if the user has two factor enabled; false otherwise;</returns>
|
||||
private async static Task<bool> TwoFactorEnabledAsync(
|
||||
Dictionary<TwoFactorProviderType, TwoFactorProvider> providers,
|
||||
Func<Task<bool>> hasPremiumAccessDelegate)
|
||||
{
|
||||
// If there are no providers, then two factor is not enabled
|
||||
if (providers == null || providers.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get all enabled providers
|
||||
// TODO: PM-21210: In practice we don't save disabled providers to the database, worth looking into.
|
||||
var enabledProviderKeys = from provider in providers
|
||||
where provider.Value?.Enabled ?? false
|
||||
select provider.Key;
|
||||
|
||||
// If no providers are enabled then two factor is not enabled
|
||||
if (!enabledProviderKeys.Any())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there are only premium two factor options then standard two factor is not enabled
|
||||
var onlyHasPremiumTwoFactor = enabledProviderKeys.All(TwoFactorProvider.RequiresPremium);
|
||||
if (onlyHasPremiumTwoFactor)
|
||||
{
|
||||
// There are no Standard two factor options, check if the user has premium access
|
||||
// If the user has premium access, then two factor is enabled
|
||||
var premiumAccess = await hasPremiumAccessDelegate();
|
||||
return premiumAccess;
|
||||
}
|
||||
|
||||
// The user has at least one non-premium two factor option
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public static class FeatureFlagKeys
|
||||
public const string ScimRevokeV2 = "pm-32394-scim-revoke-put-v2";
|
||||
public const string PM23845_VNextApplicationCache = "pm-24957-refactor-memory-application-cache";
|
||||
public const string DefaultUserCollectionRestore = "pm-30883-my-items-restored-users";
|
||||
public const string PremiumAccessQuery = "pm-29495-refactor-premium-interface";
|
||||
public const string RefactorMembersComponent = "pm-29503-refactor-members-inheritance";
|
||||
public const string BulkReinviteUI = "pm-28416-bulk-reinvite-ux-improvements";
|
||||
public const string UpdateJoinOrganizationEmailTemplate = "pm-28396-update-join-organization-email-template";
|
||||
|
||||
|
||||
@@ -922,12 +922,7 @@ public class UserService : UserManager<User>, IUserService
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.PremiumAccessQuery))
|
||||
{
|
||||
return user.Premium || await _hasPremiumAccessQuery.HasPremiumFromOrganizationAsync(userId.Value);
|
||||
}
|
||||
|
||||
return user.Premium || await HasPremiumFromOrganization(user);
|
||||
return user.Premium || await _hasPremiumAccessQuery.HasPremiumFromOrganizationAsync(userId.Value);
|
||||
}
|
||||
|
||||
public async Task<bool> HasPremiumFromOrganization(User user)
|
||||
@@ -938,25 +933,7 @@ public class UserService : UserManager<User>, IUserService
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_featureService.IsEnabled(FeatureFlagKeys.PremiumAccessQuery))
|
||||
{
|
||||
return await _hasPremiumAccessQuery.HasPremiumFromOrganizationAsync(userId.Value);
|
||||
}
|
||||
|
||||
// orgUsers in the Invited status are not associated with a userId yet, so this will get
|
||||
// orgUsers in Accepted and Confirmed states only
|
||||
var orgUsers = await _organizationUserRepository.GetManyByUserAsync(userId.Value);
|
||||
|
||||
if (!orgUsers.Any())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var orgAbilities = await _applicationCacheService.GetOrganizationAbilitiesAsync();
|
||||
return orgUsers.Any(ou =>
|
||||
orgAbilities.TryGetValue(ou.OrganizationId, out var orgAbility) &&
|
||||
orgAbility.UsersGetPremium &&
|
||||
orgAbility.Enabled);
|
||||
return await _hasPremiumAccessQuery.HasPremiumFromOrganizationAsync(userId.Value);
|
||||
}
|
||||
|
||||
public async Task<string> GenerateSignInTokenAsync(User user, string purpose)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models;
|
||||
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Implementations;
|
||||
using Bit.Core.Billing.Premium.Models;
|
||||
using Bit.Core.Billing.Premium.Queries;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
@@ -44,7 +44,7 @@ public class TwoFactorIsEnabledQueryTests
|
||||
}
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetManyWithCalculatedPremiumAsync(Arg.Is<IEnumerable<Guid>>(i => i.All(userIds.Contains)))
|
||||
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(i => i.All(userIds.Contains)))
|
||||
.Returns(usersWithCalculatedPremium);
|
||||
|
||||
// Act
|
||||
@@ -65,10 +65,6 @@ public class TwoFactorIsEnabledQueryTests
|
||||
// Arrange
|
||||
var userIds = usersWithCalculatedPremium.Select(u => u.Id).ToList();
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetManyWithCalculatedPremiumAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns([]);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.TwoFactorIsEnabledAsync(userIds);
|
||||
|
||||
@@ -109,7 +105,7 @@ public class TwoFactorIsEnabledQueryTests
|
||||
}
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetManyWithCalculatedPremiumAsync(Arg.Is<IEnumerable<Guid>>(i => i.All(userIds.Contains)))
|
||||
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(i => i.All(userIds.Contains)))
|
||||
.Returns(usersWithCalculatedPremium);
|
||||
|
||||
// Act
|
||||
@@ -144,8 +140,16 @@ public class TwoFactorIsEnabledQueryTests
|
||||
user.SetTwoFactorProviders(twoFactorProviders);
|
||||
}
|
||||
|
||||
var hasPremiumAccessQueryResults = usersWithCalculatedPremium.ToDictionary(
|
||||
k => k.Id,
|
||||
v => v.HasPremiumAccess);
|
||||
|
||||
sutProvider.GetDependency<IHasPremiumAccessQuery>()
|
||||
.HasPremiumAccessAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns(hasPremiumAccessQueryResults);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetManyWithCalculatedPremiumAsync(Arg.Is<IEnumerable<Guid>>(i => i.All(userIds.Contains)))
|
||||
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(i => i.All(userIds.Contains)))
|
||||
.Returns(usersWithCalculatedPremium);
|
||||
|
||||
// Act
|
||||
@@ -165,19 +169,19 @@ public class TwoFactorIsEnabledQueryTests
|
||||
public async Task TwoFactorIsEnabledQuery_WithNullOrEmptyTwoFactorProviders_ReturnsAllTwoFactorDisabled(
|
||||
string twoFactorProviders,
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
List<UserWithCalculatedPremium> usersWithCalculatedPremium)
|
||||
List<UserPremiumAccess> usersWithCalculatedPremium)
|
||||
{
|
||||
// Arrange
|
||||
var userIds = usersWithCalculatedPremium.Select(u => u.Id).ToList();
|
||||
|
||||
foreach (var user in usersWithCalculatedPremium)
|
||||
var usersWithoutTwoFactorProviders = usersWithCalculatedPremium.Select(u => new User
|
||||
{
|
||||
user.TwoFactorProviders = twoFactorProviders; // No two-factor providers configured
|
||||
}
|
||||
Id = u.Id,
|
||||
TwoFactorProviders = twoFactorProviders
|
||||
});
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetManyWithCalculatedPremiumAsync(Arg.Is<IEnumerable<Guid>>(i => i.All(userIds.Contains)))
|
||||
.Returns(usersWithCalculatedPremium);
|
||||
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
|
||||
.Returns(usersWithoutTwoFactorProviders);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.TwoFactorIsEnabledAsync(userIds);
|
||||
@@ -189,33 +193,6 @@ public class TwoFactorIsEnabledQueryTests
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task TwoFactorIsEnabledQuery_WithNoUserIds_ReturnsAllTwoFactorDisabled(
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
List<OrganizationUserUserDetails> users)
|
||||
{
|
||||
// Arrange
|
||||
foreach (var user in users)
|
||||
{
|
||||
user.UserId = null;
|
||||
}
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.TwoFactorIsEnabledAsync(users);
|
||||
|
||||
// Assert
|
||||
foreach (var user in users)
|
||||
{
|
||||
Assert.Contains(result, res => res.user.Equals(user) && res.twoFactorIsEnabled == false);
|
||||
}
|
||||
|
||||
// No UserIds were supplied so no calls to the UserRepository should have been made
|
||||
await sutProvider.GetDependency<IUserRepository>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.GetManyWithCalculatedPremiumAsync(default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task TwoFactorIsEnabledQuery_UserIdNull_ReturnsFalse(
|
||||
@@ -258,10 +235,6 @@ public class TwoFactorIsEnabledQueryTests
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
||||
await sutProvider.GetDependency<IUserRepository>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.GetCalculatedPremiumAsync(default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -283,10 +256,6 @@ public class TwoFactorIsEnabledQueryTests
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
|
||||
await sutProvider.GetDependency<IUserRepository>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.GetCalculatedPremiumAsync(default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -303,13 +272,11 @@ public class TwoFactorIsEnabledQueryTests
|
||||
{ premiumProviderType, new TwoFactorProvider { Enabled = true } }
|
||||
};
|
||||
|
||||
user.Premium = false;
|
||||
user.HasPremiumAccess = false;
|
||||
user.SetTwoFactorProviders(twoFactorProviders);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetCalculatedPremiumAsync(user.Id)
|
||||
.Returns(user);
|
||||
sutProvider.GetDependency<IHasPremiumAccessQuery>()
|
||||
.HasPremiumAccessAsync(user.Id)
|
||||
.Returns(false);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.TwoFactorIsEnabledAsync(user);
|
||||
@@ -317,15 +284,15 @@ public class TwoFactorIsEnabledQueryTests
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
|
||||
await sutProvider.GetDependency<IUserRepository>()
|
||||
await sutProvider.GetDependency<IHasPremiumAccessQuery>()
|
||||
.ReceivedWithAnyArgs(1)
|
||||
.GetCalculatedPremiumAsync(default);
|
||||
.HasPremiumAccessAsync(user.Id);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(TwoFactorProviderType.Duo)]
|
||||
[BitAutoData(TwoFactorProviderType.YubiKey)]
|
||||
public async Task TwoFactorIsEnabledQuery_WithProviderTypeRequiringPremium_WithUserPremium_ReturnsTrue(
|
||||
public async Task TwoFactorIsEnabledQuery_WithProviderTypeRequiringPremium_WithPremium_ReturnsTrue(
|
||||
TwoFactorProviderType premiumProviderType,
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
UserWithCalculatedPremium user)
|
||||
@@ -336,13 +303,11 @@ public class TwoFactorIsEnabledQueryTests
|
||||
{ premiumProviderType, new TwoFactorProvider { Enabled = true } }
|
||||
};
|
||||
|
||||
user.Premium = false;
|
||||
user.HasPremiumAccess = true;
|
||||
user.SetTwoFactorProviders(twoFactorProviders);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetCalculatedPremiumAsync(user.Id)
|
||||
.Returns(user);
|
||||
sutProvider.GetDependency<IHasPremiumAccessQuery>()
|
||||
.HasPremiumAccessAsync(user.Id)
|
||||
.Returns(true);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.TwoFactorIsEnabledAsync(user);
|
||||
@@ -350,42 +315,9 @@ public class TwoFactorIsEnabledQueryTests
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
||||
await sutProvider.GetDependency<IUserRepository>()
|
||||
await sutProvider.GetDependency<IHasPremiumAccessQuery>()
|
||||
.ReceivedWithAnyArgs(1)
|
||||
.GetCalculatedPremiumAsync(default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(TwoFactorProviderType.Duo)]
|
||||
[BitAutoData(TwoFactorProviderType.YubiKey)]
|
||||
public async Task TwoFactorIsEnabledQuery_WithProviderTypeRequiringPremium_WithOrgPremium_ReturnsTrue(
|
||||
TwoFactorProviderType premiumProviderType,
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
UserWithCalculatedPremium user)
|
||||
{
|
||||
// Arrange
|
||||
var twoFactorProviders = new Dictionary<TwoFactorProviderType, TwoFactorProvider>
|
||||
{
|
||||
{ premiumProviderType, new TwoFactorProvider { Enabled = true } }
|
||||
};
|
||||
|
||||
user.Premium = false;
|
||||
user.HasPremiumAccess = true;
|
||||
user.SetTwoFactorProviders(twoFactorProviders);
|
||||
|
||||
sutProvider.GetDependency<IUserRepository>()
|
||||
.GetCalculatedPremiumAsync(user.Id)
|
||||
.Returns(user);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.TwoFactorIsEnabledAsync(user);
|
||||
|
||||
// Assert
|
||||
Assert.True(result);
|
||||
|
||||
await sutProvider.GetDependency<IUserRepository>()
|
||||
.ReceivedWithAnyArgs(1)
|
||||
.GetCalculatedPremiumAsync(default);
|
||||
.HasPremiumAccessAsync(user.Id);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -402,23 +334,16 @@ public class TwoFactorIsEnabledQueryTests
|
||||
|
||||
// Assert
|
||||
Assert.False(result);
|
||||
await sutProvider.GetDependency<IUserRepository>()
|
||||
.DidNotReceiveWithAnyArgs()
|
||||
.GetCalculatedPremiumAsync(default);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData((IEnumerable<Guid>)null)]
|
||||
[BitAutoData([])]
|
||||
public async Task TwoFactorIsEnabledAsync_WhenPremiumAccessQueryEnabled_WithNoUserIds_ReturnsEmpty(
|
||||
public async Task TwoFactorIsEnabledAsync_WithNoUserIds_ReturnsEmpty(
|
||||
IEnumerable<Guid> userIds,
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PremiumAccessQuery)
|
||||
.Returns(true);
|
||||
|
||||
// Act
|
||||
var result = await sutProvider.Sut.TwoFactorIsEnabledAsync(userIds);
|
||||
|
||||
@@ -429,7 +354,7 @@ public class TwoFactorIsEnabledQueryTests
|
||||
[Theory]
|
||||
[BitAutoData(TwoFactorProviderType.Duo)]
|
||||
[BitAutoData(TwoFactorProviderType.YubiKey)]
|
||||
public async Task TwoFactorIsEnabledAsync_WhenPremiumAccessQueryEnabled_WithMixedScenarios_ReturnsCorrectResults(
|
||||
public async Task TwoFactorIsEnabledAsync_WithMixedScenarios_ReturnsCorrectResults(
|
||||
TwoFactorProviderType premiumProviderType,
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
User user1,
|
||||
@@ -437,10 +362,6 @@ public class TwoFactorIsEnabledQueryTests
|
||||
User user3)
|
||||
{
|
||||
// Arrange
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PremiumAccessQuery)
|
||||
.Returns(true);
|
||||
|
||||
var users = new List<User> { user1, user2, user3 };
|
||||
var userIds = users.Select(u => u.Id).ToList();
|
||||
|
||||
@@ -489,7 +410,7 @@ public class TwoFactorIsEnabledQueryTests
|
||||
[Theory]
|
||||
[BitAutoData(TwoFactorProviderType.Duo)]
|
||||
[BitAutoData(TwoFactorProviderType.YubiKey)]
|
||||
public async Task TwoFactorIsEnabledAsync_WhenPremiumAccessQueryEnabled_OnlyChecksPremiumAccessForUsersWhoNeedIt(
|
||||
public async Task TwoFactorIsEnabledAsync_OnlyChecksPremiumAccessForUsersWhoNeedIt(
|
||||
TwoFactorProviderType premiumProviderType,
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
User user1,
|
||||
@@ -497,10 +418,6 @@ public class TwoFactorIsEnabledQueryTests
|
||||
User user3)
|
||||
{
|
||||
// Arrange
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PremiumAccessQuery)
|
||||
.Returns(true);
|
||||
|
||||
var users = new List<User> { user1, user2, user3 };
|
||||
var userIds = users.Select(u => u.Id).ToList();
|
||||
|
||||
@@ -547,15 +464,11 @@ public class TwoFactorIsEnabledQueryTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task TwoFactorIsEnabledAsync_WhenPremiumAccessQueryEnabled_WithNoUserIds_ReturnsAllTwoFactorDisabled(
|
||||
public async Task TwoFactorIsEnabledAsync_WithNoUserIds_ReturnsAllTwoFactorDisabled(
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
List<OrganizationUserUserDetails> users)
|
||||
{
|
||||
// Arrange
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PremiumAccessQuery)
|
||||
.Returns(true);
|
||||
|
||||
foreach (var user in users)
|
||||
{
|
||||
user.UserId = null;
|
||||
@@ -580,17 +493,13 @@ public class TwoFactorIsEnabledQueryTests
|
||||
[BitAutoData(TwoFactorProviderType.Authenticator, true)] // Non-premium provider
|
||||
[BitAutoData(TwoFactorProviderType.Duo, true)] // Premium provider with premium access
|
||||
[BitAutoData(TwoFactorProviderType.YubiKey, false)] // Premium provider without premium access
|
||||
public async Task TwoFactorIsEnabledAsync_WhenPremiumAccessQueryEnabled_SingleUser_VariousScenarios(
|
||||
public async Task TwoFactorIsEnabledAsync_SingleUser_VariousScenarios(
|
||||
TwoFactorProviderType providerType,
|
||||
bool hasPremiumAccess,
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
User user)
|
||||
{
|
||||
// Arrange
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PremiumAccessQuery)
|
||||
.Returns(true);
|
||||
|
||||
user.SetTwoFactorProviders(new Dictionary<TwoFactorProviderType, TwoFactorProvider>
|
||||
{
|
||||
{ providerType, new TwoFactorProvider { Enabled = true } }
|
||||
@@ -611,15 +520,11 @@ public class TwoFactorIsEnabledQueryTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task TwoFactorIsEnabledAsync_WhenPremiumAccessQueryEnabled_WithNoEnabledProviders_ReturnsFalse(
|
||||
public async Task TwoFactorIsEnabledAsync_WithNoEnabledProviders_ReturnsFalse(
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
User user)
|
||||
{
|
||||
// Arrange
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PremiumAccessQuery)
|
||||
.Returns(true);
|
||||
|
||||
user.SetTwoFactorProviders(new Dictionary<TwoFactorProviderType, TwoFactorProvider>
|
||||
{
|
||||
{ TwoFactorProviderType.Email, new TwoFactorProvider { Enabled = false } }
|
||||
@@ -634,15 +539,11 @@ public class TwoFactorIsEnabledQueryTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task TwoFactorIsEnabledAsync_WhenPremiumAccessQueryEnabled_WithNullProviders_ReturnsFalse(
|
||||
public async Task TwoFactorIsEnabledAsync_WithNullProviders_ReturnsFalse(
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
User user)
|
||||
{
|
||||
// Arrange
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PremiumAccessQuery)
|
||||
.Returns(true);
|
||||
|
||||
user.TwoFactorProviders = null;
|
||||
|
||||
// Act
|
||||
@@ -654,15 +555,11 @@ public class TwoFactorIsEnabledQueryTests
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task TwoFactorIsEnabledAsync_WhenPremiumAccessQueryEnabled_UserNotFound_ThrowsNotFoundException(
|
||||
public async Task TwoFactorIsEnabledAsync_UserNotFound_ThrowsNotFoundException(
|
||||
SutProvider<TwoFactorIsEnabledQuery> sutProvider,
|
||||
Guid userId)
|
||||
{
|
||||
// Arrange
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PremiumAccessQuery)
|
||||
.Returns(true);
|
||||
|
||||
var testUser = new TestTwoFactorProviderUser
|
||||
{
|
||||
Id = userId,
|
||||
|
||||
@@ -12,6 +12,7 @@ using Bit.Core.Auth.Enums;
|
||||
using Bit.Core.Auth.Models;
|
||||
using Bit.Core.Auth.UserFeatures.TwoFactorAuth.Interfaces;
|
||||
using Bit.Core.Billing.Models.Business;
|
||||
using Bit.Core.Billing.Premium.Queries;
|
||||
using Bit.Core.Billing.Services;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
@@ -113,11 +114,11 @@ public class UserServiceTests
|
||||
{
|
||||
orgUser.OrganizationId = organization.Id;
|
||||
organization.Enabled = true;
|
||||
organization.UsersGetPremium = true;
|
||||
var orgAbilities = new Dictionary<Guid, OrganizationAbility>() { { organization.Id, new OrganizationAbility(organization) } };
|
||||
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().GetManyByUserAsync(user.Id).Returns(new List<OrganizationUser>() { orgUser });
|
||||
sutProvider.GetDependency<IApplicationCacheService>().GetOrganizationAbilitiesAsync().Returns(orgAbilities);
|
||||
sutProvider.GetDependency<IHasPremiumAccessQuery>().HasPremiumFromOrganizationAsync(user.Id).Returns(true);
|
||||
|
||||
Assert.True(await sutProvider.Sut.HasPremiumFromOrganization(user));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user