mirror of
https://github.com/bitwarden/server.git
synced 2024-12-04 14:13:28 +01:00
Add feature flag
This commit is contained in:
parent
56d03b8e5c
commit
c4f8679270
@ -19,6 +19,7 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz
|
|||||||
private readonly IUserRepository _userRepository;
|
private readonly IUserRepository _userRepository;
|
||||||
private readonly ICurrentContext _currentContext;
|
private readonly ICurrentContext _currentContext;
|
||||||
private readonly IHasConfirmedOwnersExceptQuery _hasConfirmedOwnersExceptQuery;
|
private readonly IHasConfirmedOwnersExceptQuery _hasConfirmedOwnersExceptQuery;
|
||||||
|
private readonly IFeatureService _featureService;
|
||||||
|
|
||||||
public DeleteManagedOrganizationUserAccountCommand(
|
public DeleteManagedOrganizationUserAccountCommand(
|
||||||
IUserService userService,
|
IUserService userService,
|
||||||
@ -27,7 +28,8 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz
|
|||||||
IOrganizationUserRepository organizationUserRepository,
|
IOrganizationUserRepository organizationUserRepository,
|
||||||
IUserRepository userRepository,
|
IUserRepository userRepository,
|
||||||
ICurrentContext currentContext,
|
ICurrentContext currentContext,
|
||||||
IHasConfirmedOwnersExceptQuery hasConfirmedOwnersExceptQuery)
|
IHasConfirmedOwnersExceptQuery hasConfirmedOwnersExceptQuery,
|
||||||
|
IFeatureService featureService)
|
||||||
{
|
{
|
||||||
_userService = userService;
|
_userService = userService;
|
||||||
_eventService = eventService;
|
_eventService = eventService;
|
||||||
@ -36,6 +38,7 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz
|
|||||||
_userRepository = userRepository;
|
_userRepository = userRepository;
|
||||||
_currentContext = currentContext;
|
_currentContext = currentContext;
|
||||||
_hasConfirmedOwnersExceptQuery = hasConfirmedOwnersExceptQuery;
|
_hasConfirmedOwnersExceptQuery = hasConfirmedOwnersExceptQuery;
|
||||||
|
_featureService = featureService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid? deletingUserId)
|
public async Task DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid? deletingUserId)
|
||||||
@ -71,6 +74,7 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz
|
|||||||
var hasOtherConfirmedOwners = await _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(organizationId, orgUserIds, includeProvider: true);
|
var hasOtherConfirmedOwners = await _hasConfirmedOwnersExceptQuery.HasConfirmedOwnersExceptAsync(organizationId, orgUserIds, includeProvider: true);
|
||||||
|
|
||||||
var results = new List<(Guid OrganizationUserId, string? ErrorMessage)>();
|
var results = new List<(Guid OrganizationUserId, string? ErrorMessage)>();
|
||||||
|
var accountDeprovisioningEnabled = _featureService.IsEnabled(FeatureFlagKeys.AccountDeprovisioning);
|
||||||
foreach (var orgUserId in orgUserIds)
|
foreach (var orgUserId in orgUserIds)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -88,7 +92,10 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz
|
|||||||
{
|
{
|
||||||
throw new NotFoundException("Member not found.");
|
throw new NotFoundException("Member not found.");
|
||||||
}
|
}
|
||||||
|
if (!accountDeprovisioningEnabled)
|
||||||
|
{
|
||||||
|
await _userService.DeleteAsync(user);
|
||||||
|
}
|
||||||
results.Add((orgUserId, string.Empty));
|
results.Add((orgUserId, string.Empty));
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -97,7 +104,10 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (accountDeprovisioningEnabled)
|
||||||
|
{
|
||||||
await _userService.DeleteManyAsync(users);
|
await _userService.DeleteManyAsync(users);
|
||||||
|
}
|
||||||
await LogDeletedOrganizationUsersAsync(orgUsers, results);
|
await LogDeletedOrganizationUsersAsync(orgUsers, results);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
|
@ -235,7 +235,7 @@ public class DeleteManagedOrganizationUserAccountCommandTests
|
|||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[BitAutoData]
|
[BitAutoData]
|
||||||
public async Task DeleteManyUsersAsync_WithValidUsers_DeletesUsersAndLogsEvents(
|
public async Task DeleteManyUsersAsync_WhenFeatureFlagEnabled_WithValidUsers_DeletesUsersAndLogsEvents(
|
||||||
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user1, User user2, Guid organizationId,
|
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user1, User user2, Guid organizationId,
|
||||||
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser1,
|
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser1,
|
||||||
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser2)
|
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser2)
|
||||||
@ -257,6 +257,9 @@ public class DeleteManagedOrganizationUserAccountCommandTests
|
|||||||
.GetUsersOrganizationManagementStatusAsync(organizationId, Arg.Any<IEnumerable<Guid>>())
|
.GetUsersOrganizationManagementStatusAsync(organizationId, Arg.Any<IEnumerable<Guid>>())
|
||||||
.Returns(new Dictionary<Guid, bool> { { orgUser1.Id, true }, { orgUser2.Id, true } });
|
.Returns(new Dictionary<Guid, bool> { { orgUser1.Id, true }, { orgUser2.Id, true } });
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.IsEnabled(FeatureFlagKeys.AccountDeprovisioning).Returns(true);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var userIds = new[] { orgUser1.Id, orgUser2.Id };
|
var userIds = new[] { orgUser1.Id, orgUser2.Id };
|
||||||
var results = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, userIds, null);
|
var results = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, userIds, null);
|
||||||
@ -267,6 +270,7 @@ public class DeleteManagedOrganizationUserAccountCommandTests
|
|||||||
|
|
||||||
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyAsync(userIds);
|
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyAsync(userIds);
|
||||||
await sutProvider.GetDependency<IUserService>().Received(1).DeleteManyAsync(Arg.Any<IEnumerable<User>>());
|
await sutProvider.GetDependency<IUserService>().Received(1).DeleteManyAsync(Arg.Any<IEnumerable<User>>());
|
||||||
|
await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
|
||||||
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventsAsync(
|
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventsAsync(
|
||||||
Arg.Is<IEnumerable<(OrganizationUser, EventType, DateTime?)>>(events =>
|
Arg.Is<IEnumerable<(OrganizationUser, EventType, DateTime?)>>(events =>
|
||||||
events.Count(e => e.Item1.Id == orgUser1.Id && e.Item2 == EventType.OrganizationUser_Deleted) == 1
|
events.Count(e => e.Item1.Id == orgUser1.Id && e.Item2 == EventType.OrganizationUser_Deleted) == 1
|
||||||
@ -275,11 +279,59 @@ public class DeleteManagedOrganizationUserAccountCommandTests
|
|||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[BitAutoData]
|
[BitAutoData]
|
||||||
public async Task DeleteManyUsersAsync_WhenUserNotFound_ReturnsErrorMessage(
|
public async Task DeleteManyUsersAsync_WhenFeatureFlagDisabled_WithValidUsers_DeletesUsersAndLogsEvents(
|
||||||
|
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user1, User user2, Guid organizationId,
|
||||||
|
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser1,
|
||||||
|
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser2)
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
orgUser1.OrganizationId = orgUser2.OrganizationId = organizationId;
|
||||||
|
orgUser1.UserId = user1.Id;
|
||||||
|
orgUser2.UserId = user2.Id;
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IOrganizationUserRepository>()
|
||||||
|
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
|
||||||
|
.Returns(new List<OrganizationUser> { orgUser1, orgUser2 });
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IUserRepository>()
|
||||||
|
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user1.Id) && ids.Contains(user2.Id)))
|
||||||
|
.Returns(new[] { user1, user2 });
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
|
||||||
|
.GetUsersOrganizationManagementStatusAsync(organizationId, Arg.Any<IEnumerable<Guid>>())
|
||||||
|
.Returns(new Dictionary<Guid, bool> { { orgUser1.Id, true }, { orgUser2.Id, true } });
|
||||||
|
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.IsEnabled(FeatureFlagKeys.AccountDeprovisioning).Returns(false);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var userIds = new[] { orgUser1.Id, orgUser2.Id };
|
||||||
|
var results = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, userIds, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Equal(2, results.Count());
|
||||||
|
Assert.All(results, r => Assert.Empty(r.Item2));
|
||||||
|
|
||||||
|
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyAsync(userIds);
|
||||||
|
await sutProvider.GetDependency<IUserService>().Received(0).DeleteManyAsync(Arg.Any<IEnumerable<User>>());
|
||||||
|
await sutProvider.GetDependency<IUserService>().Received(2).DeleteAsync(Arg.Any<User>());
|
||||||
|
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventsAsync(
|
||||||
|
Arg.Is<IEnumerable<(OrganizationUser, EventType, DateTime?)>>(events =>
|
||||||
|
events.Count(e => e.Item1.Id == orgUser1.Id && e.Item2 == EventType.OrganizationUser_Deleted) == 1
|
||||||
|
&& events.Count(e => e.Item1.Id == orgUser2.Id && e.Item2 == EventType.OrganizationUser_Deleted) == 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task DeleteManyUsersAsync_WhenFeatureFlagEnabled_WhenUserNotFound_ReturnsErrorMessage(
|
||||||
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider,
|
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider,
|
||||||
Guid organizationId,
|
Guid organizationId,
|
||||||
Guid orgUserId)
|
Guid orgUserId)
|
||||||
{
|
{
|
||||||
|
// Arrang
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.IsEnabled(FeatureFlagKeys.AccountDeprovisioning).Returns(true);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, new[] { orgUserId }, null);
|
var result = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, new[] { orgUserId }, null);
|
||||||
|
|
||||||
@ -287,6 +339,30 @@ public class DeleteManagedOrganizationUserAccountCommandTests
|
|||||||
Assert.Single(result);
|
Assert.Single(result);
|
||||||
Assert.Equal(orgUserId, result.First().Item1);
|
Assert.Equal(orgUserId, result.First().Item1);
|
||||||
Assert.Contains("Member not found.", result.First().Item2);
|
Assert.Contains("Member not found.", result.First().Item2);
|
||||||
|
await sutProvider.GetDependency<IUserService>().Received(1).DeleteManyAsync(Arg.Any<IEnumerable<User>>());
|
||||||
|
await sutProvider.GetDependency<IEventService>().Received(0)
|
||||||
|
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[BitAutoData]
|
||||||
|
public async Task DeleteManyUsersAsync_WhenFeatureFlagDisabled_WhenUserNotFound_ReturnsErrorMessage(
|
||||||
|
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider,
|
||||||
|
Guid organizationId,
|
||||||
|
Guid orgUserId)
|
||||||
|
{
|
||||||
|
// Arrang
|
||||||
|
sutProvider.GetDependency<IFeatureService>()
|
||||||
|
.IsEnabled(FeatureFlagKeys.AccountDeprovisioning).Returns(false);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, new[] { orgUserId }, null);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
Assert.Single(result);
|
||||||
|
Assert.Equal(orgUserId, result.First().Item1);
|
||||||
|
Assert.Contains("Member not found.", result.First().Item2);
|
||||||
|
await sutProvider.GetDependency<IUserService>().Received(0).DeleteManyAsync(Arg.Any<IEnumerable<User>>());
|
||||||
await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
|
await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
|
||||||
await sutProvider.GetDependency<IEventService>().Received(0)
|
await sutProvider.GetDependency<IEventService>().Received(0)
|
||||||
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
|
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
|
||||||
|
Loading…
Reference in New Issue
Block a user