using System; using System.Collections.Generic; using System.Threading.Tasks; using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.Models.Data; using Bit.Core.Models.Table; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Test.AutoFixture; using Bit.Core.Test.AutoFixture.Attributes; using Bit.Core.Test.AutoFixture.GroupFixtures; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using Xunit; namespace Bit.Core.Test.Services { public class GroupServiceTests { [Theory, GroupOrganizationAutoData] public async Task SaveAsync_DefaultGroupId_CreatesGroupInRepository(Group group, Organization organization, SutProvider sutProvider) { group.Id = default(Guid); sutProvider.GetDependency().GetByIdAsync(organization.Id).Returns(organization); organization.UseGroups = true; var utcNow = DateTime.UtcNow; await sutProvider.Sut.SaveAsync(group); await sutProvider.GetDependency().Received().CreateAsync(group); await sutProvider.GetDependency().Received() .LogGroupEventAsync(group, EventType.Group_Created); Assert.True(group.CreationDate - utcNow < TimeSpan.FromSeconds(1)); Assert.True(group.RevisionDate - utcNow < TimeSpan.FromSeconds(1)); } [Theory, GroupOrganizationAutoData] public async Task SaveAsync_DefaultGroupIdAndCollections_CreatesGroupInRepository(Group group, Organization organization, List collections, SutProvider sutProvider) { group.Id = default(Guid); sutProvider.GetDependency().GetByIdAsync(organization.Id).Returns(organization); organization.UseGroups = true; var utcNow = DateTime.UtcNow; await sutProvider.Sut.SaveAsync(group, collections); await sutProvider.GetDependency().Received().CreateAsync(group, collections); await sutProvider.GetDependency().Received() .LogGroupEventAsync(group, EventType.Group_Created); Assert.True(group.CreationDate - utcNow < TimeSpan.FromSeconds(1)); Assert.True(group.RevisionDate - utcNow < TimeSpan.FromSeconds(1)); } [Theory, GroupOrganizationAutoData] public async Task SaveAsync_NonDefaultGroupId_ReplaceGroupInRepository(Group group, Organization organization, List collections, SutProvider sutProvider) { organization.UseGroups = true; sutProvider.GetDependency().GetByIdAsync(organization.Id).Returns(organization); await sutProvider.Sut.SaveAsync(group, collections); await sutProvider.GetDependency().Received().ReplaceAsync(group, collections); await sutProvider.GetDependency().Received() .LogGroupEventAsync(group, EventType.Group_Updated); Assert.True(group.RevisionDate - DateTime.UtcNow < TimeSpan.FromSeconds(1)); } [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task SaveAsync_NonExistingOrganizationId_ThrowsBadRequest(Group group, Organization organization, SutProvider sutProvider) { var exception = await Assert.ThrowsAsync( () => sutProvider.Sut.SaveAsync(group)); Assert.Contains("Organization not found", exception.Message); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().CreateAsync(default); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().ReplaceAsync(default); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().LogGroupEventAsync(default, default, default); } [Theory, GroupOrganizationNotUseGroupsAutoData] public async Task SaveAsync_OrganizationDoesNotUseGroups_ThrowsBadRequest(Group group, Organization organization, SutProvider sutProvider) { sutProvider.GetDependency().GetByIdAsync(organization.Id).Returns(organization); var exception = await Assert.ThrowsAsync( () => sutProvider.Sut.SaveAsync(group)); Assert.Contains("This organization cannot use groups", exception.Message); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().CreateAsync(default); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().ReplaceAsync(default); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().LogGroupEventAsync(default, default, default); } [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task DeleteAsync_ValidData_DeletesGroup(Group group, SutProvider sutProvider) { await sutProvider.Sut.DeleteAsync(group); await sutProvider.GetDependency().Received().DeleteAsync(group); await sutProvider.GetDependency().Received() .LogGroupEventAsync(group, EventType.Group_Deleted); } [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task DeleteUserAsync_ValidData_DeletesUserInGroupRepository(Group group, Organization organization, OrganizationUser organizationUser, SutProvider sutProvider) { group.OrganizationId = organization.Id; organization.UseGroups = true; sutProvider.GetDependency().GetByIdAsync(organization.Id).Returns(organization); organizationUser.OrganizationId = organization.Id; sutProvider.GetDependency().GetByIdAsync(organizationUser.Id) .Returns(organizationUser); await sutProvider.Sut.DeleteUserAsync(group, organizationUser.Id); await sutProvider.GetDependency().Received().DeleteUserAsync(group.Id, organizationUser.Id); await sutProvider.GetDependency().Received() .LogOrganizationUserEventAsync(organizationUser, EventType.OrganizationUser_UpdatedGroups); } [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task DeleteUserAsync_InvalidUser_ThrowsNotFound(Group group, Organization organization, OrganizationUser organizationUser, SutProvider sutProvider) { group.OrganizationId = organization.Id; organization.UseGroups = true; sutProvider.GetDependency().GetByIdAsync(organization.Id).Returns(organization); // organizationUser.OrganizationId = organization.Id; sutProvider.GetDependency().GetByIdAsync(organizationUser.Id) .Returns(organizationUser); // user not in organization await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteUserAsync(group, organizationUser.Id)); // invalid user await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteUserAsync(group, Guid.NewGuid())); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .DeleteUserAsync(default, default); await sutProvider.GetDependency().DidNotReceiveWithAnyArgs() .LogOrganizationUserEventAsync(default, default); } } }