mirror of
https://github.com/bitwarden/server.git
synced 2024-11-29 13:25:17 +01:00
add feature flag
This commit is contained in:
parent
12da983165
commit
0b60bb93d8
@ -1,5 +1,7 @@
|
|||||||
#nullable enable
|
#nullable enable
|
||||||
using Bit.Api.KeyManagement.Models.Requests;
|
using Bit.Api.KeyManagement.Models.Requests;
|
||||||
|
using Bit.Core;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.KeyManagement.Commands.Interfaces;
|
using Bit.Core.KeyManagement.Commands.Interfaces;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
using Bit.Core.Services;
|
using Bit.Core.Services;
|
||||||
@ -13,16 +15,19 @@ namespace Bit.Api.KeyManagement.Controllers;
|
|||||||
public class AccountsKeyManagementController : Controller
|
public class AccountsKeyManagementController : Controller
|
||||||
{
|
{
|
||||||
private readonly IEmergencyAccessRepository _emergencyAccessRepository;
|
private readonly IEmergencyAccessRepository _emergencyAccessRepository;
|
||||||
|
private readonly IFeatureService _featureService;
|
||||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||||
private readonly IRegenerateUserAsymmetricKeysCommand _regenerateUserAsymmetricKeysCommand;
|
private readonly IRegenerateUserAsymmetricKeysCommand _regenerateUserAsymmetricKeysCommand;
|
||||||
private readonly IUserService _userService;
|
private readonly IUserService _userService;
|
||||||
|
|
||||||
public AccountsKeyManagementController(IUserService userService,
|
public AccountsKeyManagementController(IUserService userService,
|
||||||
|
IFeatureService featureService,
|
||||||
IOrganizationUserRepository organizationUserRepository,
|
IOrganizationUserRepository organizationUserRepository,
|
||||||
IEmergencyAccessRepository emergencyAccessRepository,
|
IEmergencyAccessRepository emergencyAccessRepository,
|
||||||
IRegenerateUserAsymmetricKeysCommand regenerateUserAsymmetricKeysCommand)
|
IRegenerateUserAsymmetricKeysCommand regenerateUserAsymmetricKeysCommand)
|
||||||
{
|
{
|
||||||
_userService = userService;
|
_userService = userService;
|
||||||
|
_featureService = featureService;
|
||||||
_regenerateUserAsymmetricKeysCommand = regenerateUserAsymmetricKeysCommand;
|
_regenerateUserAsymmetricKeysCommand = regenerateUserAsymmetricKeysCommand;
|
||||||
_organizationUserRepository = organizationUserRepository;
|
_organizationUserRepository = organizationUserRepository;
|
||||||
_emergencyAccessRepository = emergencyAccessRepository;
|
_emergencyAccessRepository = emergencyAccessRepository;
|
||||||
@ -31,7 +36,11 @@ public class AccountsKeyManagementController : Controller
|
|||||||
[HttpPost("regenerate-keys")]
|
[HttpPost("regenerate-keys")]
|
||||||
public async Task RegenerateKeysAsync([FromBody] KeyRegenerationRequestModel request)
|
public async Task RegenerateKeysAsync([FromBody] KeyRegenerationRequestModel request)
|
||||||
{
|
{
|
||||||
// FIXME add feature flag check.
|
if (!_featureService.IsEnabled(FeatureFlagKeys.PrivateKeyRegeneration))
|
||||||
|
{
|
||||||
|
throw new NotFoundException();
|
||||||
|
}
|
||||||
|
|
||||||
var user = await _userService.GetUserByPrincipalAsync(User) ?? throw new UnauthorizedAccessException();
|
var user = await _userService.GetUserByPrincipalAsync(User) ?? throw new UnauthorizedAccessException();
|
||||||
var usersOrganizationAccounts = await _organizationUserRepository.GetManyByUserAsync(user.Id);
|
var usersOrganizationAccounts = await _organizationUserRepository.GetManyByUserAsync(user.Id);
|
||||||
var designatedEmergencyAccess = await _emergencyAccessRepository.GetManyDetailsByGranteeIdAsync(user.Id);
|
var designatedEmergencyAccess = await _emergencyAccessRepository.GetManyDetailsByGranteeIdAsync(user.Id);
|
||||||
|
@ -148,6 +148,7 @@ public static class FeatureFlagKeys
|
|||||||
public const string VerifiedSsoDomainEndpoint = "pm-12337-refactor-sso-details-endpoint";
|
public const string VerifiedSsoDomainEndpoint = "pm-12337-refactor-sso-details-endpoint";
|
||||||
public const string Pm13322AddPolicyDefinitions = "pm-13322-add-policy-definitions";
|
public const string Pm13322AddPolicyDefinitions = "pm-13322-add-policy-definitions";
|
||||||
public const string LimitCollectionCreationDeletionSplit = "pm-10863-limit-collection-creation-deletion-split";
|
public const string LimitCollectionCreationDeletionSplit = "pm-10863-limit-collection-creation-deletion-split";
|
||||||
|
public const string PrivateKeyRegeneration = "pm-12241-private-key-regeneration";
|
||||||
|
|
||||||
public static List<string> GetAllKeys()
|
public static List<string> GetAllKeys()
|
||||||
{
|
{
|
||||||
|
@ -27,6 +27,8 @@ public class AccountsKeyManagementControllerTests : IClassFixture<ApiApplication
|
|||||||
public AccountsKeyManagementControllerTests(ApiApplicationFactory factory)
|
public AccountsKeyManagementControllerTests(ApiApplicationFactory factory)
|
||||||
{
|
{
|
||||||
_factory = factory;
|
_factory = factory;
|
||||||
|
_factory.UpdateConfiguration("globalSettings:launchDarkly:flagValues:pm-12241-private-key-regeneration",
|
||||||
|
"true");
|
||||||
_client = factory.CreateClient();
|
_client = factory.CreateClient();
|
||||||
_loginHelper = new LoginHelper(_factory, _client);
|
_loginHelper = new LoginHelper(_factory, _client);
|
||||||
_userRepository = _factory.GetService<IUserRepository>();
|
_userRepository = _factory.GetService<IUserRepository>();
|
||||||
@ -45,6 +47,27 @@ public class AccountsKeyManagementControllerTests : IClassFixture<ApiApplication
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task RegenerateKeysAsync_FeatureFlagTurnedOff_NotFound(KeyRegenerationRequestModel request)
|
||||||
|
{
|
||||||
|
// Localize factory to inject a false value for the feature flag.
|
||||||
|
var localFactory = new ApiApplicationFactory();
|
||||||
|
localFactory.UpdateConfiguration("globalSettings:launchDarkly:flagValues:pm-12241-private-key-regeneration",
|
||||||
|
"false");
|
||||||
|
var localClient = localFactory.CreateClient();
|
||||||
|
var localEmail = $"integration-test{Guid.NewGuid()}@bitwarden.com";
|
||||||
|
var localLoginHelper = new LoginHelper(localFactory, localClient);
|
||||||
|
await localFactory.LoginWithNewAccount(localEmail);
|
||||||
|
await localLoginHelper.LoginAsync(localEmail);
|
||||||
|
|
||||||
|
request.UserKeyEncryptedUserPrivateKey = _mockEncryptedString;
|
||||||
|
|
||||||
|
var response = await localClient.PostAsJsonAsync("/accounts/key-management/regenerate-keys", request);
|
||||||
|
|
||||||
|
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[BitAutoData]
|
[BitAutoData]
|
||||||
public async Task RegenerateKeysAsync_NotLoggedIn_Unauthorized(KeyRegenerationRequestModel request)
|
public async Task RegenerateKeysAsync_NotLoggedIn_Unauthorized(KeyRegenerationRequestModel request)
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using Bit.Api.KeyManagement.Controllers;
|
using Bit.Api.KeyManagement.Controllers;
|
||||||
using Bit.Api.KeyManagement.Models.Requests;
|
using Bit.Api.KeyManagement.Models.Requests;
|
||||||
|
using Bit.Core;
|
||||||
using Bit.Core.Auth.Models.Data;
|
using Bit.Core.Auth.Models.Data;
|
||||||
using Bit.Core.Entities;
|
using Bit.Core.Entities;
|
||||||
|
using Bit.Core.Exceptions;
|
||||||
using Bit.Core.KeyManagement.Commands.Interfaces;
|
using Bit.Core.KeyManagement.Commands.Interfaces;
|
||||||
using Bit.Core.KeyManagement.Models.Data;
|
using Bit.Core.KeyManagement.Models.Data;
|
||||||
using Bit.Core.Repositories;
|
using Bit.Core.Repositories;
|
||||||
@ -21,11 +23,35 @@ namespace Bit.Api.Test.KeyManagement.Controllers;
|
|||||||
[JsonDocumentCustomize]
|
[JsonDocumentCustomize]
|
||||||
public class AccountsKeyManagementControllerTests
|
public class AccountsKeyManagementControllerTests
|
||||||
{
|
{
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task RegenerateKeysAsync_FeatureFlagOff_Throws(
|
||||||
|
SutProvider<AccountsKeyManagementController> sutProvider,
|
||||||
|
KeyRegenerationRequestModel data)
|
||||||
|
{
|
||||||
|
sutProvider.GetDependency<IFeatureService>().IsEnabled(Arg.Is(FeatureFlagKeys.PrivateKeyRegeneration))
|
||||||
|
.Returns(false);
|
||||||
|
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).ReturnsNull();
|
||||||
|
|
||||||
|
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.RegenerateKeysAsync(data));
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IOrganizationUserRepository>().ReceivedWithAnyArgs(0)
|
||||||
|
.GetManyByUserAsync(Arg.Any<Guid>());
|
||||||
|
await sutProvider.GetDependency<IEmergencyAccessRepository>().ReceivedWithAnyArgs(0)
|
||||||
|
.GetManyDetailsByGranteeIdAsync(Arg.Any<Guid>());
|
||||||
|
await sutProvider.GetDependency<IRegenerateUserAsymmetricKeysCommand>().ReceivedWithAnyArgs(0)
|
||||||
|
.RegenerateKeysAsync(Arg.Any<UserAsymmetricKeys>(),
|
||||||
|
Arg.Any<ICollection<OrganizationUser>>(),
|
||||||
|
Arg.Any<ICollection<EmergencyAccessDetails>>());
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[BitAutoData]
|
[BitAutoData]
|
||||||
public async Task RegenerateKeysAsync_UserNull_Throws(SutProvider<AccountsKeyManagementController> sutProvider,
|
public async Task RegenerateKeysAsync_UserNull_Throws(SutProvider<AccountsKeyManagementController> sutProvider,
|
||||||
KeyRegenerationRequestModel data)
|
KeyRegenerationRequestModel data)
|
||||||
{
|
{
|
||||||
|
sutProvider.GetDependency<IFeatureService>().IsEnabled(Arg.Is(FeatureFlagKeys.PrivateKeyRegeneration))
|
||||||
|
.Returns(true);
|
||||||
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).ReturnsNull();
|
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).ReturnsNull();
|
||||||
|
|
||||||
await Assert.ThrowsAsync<UnauthorizedAccessException>(() => sutProvider.Sut.RegenerateKeysAsync(data));
|
await Assert.ThrowsAsync<UnauthorizedAccessException>(() => sutProvider.Sut.RegenerateKeysAsync(data));
|
||||||
@ -45,6 +71,8 @@ public class AccountsKeyManagementControllerTests
|
|||||||
public async Task RegenerateKeysAsync_Success(SutProvider<AccountsKeyManagementController> sutProvider,
|
public async Task RegenerateKeysAsync_Success(SutProvider<AccountsKeyManagementController> sutProvider,
|
||||||
KeyRegenerationRequestModel data, User user)
|
KeyRegenerationRequestModel data, User user)
|
||||||
{
|
{
|
||||||
|
sutProvider.GetDependency<IFeatureService>().IsEnabled(Arg.Is(FeatureFlagKeys.PrivateKeyRegeneration))
|
||||||
|
.Returns(true);
|
||||||
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(user);
|
sutProvider.GetDependency<IUserService>().GetUserByPrincipalAsync(Arg.Any<ClaimsPrincipal>()).Returns(user);
|
||||||
|
|
||||||
await sutProvider.Sut.RegenerateKeysAsync(data);
|
await sutProvider.Sut.RegenerateKeysAsync(data);
|
||||||
|
Loading…
Reference in New Issue
Block a user