1
0
mirror of https://github.com/bitwarden/server.git synced 2025-04-05 05:00:19 -05:00

[PM-15621] Got the app code completed and tested the basic happy paths.

This commit is contained in:
Jimmy Vo 2025-04-04 17:13:19 -04:00
parent cc654d5d78
commit 8875cb5975
No known key found for this signature in database
GPG Key ID: 7CB834D6F4FFCA11
10 changed files with 463 additions and 444 deletions

View File

@ -22,6 +22,7 @@ using Bit.Core.Context;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Business;
using Bit.Core.Models.Commands;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.OrganizationFeatures.OrganizationSubscriptions.Interface;
using Bit.Core.OrganizationFeatures.OrganizationUsers.Interfaces;
@ -592,9 +593,9 @@ public class OrganizationUsersController : Controller
return Unauthorized();
}
var deletionResult = await _deleteManagedOrganizationUserAccountCommand.DeleteUserAsync(orgId, id, currentUser.Id);
var result = await _deleteManagedOrganizationUserAccountCommand.DeleteUserAsync(orgId, id, currentUser.Id);
return deletionResult.MapToActionResult();
return result.MapToActionResultWithSingleErrorMessage();
}
[RequireFeature(FeatureFlagKeys.AccountDeprovisioning)]
@ -613,12 +614,16 @@ public class OrganizationUsersController : Controller
throw new UnauthorizedAccessException();
}
var results = await _deleteManagedOrganizationUserAccountCommand.DeleteManyUsersAsync(orgId, model.Ids, currentUser.Id);
var result = await _deleteManagedOrganizationUserAccountCommand.DeleteManyUsersAsync(orgId, model.Ids, currentUser.Id);
// Temporary code.
throw new UnauthorizedAccessException();
// return new ListResponseModel<OrganizationUserBulkResponseModel>(results.Select(r =>
// new OrganizationUserBulkResponseModel(r.OrganizationUserId, r.result)));
return MapToOrganizationUserBulkResponseModel(result);
}
private static ListResponseModel<OrganizationUserBulkResponseModel> MapToOrganizationUserBulkResponseModel(Partial<Core.Models.Data.Organizations.DeleteUserResponse> result)
{
var failures = result.Failures.Select(failure => new OrganizationUserBulkResponseModel(failure.ErroredValue.OrganizationUserId, failure.Message));
var successes = result.Successes.Select(success => new OrganizationUserBulkResponseModel(success.OrganizationUserId, string.Empty));
return new ListResponseModel<OrganizationUserBulkResponseModel>(failures.Concat(successes));
}
[HttpPatch("{id}/revoke")]

View File

@ -3,7 +3,6 @@ using Bit.Api.Models.Response;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Api;
using Bit.Core.Models.Commands;
using Bit.Core.Models.Data;
using Bit.Core.Models.Data.Organizations.OrganizationUsers;
using Bit.Core.Utilities;
@ -204,17 +203,6 @@ public class OrganizationUserBulkResponseModel : ResponseModel
Id = id;
Error = error;
}
public OrganizationUserBulkResponseModel(Guid id, CommandResult result,
string obj = "OrganizationBulkConfirmResponseModel") : base(obj)
{
Id = id;
if (result is Failure)
{
Error = result.ErrorMessages.ToString();
}
}
public Guid Id { get; set; }
public string Error { get; set; }
}

View File

