using System.Text.Json; using Bit.Core.AdminConsole.Entities; using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.Models.Data; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Test.AutoFixture.OrganizationUserFixtures; using Bit.Core.Utilities; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.OrganizationUsers; [SutProviderCustomize] public class UpdateOrganizationUserCommandTests { [Theory, BitAutoData] public async Task UpdateUserAsync_NoUserId_Throws(OrganizationUser user, Guid? savingUserId, List collections, IEnumerable groups, SutProvider sutProvider) { user.Id = default(Guid); var exception = await Assert.ThrowsAsync( () => sutProvider.Sut.UpdateUserAsync(user, savingUserId, collections, groups)); Assert.Contains("invite the user first", exception.Message.ToLowerInvariant()); } [Theory, BitAutoData] public async Task UpdateUserAsync_Passes( Organization organization, OrganizationUser oldUserData, OrganizationUser newUserData, List collections, IEnumerable groups, Permissions permissions, [OrganizationUser(type: OrganizationUserType.Owner)] OrganizationUser savingUser, SutProvider sutProvider) { var organizationRepository = sutProvider.GetDependency(); var organizationUserRepository = sutProvider.GetDependency(); var organizationService = sutProvider.GetDependency(); organizationRepository.GetByIdAsync(organization.Id).Returns(organization); // Deprecated with Flexible Collections oldUserData.AccessAll = false; newUserData.AccessAll = false; // Arrange list of collections to make sure Manage is mutually exclusive for (var i = 0; i < collections.Count; i++) { var cas = collections[i]; cas.Manage = i != collections.Count - 1; cas.HidePasswords = i == collections.Count - 1; cas.ReadOnly = i == collections.Count - 1; } newUserData.Id = oldUserData.Id; newUserData.UserId = oldUserData.UserId; newUserData.OrganizationId = savingUser.OrganizationId = oldUserData.OrganizationId = organization.Id; newUserData.Permissions = JsonSerializer.Serialize(permissions, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, }); organizationUserRepository.GetByIdAsync(oldUserData.Id).Returns(oldUserData); organizationUserRepository.GetManyByOrganizationAsync(savingUser.OrganizationId, OrganizationUserType.Owner) .Returns(new List { savingUser }); organizationService .HasConfirmedOwnersExceptAsync( newUserData.OrganizationId, Arg.Is>(i => i.Contains(newUserData.Id))) .Returns(true); await sutProvider.Sut.UpdateUserAsync(newUserData, savingUser.UserId, collections, groups); await organizationService.Received(1).ValidateOrganizationUserUpdatePermissions( newUserData.OrganizationId, newUserData.Type, oldUserData.Type, Arg.Any()); await organizationService.Received(1).ValidateOrganizationCustomPermissionsEnabledAsync( newUserData.OrganizationId, newUserData.Type); await organizationService.Received(1).HasConfirmedOwnersExceptAsync( newUserData.OrganizationId, Arg.Is>(i => i.Contains(newUserData.Id))); } [Theory, BitAutoData] public async Task UpdateUserAsync_WithAccessAll_Throws( Organization organization, [OrganizationUser(type: OrganizationUserType.User)] OrganizationUser oldUserData, [OrganizationUser(type: OrganizationUserType.User)] OrganizationUser newUserData, [OrganizationUser(type: OrganizationUserType.Owner, status: OrganizationUserStatusType.Confirmed)] OrganizationUser savingUser, List collections, IEnumerable groups, SutProvider sutProvider) { newUserData.Id = oldUserData.Id; newUserData.UserId = oldUserData.UserId; newUserData.OrganizationId = oldUserData.OrganizationId = savingUser.OrganizationId = organization.Id; newUserData.Permissions = CoreHelpers.ClassToJsonData(new Permissions()); newUserData.AccessAll = true; sutProvider.GetDependency() .GetByIdAsync(organization.Id) .Returns(organization); sutProvider.GetDependency() .HasConfirmedOwnersExceptAsync( newUserData.OrganizationId, Arg.Is>(i => i.Contains(newUserData.Id))) .Returns(true); sutProvider.GetDependency() .GetByIdAsync(oldUserData.Id) .Returns(oldUserData); sutProvider.GetDependency() .GetManyByOrganizationAsync(organization.Id, OrganizationUserType.Owner) .Returns(new List { savingUser }); var exception = await Assert.ThrowsAsync( () => sutProvider.Sut.UpdateUserAsync(newUserData, oldUserData.UserId, collections, groups)); Assert.Contains("the accessall property has been deprecated", exception.Message.ToLowerInvariant()); } }