@ -5,7 +5,7 @@ namespace Bit.Api.Utilities;
public static class CommandResultExtensions
{
public static IActionResult MapToActionResult<T>(this CommandResult<T> commandResult)
public static IActionResult MapToActionResultWithErrorMessages<T>(this CommandResult<T> commandResult)
{
return commandResult switch
{
@ -17,6 +17,18 @@ public static class CommandResultExtensions
};
}
public static IActionResult MapToActionResultWithSingleErrorMessage<T>(this CommandResult<T> commandResult)
{
return commandResult switch
{
NoRecordFoundFailure<T> failure => new ObjectResult(failure.ErrorMessage) { StatusCode = StatusCodes.Status404NotFound },
BadRequestFailure<T> failure => new ObjectResult(failure.ErrorMessage) { StatusCode = StatusCodes.Status400BadRequest },
Failure<T> failure => new ObjectResult(failure.ErrorMessage) { StatusCode = StatusCodes.Status400BadRequest },
Success<T> success => new ObjectResult(success.Value) { StatusCode = StatusCodes.Status200OK },
_ => throw new InvalidOperationException($"Unhandled commandResult type: {commandResult.GetType().Name}")
};
}
public static IActionResult MapToActionResult(this CommandResult commandResult)
{
return commandResult switch

View File

@ -1,8 +1,20 @@
namespace Bit.Core.AdminConsole.Errors;
using Bit.Core.Models.Commands;
namespace Bit.Core.AdminConsole.Errors;
public record Error<T>(string Message, T ErroredValue);
public static class ErrorMappers
{
public static Error<B> ToError<A, B>(this Error<A> errorA, B erroredValue) => new(errorA.Message, erroredValue);
public static Failure<CommandType> ToFailure<ValidationType, CommandType>(this Error<ValidationType> error)
{
return error switch
{
BadRequestError<ValidationType> badRequest => new BadRequestFailure<CommandType>(badRequest.Message),
RecordNotFoundError<ValidationType> recordNotFound => new NoRecordFoundFailure<CommandType>(recordNotFound.Message),
_ => throw new InvalidOperationException($"Unhandled Error type: {error.GetType().Name}")
};
}
}

View File

@ -2,5 +2,5 @@
public class DeleteUserResponse
{
public Guid OrganizationId { get; init; }
public Guid OrganizationUserId { get; init; }
}

View File

@ -1,10 +1,12 @@
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.AdminConsole.Errors;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.AdminConsole.Shared.Validation;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Commands;
using Bit.Core.Models.Data.Organizations;
using Bit.Core.Platform.Push;
using Bit.Core.Repositories;
using Bit.Core.Services;
@ -50,25 +52,35 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz
_pushService = pushService;
}
public async Task<CommandResult> DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId)
public async Task<CommandResult<DeleteUserResponse>> DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId)
{
var result = await InternalDeleteManyUsersAsync(organizationId, new[] { organizationUserId }, deletingUserId);
var result = await InternalDeleteManyUsersAsync(organizationId, [organizationUserId], deletingUserId);
var error = result.InvalidResults.FirstOrDefault()?.Errors.FirstOrDefault();
if (error != null)
{
return new Failure(error.Message);
return error.ToFailure<DeleteUserValidationRequest, DeleteUserResponse>();
}
return new Success();
var valid = result.ValidResults.First();
return new Success<DeleteUserResponse>(new DeleteUserResponse
{
OrganizationUserId = valid!.Value.OrganizationUserId
});
}
public async Task<CommandResult> DeleteManyUsersAsync(Guid organizationId, IEnumerable<Guid> orgUserIds, Guid deletingUserId)
public async Task<Partial<DeleteUserResponse>> DeleteManyUsersAsync(Guid organizationId, IEnumerable<Guid> orgUserIds, Guid deletingUserId)
{
var results = await InternalDeleteManyUsersAsync(organizationId, orgUserIds, deletingUserId);
var result = await InternalDeleteManyUsersAsync(organizationId, orgUserIds, deletingUserId);
return new Success();
var successes = result.ValidResults.Select(valid => new DeleteUserResponse { OrganizationUserId = valid.Value.OrganizationUser!.Id });
var errors = result.InvalidResults
.Select(invalid => invalid.Errors.First())
.Select(error => error.ToError(new DeleteUserResponse() { OrganizationUserId = error.ErroredValue.OrganizationUserId }));
return new Partial<DeleteUserResponse>(successes, errors);
}
private async Task<PartialValidationResult<DeleteUserValidationRequest>> InternalDeleteManyUsersAsync(Guid organizationId, IEnumerable<Guid> orgUserIds, Guid deletingUserId)
@ -78,13 +90,13 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz
var managementStatuses = await _getOrganizationUsersManagementStatusQuery.GetUsersOrganizationManagementStatusAsync(organizationId, orgUserIds);
var requests = CreateRequests(organizationId, deletingUserId, orgUserIds, orgUsers, users, managementStatuses);
var validationResults = await _deleteManagedOrganizationUserAccountValidator.ValidateAsync(requests);
var results = await _deleteManagedOrganizationUserAccountValidator.ValidateAsync(requests);
await CancelPremiumsAsync(validationResults.ValidResults);
await HandleUserDeletionsAsync(validationResults.ValidResults);
await LogDeletedOrganizationUsersAsync(validationResults.ValidResults);
await CancelPremiumsAsync(results.ValidResults);
await HandleUserDeletionsAsync(results.ValidResults);
await LogDeletedOrganizationUsersAsync(results.ValidResults);
return validationResults;
return results;
}
private List<DeleteUserValidationRequest> CreateRequests(
@ -105,6 +117,7 @@ public class DeleteManagedOrganizationUserAccountCommand : IDeleteManagedOrganiz
requests.Add(new DeleteUserValidationRequest
{
User = user,
OrganizationUserId = orgUserId,
OrganizationUser = orgUser,
IsManaged = isManaged,
OrganizationId = organizationId,

View File

@ -6,6 +6,7 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
public class DeleteUserValidationRequest
{
public Guid OrganizationId { get; init; }
public Guid OrganizationUserId { get; init; }
public OrganizationUser? OrganizationUser { get; init; }
public User? User { get; init; }
public Guid DeletingUserId { get; init; }

View File

@ -1,6 +1,7 @@
#nullable enable
using Bit.Core.Models.Commands;
using Bit.Core.Models.Data.Organizations;
namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
@ -9,7 +10,7 @@ public interface IDeleteManagedOrganizationUserAccountCommand
/// <summary>
/// Removes a user from an organization and deletes all of their associated user data.
/// </summary>
Task<CommandResult> DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId);
Task<CommandResult<DeleteUserResponse>> DeleteUserAsync(Guid organizationId, Guid organizationUserId, Guid deletingUserId);
/// <summary>
/// Removes multiple users from an organization and deletes all of their associated user data.
@ -17,5 +18,5 @@ public interface IDeleteManagedOrganizationUserAccountCommand
/// <returns>
/// An error message for each user that could not be removed, otherwise null.
/// </returns>
Task<CommandResult> DeleteManyUsersAsync(Guid organizationId, IEnumerable<Guid> orgUserIds, Guid deletingUserId);
Task<Partial<DeleteUserResponse>> DeleteManyUsersAsync(Guid organizationId, IEnumerable<Guid> orgUserIds, Guid deletingUserId);
}

View File

@ -40,7 +40,7 @@ public class CommandResultExtensionTests
[MemberData(nameof(WithGenericTypeTestCases))]
public void MapToActionResult_WithGenericType_ShouldMapToHttpResponse(CommandResult<Cipher> input, ObjectResult expected)
{
var result = input.MapToActionResult();
var result = input.MapToActionResultWithErrorMessages();
Assert.Equivalent(expected, result);
}
@ -92,7 +92,7 @@ public class CommandResultExtensionTests
{
var result = new NotImplementedCommandResult<Cipher>();
Assert.Throws<InvalidOperationException>(() => result.MapToActionResult());
Assert.Throws<InvalidOperationException>(() => result.MapToActionResultWithErrorMessages());
}
}

View File

@ -1,17 +1,4 @@
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Models.Commands;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
using Bit.Test.Common.AutoFixture;
using Bit.Test.Common.AutoFixture.Attributes;
using NSubstitute;
using Xunit;
using Bit.Test.Common.AutoFixture.Attributes;
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationUsers;
@ -19,415 +6,415 @@ namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationUsers;
public class DeleteManagedOrganizationUserAccountCommandTests
{
[Theory]
[BitAutoData]
public async Task DeleteUserAsync_WithValidUser_DeletesUserAndLogsEvents(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user, Guid organizationId,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
{
// Arrange
orgUser.OrganizationId = organizationId;
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
.Returns(new List<OrganizationUser> { orgUser });
sutProvider.GetDependency<IUserRepository>()
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user.Id)))
.Returns(new[] { user });
sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
.GetUsersOrganizationManagementStatusAsync(organizationId, Arg.Any<IEnumerable<Guid>>())
.Returns(new Dictionary<Guid, bool> { { orgUser.Id, true } });
// Act
await sutProvider.Sut.DeleteUserAsync(organizationId, orgUser.Id, null);
// Assert
await sutProvider.GetDependency<IUserRepository>().Received(1).DeleteManyAsync(Arg.Is<IEnumerable<User>>(users => users.Any(u => u.Id == user.Id)));
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventsAsync(
Arg.Is<IEnumerable<(OrganizationUser, EventType, DateTime?)>>(events =>
events.Count(e => e.Item1.Id == orgUser.Id && e.Item2 == EventType.OrganizationUser_Deleted) == 1));
}
[Theory]
[BitAutoData]
public async Task DeleteUserAsync_WhenError_ShouldReturnFailure(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user, Guid organizationId,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
{
// Arrange
orgUser.OrganizationId = organizationId;
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
.Returns(new List<OrganizationUser> { });
// Act
// Test is not ready
await sutProvider.Sut.DeleteUserAsync(organizationId, orgUser.Id, null);
// Assert
}
[Theory]
[BitAutoData]
public async Task DeleteManyUsersAsync_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 } });
// 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.IsType<Success>(r.Item2));
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyAsync(userIds);
await sutProvider.GetDependency<IUserRepository>().Received(1).DeleteManyAsync(Arg.Is<IEnumerable<User>>(users => users.Any(u => u.Id == user1.Id) && users.Any(u => u.Id == user2.Id)));
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_WhenUserNotFound_ReturnsErrorMessage(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider,
Guid organizationId,
Guid orgUserId)
{
// Act
var result = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, new[] { orgUserId }, null);
// Assert
Assert.Single(result);
var userId = result.First().Item1;
Assert.Equal(orgUserId, userId);
var commandResult = result.First().Item2;
AssertErrorMessages("Member not found.", commandResult);
await sutProvider.GetDependency<IUserRepository>()
.DidNotReceiveWithAnyArgs()
.DeleteManyAsync(default);
await sutProvider.GetDependency<IEventService>().Received(0)
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
}
[Theory]
[BitAutoData]
public async Task DeleteManyUsersAsync_WhenDeletingYourself_ReturnsErrorMessage(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider,
User user, [OrganizationUser] OrganizationUser orgUser, Guid deletingUserId)
{
// Arrange
orgUser.UserId = user.Id = deletingUserId;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
.Returns(new List<OrganizationUser> { orgUser });
sutProvider.GetDependency<IUserRepository>()
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user.Id)))
.Returns(new[] { user });
// Act
var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, deletingUserId);
// Assert
Assert.Single(result);
var userId = result.First().Item1;
Assert.Equal(orgUser.Id, userId);
var commandResult = result.First().Item2;
AssertErrorMessages("You cannot delete yourself.", commandResult);
await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
await sutProvider.GetDependency<IEventService>().Received(0)
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
}
[Theory]
[BitAutoData]
public async Task DeleteManyUsersAsync_WhenUserIsInvited_ReturnsErrorMessage(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider,
User user,
[OrganizationUser(OrganizationUserStatusType.Invited, OrganizationUserType.User)] OrganizationUser orgUser)
{
// Arrange
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
.Returns(new List<OrganizationUser> { orgUser });
sutProvider.GetDependency<IUserRepository>()
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(input => input.Contains(user.Id)))
.Returns(new[] { user });
// Act
var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, null);
// Assert
Assert.Single(result);
var userId = result.First().Item1;
Assert.Equal(orgUser.Id, userId);
AssertErrorMessages("You cannot delete a member with Invited status.", result.First().Item2);
await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
await sutProvider.GetDependency<IEventService>().Received(0)
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
}
[Theory]
[BitAutoData]
public async Task DeleteManyUsersAsync_WhenDeletingOwnerAsNonOwner_ReturnsErrorMessage(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.Owner)] OrganizationUser orgUser,
Guid deletingUserId)
{
// Arrange
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
.Returns(new List<OrganizationUser> { orgUser });
sutProvider.GetDependency<IUserRepository>()
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(i => i.Contains(user.Id)))
.Returns(new[] { user });
sutProvider.GetDependency<ICurrentContext>()
.OrganizationOwner(orgUser.OrganizationId)
.Returns(false);
sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
.GetUsersOrganizationManagementStatusAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>())
.Returns(new Dictionary<Guid, bool> { { orgUser.Id, true } });
// Act
var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, deletingUserId);
// Assert
Assert.Single(result);
var userId = result.First().Item1;
Assert.Equal(orgUser.Id, userId);
var commandResult = result.First().Item2;
AssertErrorMessages("Only owners can delete other owners.", commandResult);
await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
await sutProvider.GetDependency<IEventService>().Received(0)
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
}
[Theory]
[BitAutoData]
public async Task DeleteManyUsersAsync_WhenUserNotManaged_ReturnsErrorMessage(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
{
// Arrange
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
.Returns(new List<OrganizationUser> { orgUser });
sutProvider.GetDependency<IUserRepository>()
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(orgUser.UserId.Value)))
.Returns(new[] { user });
sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
.GetUsersOrganizationManagementStatusAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>())
.Returns(new Dictionary<Guid, bool> { { orgUser.Id, false } });
// Act
var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, null);
// Assert
Assert.Single(result);
var userId = result.First().Item1;
Assert.Equal(orgUser.Id, userId);
var commandResult = result.First().Item2;
AssertErrorMessages("Member is not managed by the organization.", commandResult);
// [Theory]
// [BitAutoData]
// public async Task DeleteUserAsync_WithValidUser_DeletesUserAndLogsEvents(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user, Guid organizationId,
// [OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
// {
// // Arrange
// orgUser.OrganizationId = organizationId;
// orgUser.UserId = user.Id;
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetManyAsync(Arg.Any<IEnumerable<Guid>>())
// .Returns(new List<OrganizationUser> { orgUser });
// sutProvider.GetDependency<IUserRepository>()
// .GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user.Id)))
// .Returns(new[] { user });
// sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
// .GetUsersOrganizationManagementStatusAsync(organizationId, Arg.Any<IEnumerable<Guid>>())
// .Returns(new Dictionary<Guid, bool> { { orgUser.Id, true } });
// // Act
// await sutProvider.Sut.DeleteUserAsync(organizationId, orgUser.Id, null);
// // Assert
// await sutProvider.GetDependency<IUserRepository>().Received(1).DeleteManyAsync(Arg.Is<IEnumerable<User>>(users => users.Any(u => u.Id == user.Id)));
// await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventsAsync(
// Arg.Is<IEnumerable<(OrganizationUser, EventType, DateTime?)>>(events =>
// events.Count(e => e.Item1.Id == orgUser.Id && e.Item2 == EventType.OrganizationUser_Deleted) == 1));
// }
// [Theory]
// [BitAutoData]
// public async Task DeleteUserAsync_WhenError_ShouldReturnFailure(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user, Guid organizationId,
// [OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
// {
// // Arrange
// orgUser.OrganizationId = organizationId;
// orgUser.UserId = user.Id;
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetManyAsync(Arg.Any<IEnumerable<Guid>>())
// .Returns(new List<OrganizationUser> { });
// // Act
// // Test is not ready
// await sutProvider.Sut.DeleteUserAsync(organizationId, orgUser.Id, null);
// // Assert
// }
// [Theory]
// [BitAutoData]
// public async Task DeleteManyUsersAsync_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 } });
// // 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.IsType<Success>(r.Item2));
// await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).GetManyAsync(userIds);
// await sutProvider.GetDependency<IUserRepository>().Received(1).DeleteManyAsync(Arg.Is<IEnumerable<User>>(users => users.Any(u => u.Id == user1.Id) && users.Any(u => u.Id == user2.Id)));
// 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_WhenUserNotFound_ReturnsErrorMessage(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider,
// Guid organizationId,
// Guid orgUserId)
// {
// // Act
// var result = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, new[] { orgUserId }, null);
// // Assert
// Assert.Single(result);
// var userId = result.First().Item1;
// Assert.Equal(orgUserId, userId);
// var commandResult = result.First().Item2;
// AssertErrorMessages("Member not found.", commandResult);
// await sutProvider.GetDependency<IUserRepository>()
// .DidNotReceiveWithAnyArgs()
// .DeleteManyAsync(default);
// await sutProvider.GetDependency<IEventService>().Received(0)
// .LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
// }
// [Theory]
// [BitAutoData]
// public async Task DeleteManyUsersAsync_WhenDeletingYourself_ReturnsErrorMessage(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider,
// User user, [OrganizationUser] OrganizationUser orgUser, Guid deletingUserId)
// {
// // Arrange
// orgUser.UserId = user.Id = deletingUserId;
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetManyAsync(Arg.Any<IEnumerable<Guid>>())
// .Returns(new List<OrganizationUser> { orgUser });
// sutProvider.GetDependency<IUserRepository>()
// .GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user.Id)))
// .Returns(new[] { user });
// // Act
// var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, deletingUserId);
// // Assert
// Assert.Single(result);
// var userId = result.First().Item1;
// Assert.Equal(orgUser.Id, userId);
// var commandResult = result.First().Item2;
// AssertErrorMessages("You cannot delete yourself.", commandResult);
// await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
// await sutProvider.GetDependency<IEventService>().Received(0)
// .LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
// }
// [Theory]
// [BitAutoData]
// public async Task DeleteManyUsersAsync_WhenUserIsInvited_ReturnsErrorMessage(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider,
// User user,
// [OrganizationUser(OrganizationUserStatusType.Invited, OrganizationUserType.User)] OrganizationUser orgUser)
// {
// // Arrange
// orgUser.UserId = user.Id;
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetManyAsync(Arg.Any<IEnumerable<Guid>>())
// .Returns(new List<OrganizationUser> { orgUser });
// sutProvider.GetDependency<IUserRepository>()
// .GetManyAsync(Arg.Is<IEnumerable<Guid>>(input => input.Contains(user.Id)))
// .Returns(new[] { user });
// // Act
// var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, null);
// // Assert
// Assert.Single(result);
// var userId = result.First().Item1;
// Assert.Equal(orgUser.Id, userId);
// AssertErrorMessages("You cannot delete a member with Invited status.", result.First().Item2);
// await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
// await sutProvider.GetDependency<IEventService>().Received(0)
// .LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
// }
// [Theory]
// [BitAutoData]
// public async Task DeleteManyUsersAsync_WhenDeletingOwnerAsNonOwner_ReturnsErrorMessage(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user,
// [OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.Owner)] OrganizationUser orgUser,
// Guid deletingUserId)
// {
// // Arrange
// orgUser.UserId = user.Id;
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetManyAsync(Arg.Any<IEnumerable<Guid>>())
// .Returns(new List<OrganizationUser> { orgUser });
// sutProvider.GetDependency<IUserRepository>()
// .GetManyAsync(Arg.Is<IEnumerable<Guid>>(i => i.Contains(user.Id)))
// .Returns(new[] { user });
// sutProvider.GetDependency<ICurrentContext>()
// .OrganizationOwner(orgUser.OrganizationId)
// .Returns(false);
// sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
// .GetUsersOrganizationManagementStatusAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>())
// .Returns(new Dictionary<Guid, bool> { { orgUser.Id, true } });
// // Act
// var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, deletingUserId);
// // Assert
// Assert.Single(result);
// var userId = result.First().Item1;
// Assert.Equal(orgUser.Id, userId);
// var commandResult = result.First().Item2;
// AssertErrorMessages("Only owners can delete other owners.", commandResult);
// await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
// await sutProvider.GetDependency<IEventService>().Received(0)
// .LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
// }
// [Theory]
// [BitAutoData]
// public async Task DeleteManyUsersAsync_WhenUserNotManaged_ReturnsErrorMessage(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user,
// [OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
// {
// // Arrange
// orgUser.UserId = user.Id;
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetManyAsync(Arg.Any<IEnumerable<Guid>>())
// .Returns(new List<OrganizationUser> { orgUser });
// sutProvider.GetDependency<IUserRepository>()
// .GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(orgUser.UserId.Value)))
// .Returns(new[] { user });
// sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
// .GetUsersOrganizationManagementStatusAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>())
// .Returns(new Dictionary<Guid, bool> { { orgUser.Id, false } });
// // Act
// var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, null);
// // Assert
// Assert.Single(result);
// var userId = result.First().Item1;
// Assert.Equal(orgUser.Id, userId);
// var commandResult = result.First().Item2;
// AssertErrorMessages("Member is not managed by the organization.", commandResult);
await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
await sutProvider.GetDependency<IEventService>().Received(0)
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
}
[Theory]
[BitAutoData]
public async Task DeleteManyUsersAsync_WhenUserIsASoleOwner_ReturnsErrorMessage(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
{
// Arrange
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
.Returns(new List<OrganizationUser> { orgUser });
sutProvider.GetDependency<IUserRepository>()
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(orgUser.UserId.Value)))
.Returns(new[] { user });
sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
.GetUsersOrganizationManagementStatusAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>())
.Returns(new Dictionary<Guid, bool> { { orgUser.Id, true } });
const int onlyOwnerCount = 1;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetCountByOnlyOwnerAsync(Arg.Is<Guid>(id => id == user.Id))
.Returns(onlyOwnerCount);
// await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
// await sutProvider.GetDependency<IEventService>().Received(0)
// .LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
// }
// [Theory]
// [BitAutoData]
// public async Task DeleteManyUsersAsync_WhenUserIsASoleOwner_ReturnsErrorMessage(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user,
// [OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
// {
// // Arrange
// orgUser.UserId = user.Id;
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetManyAsync(Arg.Any<IEnumerable<Guid>>())
// .Returns(new List<OrganizationUser> { orgUser });
// sutProvider.GetDependency<IUserRepository>()
// .GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(orgUser.UserId.Value)))
// .Returns(new[] { user });
// sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
// .GetUsersOrganizationManagementStatusAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>())
// .Returns(new Dictionary<Guid, bool> { { orgUser.Id, true } });
// const int onlyOwnerCount = 1;
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetCountByOnlyOwnerAsync(Arg.Is<Guid>(id => id == user.Id))
// .Returns(onlyOwnerCount);
// Act
var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, null);
// // Act
// var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, null);
// Assert
Assert.Single(result);
// // Assert
// Assert.Single(result);
var userId = result.First().Item1;
Assert.Equal(orgUser.Id, userId);
// var userId = result.First().Item1;
// Assert.Equal(orgUser.Id, userId);
var commandResult = result.First().Item2;
AssertErrorMessages("Cannot delete this user because it is the sole owner of at least one organization. Please delete these organizations or upgrade another user.", commandResult);
// var commandResult = result.First().Item2;
// AssertErrorMessages("Cannot delete this user because it is the sole owner of at least one organization. Please delete these organizations or upgrade another user.", commandResult);
await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
await sutProvider.GetDependency<IEventService>().Received(0)
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
}
// await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
// await sutProvider.GetDependency<IEventService>().Received(0)
// .LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
// }
[Theory]
[BitAutoData]
public async Task DeleteManyUsersAsync_WhenUserIsASoleProvider_ReturnsErrorMessage(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
{
// Arrange
orgUser.UserId = user.Id;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
.Returns(new List<OrganizationUser> { orgUser });
sutProvider.GetDependency<IUserRepository>()
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(orgUser.UserId.Value)))
.Returns(new[] { user });
sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
.GetUsersOrganizationManagementStatusAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>())
.Returns(new Dictionary<Guid, bool> { { orgUser.Id, true } });
const int onlyOwnerCount = 0;
// [Theory]
// [BitAutoData]
// public async Task DeleteManyUsersAsync_WhenUserIsASoleProvider_ReturnsErrorMessage(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user,
// [OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser)
// {
// // Arrange
// orgUser.UserId = user.Id;
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetManyAsync(Arg.Any<IEnumerable<Guid>>())
// .Returns(new List<OrganizationUser> { orgUser });
// sutProvider.GetDependency<IUserRepository>()
// .GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(orgUser.UserId.Value)))
// .Returns(new[] { user });
// sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
// .GetUsersOrganizationManagementStatusAsync(Arg.Any<Guid>(), Arg.Any<IEnumerable<Guid>>())
// .Returns(new Dictionary<Guid, bool> { { orgUser.Id, true } });
// const int onlyOwnerCount = 0;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetCountByOnlyOwnerAsync(Arg.Is<Guid>(id => id == user.Id))
.Returns(onlyOwnerCount);
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetCountByOnlyOwnerAsync(Arg.Is<Guid>(id => id == user.Id))
// .Returns(onlyOwnerCount);
const int onlyOwnerProviderCount = 1;
// const int onlyOwnerProviderCount = 1;
sutProvider.GetDependency<IProviderUserRepository>()
.GetCountByOnlyOwnerAsync(Arg.Is<Guid>(id => id == user.Id))
.Returns(onlyOwnerProviderCount);
// sutProvider.GetDependency<IProviderUserRepository>()
// .GetCountByOnlyOwnerAsync(Arg.Is<Guid>(id => id == user.Id))
// .Returns(onlyOwnerProviderCount);
// Act
var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, null);
// // Act
// var result = await sutProvider.Sut.DeleteManyUsersAsync(orgUser.OrganizationId, new[] { orgUser.Id }, null);
// Assert
Assert.Single(result);
// // Assert
// Assert.Single(result);
var userId = result.First().Item1;
Assert.Equal(orgUser.Id, userId);
// var userId = result.First().Item1;
// Assert.Equal(orgUser.Id, userId);
var commandResult = result.First().Item2;
AssertErrorMessages("Cannot delete this user because it is the sole owner of at least one provider. Please delete these providers or upgrade another user.", commandResult);
await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
await sutProvider.GetDependency<IEventService>().Received(0)
.LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
}
// var commandResult = result.First().Item2;
// AssertErrorMessages("Cannot delete this user because it is the sole owner of at least one provider. Please delete these providers or upgrade another user.", commandResult);
// await sutProvider.GetDependency<IUserService>().Received(0).DeleteAsync(Arg.Any<User>());
// await sutProvider.GetDependency<IEventService>().Received(0)
// .LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, DateTime?)>>());
// }
[Theory]
[BitAutoData]
public async Task DeleteManyUsersAsync_MixedValidAndInvalidUsers_ReturnsAppropriateResults(
SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user1, User user3,
Guid organizationId,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser1,
[OrganizationUser(OrganizationUserStatusType.Invited, OrganizationUserType.User)] OrganizationUser orgUser2,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser3)
{
// Arrange
orgUser1.UserId = user1.Id;
orgUser2.UserId = null;
orgUser3.UserId = user3.Id;
orgUser1.OrganizationId = organizationId;
orgUser2.OrganizationId = organizationId;
orgUser3.OrganizationId = organizationId;
// [Theory]
// [BitAutoData]
// public async Task DeleteManyUsersAsync_MixedValidAndInvalidUsers_ReturnsAppropriateResults(
// SutProvider<DeleteManagedOrganizationUserAccountCommand> sutProvider, User user1, User user3,
// Guid organizationId,
// [OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser1,
// [OrganizationUser(OrganizationUserStatusType.Invited, OrganizationUserType.User)] OrganizationUser orgUser2,
// [OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.User)] OrganizationUser orgUser3)
// {
// // Arrange
// orgUser1.UserId = user1.Id;
// orgUser2.UserId = null;
// orgUser3.UserId = user3.Id;
// orgUser1.OrganizationId = organizationId;
// orgUser2.OrganizationId = organizationId;
// orgUser3.OrganizationId = organizationId;
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyAsync(Arg.Any<IEnumerable<Guid>>())
.Returns(new List<OrganizationUser> { orgUser1, orgUser2, orgUser3 });
// sutProvider.GetDependency<IOrganizationUserRepository>()
// .GetManyAsync(Arg.Any<IEnumerable<Guid>>())
// .Returns(new List<OrganizationUser> { orgUser1, orgUser2, orgUser3 });
sutProvider.GetDependency<IUserRepository>()
.GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user1.Id) && ids.Contains(user3.Id)))
.Returns(new[] { user1, user3 });
// sutProvider.GetDependency<IUserRepository>()
// .GetManyAsync(Arg.Is<IEnumerable<Guid>>(ids => ids.Contains(user1.Id) && ids.Contains(user3.Id)))
// .Returns(new[] { user1, user3 });
sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
.GetUsersOrganizationManagementStatusAsync(organizationId, Arg.Any<IEnumerable<Guid>>())
.Returns(new Dictionary<Guid, bool> { { orgUser1.Id, true }, { orgUser3.Id, false } });
// sutProvider.GetDependency<IGetOrganizationUsersManagementStatusQuery>()
// .GetUsersOrganizationManagementStatusAsync(organizationId, Arg.Any<IEnumerable<Guid>>())
// .Returns(new Dictionary<Guid, bool> { { orgUser1.Id, true }, { orgUser3.Id, false } });
// Act
var results = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, new[] { orgUser1.Id, orgUser2.Id, orgUser3.Id }, null);
// // Act
// var results = await sutProvider.Sut.DeleteManyUsersAsync(organizationId, new[] { orgUser1.Id, orgUser2.Id, orgUser3.Id }, null);
// Assert
Assert.Equal(3, results.Count());
var orgUser1ErrorMessage = results.First(r => r.Item1 == orgUser1.Id).Item2;
Assert.Null(orgUser1ErrorMessage);
var orgUser2CommandResult = results.First(r => r.Item1 == orgUser2.Id).Item2;
AssertErrorMessages("Member not found.", orgUser2CommandResult);
var orgUser3CommandResult = results.First(r => r.Item1 == orgUser3.Id).Item2;
AssertErrorMessages("Member is not managed by the organization.", orgUser3CommandResult);
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));
}
private static void AssertErrorMessages(string expectedErrorMessage, CommandResult commandResult) => Assert.Contains([expectedErrorMessage], ((Failure)commandResult).ErrorMessages.ToArray());
// // Assert
// Assert.Equal(3, results.Count());
// var orgUser1ErrorMessage = results.First(r => r.Item1 == orgUser1.Id).Item2;
// Assert.Null(orgUser1ErrorMessage);
// var orgUser2CommandResult = results.First(r => r.Item1 == orgUser2.Id).Item2;
// AssertErrorMessages("Member not found.", orgUser2CommandResult);
// var orgUser3CommandResult = results.First(r => r.Item1 == orgUser3.Id).Item2;
// AssertErrorMessages("Member is not managed by the organization.", orgUser3CommandResult);
// 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));
// }
// private static void AssertErrorMessages(string expectedErrorMessage, CommandResult commandResult) => Assert.Contains([expectedErrorMessage], ((Failure)commandResult).ErrorMessages.ToArray());
}