1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 15:42:48 -05:00

Postgres & MySql Support For Self-Hosted Installations (#1386)

* EF Database Support Init (#1221)

* scaffolding for ef support

* deleted old postgres repos

* added tables to oncreate

* updated all the things to .NET 5

* Addition to #1221: Migrated DockerFiles from dotnet/3.1 to  5.0 (#1223)

* Migrated DockerFiles from dotnet/3.1 to  5.0

* Migrated SSO/Dockerfile from dotnet 3.1 to 5.0

Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>

* EFDatabaseSupport: Updated links and description in README.md and SETUP.md (#1232)

* Updated requirements in README.md

* Updated link to documentation of app-secrets

* upgraded dotnet version to 5.0

* Ef database support implementation examples (#1265)

* mostly finished testing the user repo

* finished testing user repo

* finished org, user, ssoconfig, and ssouser ef implementations

* removed unused prop

* fixed a sql file

* fixed a spacing issue

* fixed a spacing issue

* removed extra database creation

* refactoring

* MsSql => SqlServer

* refactoring

* code review fixes

* build fix

* code review

* continued attempts to fix the the build

* skipped another test

* finished all create test

* initial pass at several repos

* continued building out repos

* initial pass at several repos

* initial pass at device repo

* initial pass at collection repo

* initial run of all Entity Framework implementations

* signup, signin, create/edit ciphers works

* sync working

* all web vault pages seem to load with 100% 200s

* bulkcopy, folders, and favorites

* group and collection management

* sso, groups, emergency access, send

* get basic creates matching on all repos

* got everything building again post merge

* removed some IDE config files

* cleanup

* no more notimplemented methods in the cipher repo

* no more not implementeds everywhere

* cleaned up schema/navigation properties and fixed tests

* removed a sql comment that was written in c# style

* fixed build issues from merge

* removed unsupported db providers

* formatting

* code review refactors

* naming cleanup for queries

* added provider methods

* cipher repo cleanup

* implemented several missing procedures from the EF implementation surround account revision dates, keys, and storage

* fixed the build

* added a null check

* consolidated some cipher repo methods

* formatting fix

* cleaned up indentation of queries

* removed .idea file

* generated postgres migrations

* added mysql migrations

* formatting

* Bug Fixes & Formatting

* Formatting

* fixed a bug with bulk import when using MySql

* code review fixes

* fixed the build

* implemented new methods

* formatting

* fixed the build

* cleaned up select statements in ef queries

* formatting

* formatting

* formatting

Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
Addison Beck
2021-07-08 12:35:48 -04:00
committed by GitHub
parent be13eb153a
commit b13dda2799
251 changed files with 21099 additions and 608 deletions

View File

@ -0,0 +1,16 @@
using System;
namespace Bit.Core.Test.AutoFixture.Attributes
{
public sealed class CiSkippedTheory : Xunit.TheoryAttribute
{
private static bool IsGithubActions() => Environment.GetEnvironmentVariable("CI") != null;
public CiSkippedTheory()
{
if(IsGithubActions())
{
Skip = "Ignore during CI builds";
}
}
}
}

View File

@ -1,7 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using AutoFixture;
using AutoFixture.Kernel;
using Bit.Core.Models.Data;
using Bit.Core.Models.Table;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
using Bit.Core.Test.AutoFixture.Relays;
using Bit.Core.Test.AutoFixture.TransactionFixtures;
using Bit.Core.Test.AutoFixture.UserFixtures;
using Core.Models.Data;
namespace Bit.Core.Test.AutoFixture.CipherFixtures
@ -34,6 +47,90 @@ namespace Bit.Core.Test.AutoFixture.CipherFixtures
}
}
internal class CipherBuilder: ISpecimenBuilder
{
public bool OrganizationOwned { get; set; }
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || (type != typeof(Cipher) && type != typeof(List<Cipher>)))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
if (!OrganizationOwned)
{
fixture.Customize<Cipher>(composer => composer
.Without(c => c.OrganizationId));
}
// Can't test valid Favorites and Folders without creating those values inide each test,
// since we won't have any UserIds until the test is running & creating data
fixture.Customize<Cipher>(c => c
.Without(e => e.Favorites)
.Without(e => e.Folders));
//
var serializerOptions = new JsonSerializerOptions(){
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
if(type == typeof(Cipher))
{
var obj = fixture.WithAutoNSubstitutions().Create<Cipher>();
var cipherData = fixture.WithAutoNSubstitutions().Create<CipherLoginData>();
var cipherAttachements = fixture.WithAutoNSubstitutions().Create<List<CipherAttachment>>();
obj.Data = JsonSerializer.Serialize(cipherData, serializerOptions);
obj.Attachments = JsonSerializer.Serialize(cipherAttachements, serializerOptions);
return obj;
}
if (type == typeof(List<Cipher>))
{
var ciphers = fixture.WithAutoNSubstitutions().CreateMany<Cipher>().ToArray();
for (var i = 0; i < ciphers.Count(); i++ )
{
var cipherData = fixture.WithAutoNSubstitutions().Create<CipherLoginData>();
var cipherAttachements = fixture.WithAutoNSubstitutions().Create<List<CipherAttachment>>();
ciphers[i].Data = JsonSerializer.Serialize(cipherData, serializerOptions);
ciphers[i].Attachments = JsonSerializer.Serialize(cipherAttachements, serializerOptions);
}
return ciphers;
}
return new NoSpecimen();
}
}
internal class EfCipher: ICustomization
{
public bool OrganizationOwned { get; set; }
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new CipherBuilder(){
OrganizationOwned = OrganizationOwned
});
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new OrganizationUserBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<CipherRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationUserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<CollectionRepository>());
}
}
internal class UserCipherAutoDataAttribute : CustomAutoDataAttribute
{
public UserCipherAutoDataAttribute(string userId = null) : base(new SutProviderCustomization(),
@ -67,4 +164,25 @@ namespace Bit.Core.Test.AutoFixture.CipherFixtures
typeof(OrganizationCipher) }, values)
{ }
}
internal class EfUserCipherAutoDataAttribute : CustomAutoDataAttribute
{
public EfUserCipherAutoDataAttribute() : base(new SutProviderCustomization(), new EfCipher())
{ }
}
internal class EfOrganizationCipherAutoDataAttribute : CustomAutoDataAttribute
{
public EfOrganizationCipherAutoDataAttribute() : base(new SutProviderCustomization(), new EfCipher(){
OrganizationOwned = true,
})
{ }
}
internal class InlineEfCipherAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfCipherAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfCipher) }, values)
{ }
}
}

View File

@ -0,0 +1,74 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.TransactionFixtures;
using Bit.Core.Test.AutoFixture.Relays;
using Bit.Core.Test.AutoFixture.CollectionFixtures;
using Bit.Core.Test.AutoFixture.CipherFixtures;
using Bit.Core.Test.AutoFixture.UserFixtures;
namespace Bit.Core.Test.AutoFixture.CollectionCipherFixtures
{
internal class CollectionCipherBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.CollectionCipher))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.CollectionCipher>();
return obj;
}
}
internal class EfCollectionCipher: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new CollectionCipherBuilder());
fixture.Customizations.Add(new CollectionBuilder());
fixture.Customizations.Add(new CipherBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<CollectionCipherRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<CollectionRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<CipherRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
}
}
internal class EfCollectionCipherAutoDataAttribute : CustomAutoDataAttribute
{
public EfCollectionCipherAutoDataAttribute() : base(new SutProviderCustomization(), new EfCollectionCipher())
{ }
}
internal class InlineEfCollectionCipherAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfCollectionCipherAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfCollectionCipher) }, values)
{ }
}
}

View File

@ -1,12 +1,73 @@
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
namespace Bit.Core.Test.AutoFixture
{
internal class CollectionAutoDataAttribute : CustomAutoDataAttribute
{
public CollectionAutoDataAttribute() : base(new SutProviderCustomization(), new Organization())
{ }
}
}
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.TransactionFixtures;
using Bit.Core.Test.AutoFixture.Relays;
namespace Bit.Core.Test.AutoFixture.CollectionFixtures
{
internal class CollectionBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Collection))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.Collection>();
return obj;
}
}
internal class EfCollection: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new CollectionBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<CollectionRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfCollectionAutoDataAttribute : CustomAutoDataAttribute
{
public EfCollectionAutoDataAttribute() : base(new SutProviderCustomization(), new EfCollection())
{ }
}
internal class InlineEfCollectionAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfCollectionAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfCollection) }, values)
{ }
}
internal class CollectionAutoDataAttribute : CustomAutoDataAttribute
{
public CollectionAutoDataAttribute() : base(new SutProviderCustomization(), new Bit.Core.Test.AutoFixture.OrganizationFixtures.Organization())
{ }
}
}

View File

@ -0,0 +1,69 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.UserFixtures;
using Bit.Core.Test.AutoFixture.TransactionFixtures;
using Bit.Core.Test.AutoFixture.Relays;
namespace Bit.Core.Test.AutoFixture.DeviceFixtures
{
internal class DeviceBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Device))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.Device>();
return obj;
}
}
internal class EfDevice: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new DeviceBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<DeviceRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
}
}
internal class EfDeviceAutoDataAttribute : CustomAutoDataAttribute
{
public EfDeviceAutoDataAttribute() : base(new SutProviderCustomization(), new EfDevice())
{ }
}
internal class InlineEfDeviceAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfDeviceAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfDevice) }, values)
{ }
}
}

View File

@ -0,0 +1,71 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.UserFixtures;
using Bit.Core.Test.AutoFixture.TransactionFixtures;
using AutoFixture.DataAnnotations;
using Bit.Core.Test.AutoFixture.Relays;
namespace Bit.Core.Test.AutoFixture.EmergencyAccessFixtures
{
internal class EmergencyAccessBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.EmergencyAccess))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
var obj = fixture.Create<TableModel.EmergencyAccess>();
return obj;
}
}
internal class EfEmergencyAccess: ICustomization
{
public void Customize(IFixture fixture)
{
// TODO: Make a base EF Customization with IgnoreVirtualMembers/GlobalSettings/All repos and inherit
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new EmergencyAccessBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<EmergencyAccessRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
}
}
internal class EfEmergencyAccessAutoDataAttribute : CustomAutoDataAttribute
{
public EfEmergencyAccessAutoDataAttribute() : base(new SutProviderCustomization(), new EfEmergencyAccess())
{ }
}
internal class InlineEfEmergencyAccessAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfEmergencyAccessAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfEmergencyAccess) }, values)
{ }
}
}

View File

@ -0,0 +1,119 @@
using AutoFixture;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using System.Collections.Generic;
using AutoFixture.Kernel;
using System;
using Moq;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.Helpers.Factories;
using Microsoft.EntityFrameworkCore;
using Bit.Core.Settings;
namespace Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures
{
internal class ServiceScopeFactoryBuilder: ISpecimenBuilder
{
private DbContextOptions<DatabaseContext> _options { get; set; }
public ServiceScopeFactoryBuilder(DbContextOptions<DatabaseContext> options) {
_options = options;
}
public object Create(object request, ISpecimenContext context)
{
var fixture = new Fixture();
var serviceProvider = new Mock<IServiceProvider>();
var dbContext = new DatabaseContext(_options);
serviceProvider
.Setup(x => x.GetService(typeof(DatabaseContext)))
.Returns(dbContext);
var serviceScope = new Mock<IServiceScope>();
serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object);
var serviceScopeFactory = new Mock<IServiceScopeFactory>();
serviceScopeFactory
.Setup(x => x.CreateScope())
.Returns(serviceScope.Object);
return serviceScopeFactory.Object;
}
}
public class EfRepositoryListBuilder<T>: ISpecimenBuilder where T: BaseEntityFrameworkRepository
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var t = request as ParameterInfo;
if (t == null || t.ParameterType != typeof(List<T>))
{
return new NoSpecimen();
}
var list = new List<T>();
foreach (var option in DatabaseOptionsFactory.Options)
{
var fixture = new Fixture();
fixture.Customize<IServiceScopeFactory>(x => x.FromFactory(new ServiceScopeFactoryBuilder(option)));
fixture.Customize<IMapper>(x => x.FromFactory(() =>
new MapperConfiguration(cfg => {
cfg.AddProfile<CipherMapperProfile>();
cfg.AddProfile<CollectionCipherMapperProfile>();
cfg.AddProfile<CollectionMapperProfile>();
cfg.AddProfile<DeviceMapperProfile>();
cfg.AddProfile<EmergencyAccessMapperProfile>();
cfg.AddProfile<EventMapperProfile>();
cfg.AddProfile<FolderMapperProfile>();
cfg.AddProfile<GrantMapperProfile>();
cfg.AddProfile<GroupMapperProfile>();
cfg.AddProfile<GroupUserMapperProfile>();
cfg.AddProfile<InstallationMapperProfile>();
cfg.AddProfile<OrganizationMapperProfile>();
cfg.AddProfile<OrganizationUserMapperProfile>();
cfg.AddProfile<PolicyMapperProfile>();
cfg.AddProfile<SendMapperProfile>();
cfg.AddProfile<SsoConfigMapperProfile>();
cfg.AddProfile<SsoUserMapperProfile>();
cfg.AddProfile<TaxRateMapperProfile>();
cfg.AddProfile<TransactionMapperProfile>();
cfg.AddProfile<U2fMapperProfile>();
cfg.AddProfile<UserMapperProfile>();
})
.CreateMapper()));
var repo = fixture.Create<T>();
list.Add(repo);
}
return list;
}
}
public class IgnoreVirtualMembersCustomization : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException("context");
}
var pi = request as PropertyInfo;
if (pi == null)
{
return new NoSpecimen();
}
if (pi.GetGetMethod().IsVirtual && pi.DeclaringType != typeof(GlobalSettings))
{
return null;
}
return new NoSpecimen();
}
}
}

View File

@ -0,0 +1,65 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.Relays;
namespace Bit.Core.Test.AutoFixture.EventFixtures
{
internal class EventBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Event))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.Event>();
return obj;
}
}
internal class EfEvent: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new EventBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<EventRepository>());
}
}
internal class EfEventAutoDataAttribute : CustomAutoDataAttribute
{
public EfEventAutoDataAttribute() : base(new SutProviderCustomization(), new EfEvent())
{ }
}
internal class InlineEfEventAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfEventAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfEvent) }, values)
{ }
}
}

View File

@ -0,0 +1,68 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.Relays;
using Bit.Core.Test.AutoFixture.UserFixtures;
namespace Bit.Core.Test.AutoFixture.FolderFixtures
{
internal class FolderBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Folder))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.Folder>();
return obj;
}
}
internal class EfFolder: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new FolderBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<FolderRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
}
}
internal class EfFolderAutoDataAttribute : CustomAutoDataAttribute
{
public EfFolderAutoDataAttribute() : base(new SutProviderCustomization(), new EfFolder())
{ }
}
internal class InlineEfFolderAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfFolderAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfFolder) }, values)
{ }
}
}

View File

@ -1,7 +1,37 @@
using AutoFixture;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using AutoFixture;
using AutoFixture.Kernel;
using AutoMapper;
using Bit.Core.Enums;
using Bit.Core.Models;
using Bit.Core.Models.Table;
using Bit.Core.Settings;
using Bit.Core.Test.Helpers.Factories;
namespace Bit.Core.Test.AutoFixture
namespace Bit.Core.Test.AutoFixture.GlobalSettingsFixtures
{
internal class GlobalSettingsBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var pi = request as ParameterInfo;
var fixture = new Fixture();
if (pi == null || pi.ParameterType != typeof(Settings.GlobalSettings))
return new NoSpecimen();
return GlobalSettingsFactory.GlobalSettings;
}
}
internal class GlobalSettings : ICustomization
{
public void Customize(IFixture fixture)

View File

@ -0,0 +1,64 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.Relays;
namespace Bit.Core.Test.AutoFixture.GrantFixtures
{
internal class GrantBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Grant))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.Grant>();
return obj;
}
}
internal class EfGrant: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new GrantBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<GrantRepository>());
}
}
internal class EfGrantAutoDataAttribute : CustomAutoDataAttribute
{
public EfGrantAutoDataAttribute() : base(new SutProviderCustomization(), new EfGrant())
{ }
}
internal class InlineEfGrantAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfGrantAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfGrant) }, values)
{ }
}
}

View File

@ -1,19 +1,76 @@
using Bit.Core.Test.AutoFixture.Attributes;
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.Relays;
using Fixtures = Bit.Core.Test.AutoFixture.OrganizationFixtures;
namespace Bit.Core.Test.AutoFixture
namespace Bit.Core.Test.AutoFixture.GroupFixtures
{
internal class GroupOrganizationAutoDataAttribute : CustomAutoDataAttribute
{
public GroupOrganizationAutoDataAttribute() : base(
new SutProviderCustomization(), new Organization { UseGroups = true })
new SutProviderCustomization(), new Fixtures.Organization { UseGroups = true })
{ }
}
internal class GroupOrganizationNotUseGroupsAutoDataAttribute : CustomAutoDataAttribute
{
public GroupOrganizationNotUseGroupsAutoDataAttribute() : base(
new SutProviderCustomization(), new Organization { UseGroups = false })
new SutProviderCustomization(), new Bit.Core.Test.AutoFixture.OrganizationFixtures.Organization { UseGroups = false })
{ }
}
internal class GroupBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Group))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.Group>();
return obj;
}
}
internal class EfGroup: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new GroupBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<GroupRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfGroupAutoDataAttribute : CustomAutoDataAttribute
{
public EfGroupAutoDataAttribute() : base(new SutProviderCustomization(), new EfGroup())
{ }
}
internal class InlineEfGroupAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfGroupAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfGroup) }, values)
{ }
}
}

View File

@ -0,0 +1,63 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
namespace Bit.Core.Test.AutoFixture.GroupUserFixtures
{
internal class GroupUserBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.GroupUser))
{
return new NoSpecimen();
}
var fixture = new Fixture();
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.GroupUser>();
return obj;
}
}
internal class EfGroupUser: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new GroupUserBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<GroupRepository>());
}
}
internal class EfGroupUserAutoDataAttribute : CustomAutoDataAttribute
{
public EfGroupUserAutoDataAttribute() : base(new SutProviderCustomization(), new EfGroupUser())
{ }
}
internal class InlineEfGroupUserAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfGroupUserAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfGroupUser) }, values)
{ }
}
}

View File

@ -0,0 +1,63 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
namespace Bit.Core.Test.AutoFixture.InstallationFixtures
{
internal class InstallationBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Installation))
{
return new NoSpecimen();
}
var fixture = new Fixture();
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.Installation>();
return obj;
}
}
internal class EfInstallation: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new InstallationBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<InstallationRepository>());
}
}
internal class EfInstallationAutoDataAttribute : CustomAutoDataAttribute
{
public EfInstallationAutoDataAttribute() : base(new SutProviderCustomization(), new EfInstallation())
{ }
}
internal class InlineEfInstallationAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfInstallationAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfInstallation) }, values)
{ }
}
}

View File

@ -6,9 +6,14 @@ using AutoFixture;
using Bit.Core.Enums;
using Bit.Core.Models.Business;
using Bit.Core.Models.Data;
using Bit.Core.Models.Table;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using Bit.Core.Utilities;
using AutoFixture.Kernel;
using Bit.Core.Models;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Repositories.EntityFramework;
namespace Bit.Core.Test.AutoFixture.OrganizationFixtures
{
@ -30,7 +35,30 @@ namespace Bit.Core.Test.AutoFixture.OrganizationFixtures
composer
.With(c => c.OrganizationId, organizationId));
fixture.Customize<Group>(composer => composer.With(g => g.OrganizationId, organizationId));
fixture.Customize<TableModel.Group>(composer => composer.With(g => g.OrganizationId, organizationId));
}
}
internal class OrganizationBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Organization))
{
return new NoSpecimen();
}
var fixture = new Fixture();
var providers = fixture.Create<Dictionary<TwoFactorProviderType, TwoFactorProvider>>();
var organization = new Fixture().WithAutoNSubstitutions().Create<TableModel.Organization>();
organization.SetTwoFactorProviders(providers);
return organization;
}
}
@ -46,7 +74,7 @@ namespace Bit.Core.Test.AutoFixture.OrganizationFixtures
fixture.Customize<Core.Models.Table.Organization>(composer => composer
.With(o => o.PlanType, CheckedPlanType));
fixture.Customize<OrganizationUpgrade>(composer => composer
.With(ou => ou.Plan, validUpgradePlans.First()));
.With(ou => ou.Plan, validUpgradePlans.First())) ;
}
}
@ -67,6 +95,7 @@ namespace Bit.Core.Test.AutoFixture.OrganizationFixtures
.Without(o => o.GatewaySubscriptionId));
}
}
internal class OrganizationInvite : ICustomization
{
public OrganizationUserType InviteeUserType { get; set; }
@ -82,7 +111,7 @@ namespace Bit.Core.Test.AutoFixture.OrganizationFixtures
fixture.Customize<Core.Models.Table.Organization>(composer => composer
.With(o => o.Id, organizationId)
.With(o => o.Seats, (short)100));
fixture.Customize<OrganizationUser>(composer => composer
fixture.Customize<TableModel.OrganizationUser>(composer => composer
.With(ou => ou.OrganizationId, organizationId)
.With(ou => ou.Type, InvitorUserType)
.With(ou => ou.Permissions, PermissionsBlob));
@ -91,6 +120,17 @@ namespace Bit.Core.Test.AutoFixture.OrganizationFixtures
}
}
internal class EfOrganization: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class PaidOrganizationAutoDataAttribute : CustomAutoDataAttribute
{
public PaidOrganizationAutoDataAttribute(int planType = 0) : base(new SutProviderCustomization(),
@ -136,4 +176,17 @@ namespace Bit.Core.Test.AutoFixture.OrganizationFixtures
typeof(OrganizationInvite) }, values)
{ }
}
internal class EfOrganizationAutoDataAttribute : CustomAutoDataAttribute
{
public EfOrganizationAutoDataAttribute() : base(new SutProviderCustomization(), new EfOrganization())
{ }
}
internal class InlineEfOrganizationAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfOrganizationAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfOrganization) }, values)
{ }
}
}

View File

@ -1,10 +1,63 @@
using System.Reflection;
using AutoFixture;
using AutoFixture.Xunit2;
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Models.Data;
using System.Text.Json;
using Bit.Core.Test.AutoFixture.UserFixtures;
using AutoFixture.Xunit2;
using System.Reflection;
namespace Bit.Core.Test.AutoFixture.OrganizationUserFixtures
{
internal class OrganizationUserBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == typeof(OrganizationUser))
{
var fixture = new Fixture();
var orgUser = fixture.WithAutoNSubstitutions().Create<TableModel.OrganizationUser>();
var orgUserPermissions = fixture.WithAutoNSubstitutions().Create<Permissions>();
orgUser.Permissions = JsonSerializer.Serialize(orgUserPermissions, new JsonSerializerOptions() {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
return orgUser;
}
else if (type == typeof(List<OrganizationUser>))
{
var fixture = new Fixture();
var orgUsers = fixture.WithAutoNSubstitutions().CreateMany<TableModel.OrganizationUser>(2);
foreach (var orgUser in orgUsers)
{
var providers = fixture.Create<Dictionary<TwoFactorProviderType, TwoFactorProvider>>();
var orgUserPermissions = fixture.WithAutoNSubstitutions().Create<Permissions>();
orgUser.Permissions = JsonSerializer.Serialize(orgUserPermissions, new JsonSerializerOptions() {
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
}
return orgUsers;
}
return new NoSpecimen();
}
}
internal class OrganizationUser : ICustomization
{
public OrganizationUserStatusType Status { get; set; }
@ -42,4 +95,32 @@ namespace Bit.Core.Test.AutoFixture.OrganizationUserFixtures
return new OrganizationUser(_status, _type);
}
}
internal class EfOrganizationUser: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new OrganizationUserBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationUserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfOrganizationUserAutoDataAttribute : CustomAutoDataAttribute
{
public EfOrganizationUserAutoDataAttribute() : base(new SutProviderCustomization(), new EfOrganizationUser())
{ }
}
internal class InlineEfOrganizationUserAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfOrganizationUserAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfOrganizationUser) }, values)
{ }
}
}

View File

@ -1,10 +1,23 @@
using System;
using System.Reflection;
using AutoFixture;
using AutoFixture.Xunit2;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using System.Reflection;
using AutoFixture.Xunit2;
namespace Bit.Core.Test.AutoFixture.OrganizationUserFixtures
namespace Bit.Core.Test.AutoFixture.PolicyFixtures
{
internal class Policy : ICustomization
{
@ -38,4 +51,51 @@ namespace Bit.Core.Test.AutoFixture.OrganizationUserFixtures
return new Policy(_type);
}
}
internal class PolicyBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Policy))
{
return new NoSpecimen();
}
var fixture = new Fixture();
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.Policy>();
return obj;
}
}
internal class EfPolicy: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new PolicyBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<PolicyRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfPolicyAutoDataAttribute : CustomAutoDataAttribute
{
public EfPolicyAutoDataAttribute() : base(new SutProviderCustomization(), new EfPolicy())
{ }
}
internal class InlineEfPolicyAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfPolicyAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfPolicy) }, values)
{ }
}
}

View File

@ -0,0 +1,43 @@
using AutoFixture.Kernel;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
namespace Bit.Core.Test.AutoFixture.Relays
{
// Creates a string the same length as any availible MaxLength data annotation
// Modified version of the StringLenfthRelay provided by AutoFixture
// https://github.com/AutoFixture/AutoFixture/blob/master/Src/AutoFixture/DataAnnotations/StringLengthAttributeRelay.cs
internal class MaxLengthStringRelay: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (request == null)
{
return new NoSpecimen();
}
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var p = request as PropertyInfo;
if (p == null)
{
return new NoSpecimen();
}
var a = (MaxLengthAttribute)p.GetCustomAttributes(typeof(MaxLengthAttribute), false).SingleOrDefault();
if (a == null)
{
return new NoSpecimen();
}
return context.Resolve(new ConstrainedStringRequest(a.Length, a.Length));
}
}
}

View File

@ -1,7 +1,14 @@
using System;
using AutoFixture;
using AutoFixture.Kernel;
using Bit.Core.Models.Table;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Test.AutoFixture.Relays;
using Bit.Core.Test.AutoFixture.UserFixtures;
namespace Bit.Core.Test.AutoFixture.SendFixtures
{
@ -62,4 +69,62 @@ namespace Bit.Core.Test.AutoFixture.SendFixtures
typeof(SutProviderCustomization), typeof(OrganizationSend) }, values)
{ }
}
internal class SendBuilder: ISpecimenBuilder
{
public bool OrganizationOwned { get; set; }
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(Send))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
if (!OrganizationOwned)
{
fixture.Customize<Send>(composer => composer
.Without(c => c.OrganizationId));
}
var obj = fixture.WithAutoNSubstitutions().Create<Send>();
return obj;
}
}
internal class EfSend: ICustomization
{
public bool OrganizationOwned { get; set; }
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new SendBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<SendRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfUserSendAutoDataAttribute : CustomAutoDataAttribute
{
public EfUserSendAutoDataAttribute() : base(new SutProviderCustomization(), new EfSend())
{ }
}
internal class EfOrganizationSendAutoDataAttribute : CustomAutoDataAttribute
{
public EfOrganizationSendAutoDataAttribute() : base(new SutProviderCustomization(), new EfSend(){
OrganizationOwned = true,
})
{ }
}
}

View File

@ -0,0 +1,67 @@
using System;
using AutoFixture;
using AutoFixture.Kernel;
using AutoMapper;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Models.Data;
using System.Text.Json;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Repositories.EntityFramework;
namespace Bit.Core.Test.AutoFixture.SsoConfigFixtures
{
internal class SsoConfigBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.SsoConfig))
{
return new NoSpecimen();
}
var fixture = new Fixture();
var ssoConfig = fixture.WithAutoNSubstitutions().Create<TableModel.SsoConfig>();
var ssoConfigData = fixture.WithAutoNSubstitutions().Create<SsoConfigurationData>();
ssoConfig.Data = JsonSerializer.Serialize(ssoConfigData, new JsonSerializerOptions(){
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
});
return ssoConfig;
}
}
internal class EfSsoConfig: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new SsoConfigBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<SsoConfigRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfSsoConfigAutoDataAttribute : CustomAutoDataAttribute
{
public EfSsoConfigAutoDataAttribute() : base(new SutProviderCustomization(), new EfSsoConfig())
{ }
}
internal class InlineEfSsoConfigAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfSsoConfigAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfSsoConfig) }, values)
{ }
}
}

View File

@ -0,0 +1,41 @@
using AutoFixture;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Test.AutoFixture.UserFixtures;
using TableModel = Bit.Core.Models.Table;
namespace Bit.Core.Test.AutoFixture.SsoUserFixtures
{
internal class EfSsoUser: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customize<TableModel.SsoUser>(composer => composer.Without(ou => ou.Id));
fixture.Customizations.Add(new EfRepositoryListBuilder<SsoUserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfSsoUserAutoDataAttribute : CustomAutoDataAttribute
{
public EfSsoUserAutoDataAttribute() : base(new SutProviderCustomization(), new EfSsoUser())
{ }
}
internal class InlineEfSsoUserAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfSsoUserAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfSsoUser) }, values)
{ }
}
}

View File

@ -4,6 +4,7 @@ using AutoFixture;
using AutoFixture.Kernel;
using System.Reflection;
using System.Linq;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
namespace Bit.Core.Test.AutoFixture
{

View File

@ -0,0 +1,65 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.Relays;
namespace Bit.Core.Test.AutoFixture.TaxRateFixtures
{
internal class TaxRateBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.TaxRate))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Insert(0, new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.TaxRate>();
return obj;
}
}
internal class EfTaxRate: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new TaxRateBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<TaxRateRepository>());
}
}
internal class EfTaxRateAutoDataAttribute : CustomAutoDataAttribute
{
public EfTaxRateAutoDataAttribute() : base(new SutProviderCustomization(), new EfTaxRate())
{ }
}
internal class InlineEfTaxRateAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfTaxRateAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfTaxRate) }, values)
{ }
}
}

View File

@ -0,0 +1,78 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.UserFixtures;
using Bit.Core.Test.AutoFixture.Relays;
namespace Bit.Core.Test.AutoFixture.TransactionFixtures
{
internal class TransactionBuilder: ISpecimenBuilder
{
public bool OrganizationOwned { get; set; }
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.Transaction))
{
return new NoSpecimen();
}
var fixture = new Fixture();
if (!OrganizationOwned)
{
fixture.Customize<Transaction>(composer => composer
.Without(c => c.OrganizationId));
}
fixture.Customizations.Add(new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.Transaction>();
return obj;
}
}
internal class EfTransaction: ICustomization
{
public bool OrganizationOwned { get; set; }
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new TransactionBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<TransactionRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfUserTransactionAutoDataAttribute : CustomAutoDataAttribute
{
public EfUserTransactionAutoDataAttribute() : base(new SutProviderCustomization(), new EfTransaction())
{ }
}
internal class EfOrganizationTransactionAutoDataAttribute : CustomAutoDataAttribute
{
public EfOrganizationTransactionAutoDataAttribute() : base(new SutProviderCustomization(), new EfTransaction(){
OrganizationOwned = true,
})
{ }
}
}

View File

@ -0,0 +1,68 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
using Bit.Core.Test.AutoFixture.Relays;
using Bit.Core.Test.AutoFixture.UserFixtures;
namespace Bit.Core.Test.AutoFixture.U2fFixtures
{
internal class U2fBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == null || type != typeof(TableModel.U2f))
{
return new NoSpecimen();
}
var fixture = new Fixture();
fixture.Customizations.Add(new MaxLengthStringRelay());
var obj = fixture.WithAutoNSubstitutions().Create<TableModel.U2f>();
return obj;
}
}
internal class EfU2f: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new U2fBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<U2fRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
}
}
internal class EfU2fAutoDataAttribute : CustomAutoDataAttribute
{
public EfU2fAutoDataAttribute() : base(new SutProviderCustomization(), new EfU2f())
{ }
}
internal class InlineEfU2fAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfU2fAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfU2f) }, values)
{ }
}
}

View File

@ -0,0 +1,78 @@
using AutoFixture;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.GlobalSettingsFixtures;
using AutoMapper;
using Bit.Core.Models.EntityFramework;
using Bit.Core.Models;
using System.Collections.Generic;
using Bit.Core.Enums;
using AutoFixture.Kernel;
using System;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture.EntityFrameworkRepositoryFixtures;
namespace Bit.Core.Test.AutoFixture.UserFixtures
{
internal class UserBuilder: ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var type = request as Type;
if (type == typeof(TableModel.User))
{
var fixture = new Fixture();
var providers = fixture.Create<Dictionary<TwoFactorProviderType, TwoFactorProvider>>();
var user = fixture.WithAutoNSubstitutions().Create<TableModel.User>();
user.SetTwoFactorProviders(providers);
return user;
}
else if (type == typeof(List<TableModel.User>))
{
var fixture = new Fixture();
var users = fixture.WithAutoNSubstitutions().CreateMany<TableModel.User>(2);
foreach (var user in users)
{
var providers = fixture.Create<Dictionary<TwoFactorProviderType, TwoFactorProvider>>();
user.SetTwoFactorProviders(providers);
}
return users;
}
return new NoSpecimen();
}
}
internal class EfUser: ICustomization
{
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(new IgnoreVirtualMembersCustomization());
fixture.Customizations.Add(new GlobalSettingsBuilder());
fixture.Customizations.Add(new UserBuilder());
fixture.Customizations.Add(new OrganizationBuilder());
fixture.Customizations.Add(new EfRepositoryListBuilder<UserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<SsoUserRepository>());
fixture.Customizations.Add(new EfRepositoryListBuilder<OrganizationRepository>());
}
}
internal class EfUserAutoDataAttribute : CustomAutoDataAttribute
{
public EfUserAutoDataAttribute() : base(new SutProviderCustomization(), new EfUser())
{ }
}
internal class InlineEfUserAutoDataAttribute : InlineCustomAutoDataAttribute
{
public InlineEfUserAutoDataAttribute(params object[] values) : base(new[] { typeof(SutProviderCustomization),
typeof(EfUser) }, values)
{ }
}
}

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<IsPackable>false</IsPackable>
@ -11,6 +11,7 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="NSubstitute" Version="4.2.2" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
@ -23,6 +24,6 @@
<ItemGroup>
<ProjectReference Include="..\..\src\Core\Core.csproj" />
<ProjectReference Include="..\..\src\Api\Api.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,38 @@
using System.Collections.Generic;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Settings;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
namespace Bit.Core.Test.Helpers.Factories
{
public static class GlobalSettingsFactory
{
public static GlobalSettings GlobalSettings { get; } = new GlobalSettings();
static GlobalSettingsFactory()
{
var configBuilder = new ConfigurationBuilder().AddUserSecrets<Bit.Api.Startup>();
var Configuration = configBuilder.Build();
ConfigurationBinder.Bind(Configuration.GetSection("GlobalSettings"), GlobalSettings);
}
}
public static class DatabaseOptionsFactory
{
public static List<DbContextOptions<DatabaseContext>> Options { get; } = new List<DbContextOptions<DatabaseContext>>();
static DatabaseOptionsFactory()
{
var globalSettings = GlobalSettingsFactory.GlobalSettings;
if (!string.IsNullOrWhiteSpace(GlobalSettingsFactory.GlobalSettings.PostgreSql?.ConnectionString))
{
Options.Add(new DbContextOptionsBuilder<DatabaseContext>().UseNpgsql(globalSettings.PostgreSql.ConnectionString).Options);
}
if (!string.IsNullOrWhiteSpace(GlobalSettingsFactory.GlobalSettings.MySql?.ConnectionString))
{
var mySqlConnectionString = globalSettings.MySql.ConnectionString;
Options.Add(new DbContextOptionsBuilder<DatabaseContext>().UseMySql(mySqlConnectionString, ServerVersion.AutoDetect(mySqlConnectionString)).Options);
}
}
}
}

View File

@ -0,0 +1,200 @@
using System.Collections.Generic;
using System.Linq;
using Bit.Core.Models.Table;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.CipherFixtures;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Microsoft.EntityFrameworkCore;
using Xunit;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using Bit.Core.Test.AutoFixture.CipherFixtures;
using Bit.Core.Repositories.EntityFramework.Queries;
using Bit.Core.Models.Data;
using System;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class CipherRepositoryTests
{
[Theory (Skip = "Run ad-hoc"), EfUserCipherAutoData]
public async void RefreshDb(List<EfRepo.CipherRepository> suts)
{
foreach (var sut in suts)
{
await sut.RefreshDb();
}
}
[CiSkippedTheory, EfUserCipherAutoData, EfOrganizationCipherAutoData]
public async void CreateAsync_Works_DataMatches(Cipher cipher, User user, Organization org,
CipherCompare equalityComparer, List<EfRepo.CipherRepository> suts, List<EfRepo.UserRepository> efUserRepos,
List<EfRepo.OrganizationRepository> efOrgRepos, SqlRepo.CipherRepository sqlCipherRepo,
SqlRepo.UserRepository sqlUserRepo, SqlRepo.OrganizationRepository sqlOrgRepo)
{
var savedCiphers = new List<Cipher>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efUser = await efUserRepos[i].CreateAsync(user);
sut.ClearChangeTracking();
cipher.UserId = efUser.Id;
if (cipher.OrganizationId.HasValue)
{
var efOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
cipher.OrganizationId = efOrg.Id;
}
var postEfCipher = await sut.CreateAsync(cipher);
sut.ClearChangeTracking();
var savedCipher = await sut.GetByIdAsync(postEfCipher.Id);
savedCiphers.Add(savedCipher);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
cipher.UserId = sqlUser.Id;
if (cipher.OrganizationId.HasValue)
{
var sqlOrg = await sqlOrgRepo.CreateAsync(org);
cipher.OrganizationId = sqlOrg.Id;
}
var sqlCipher = await sqlCipherRepo.CreateAsync(cipher);
var savedSqlCipher = await sqlCipherRepo.GetByIdAsync(sqlCipher.Id);
savedCiphers.Add(savedSqlCipher);
var distinctItems = savedCiphers.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfUserCipherAutoData]
public async void CreateAsync_BumpsUserAccountRevisionDate(Cipher cipher, User user,
CipherCompare equalityComparer, List<EfRepo.CipherRepository> suts, List<EfRepo.UserRepository> efUserRepos,
SqlRepo.CipherRepository sqlCipherRepo, SqlRepo.UserRepository sqlUserRepo)
{
var bumpedUsers = new List<User>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efUser = await efUserRepos[i].CreateAsync(user);
efUserRepos[i].ClearChangeTracking();
cipher.UserId = efUser.Id;
cipher.OrganizationId = null;
var postEfCipher = await sut.CreateAsync(cipher);
sut.ClearChangeTracking();
var bumpedUser = await efUserRepos[i].GetByIdAsync(efUser.Id);
bumpedUsers.Add(bumpedUser);
}
Assert.True(bumpedUsers.All(u => u.AccountRevisionDate.ToShortDateString() == DateTime.UtcNow.ToShortDateString() ));
}
[CiSkippedTheory, EfOrganizationCipherAutoData]
public async void CreateAsync_BumpsOrgUserAccountRevisionDates(Cipher cipher, List<User> users,
List<OrganizationUser> orgUsers, Collection collection, Organization org, CipherCompare equalityComparer,
List<EfRepo.CipherRepository> suts, List<EfRepo.UserRepository> efUserRepos, List<EfRepo.OrganizationRepository> efOrgRepos,
List<EfRepo.OrganizationUserRepository> efOrgUserRepos, List<EfRepo.CollectionRepository> efCollectionRepos)
{
var savedCiphers = new List<Cipher>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efUsers = await efUserRepos[i].CreateMany(users);
efUserRepos[i].ClearChangeTracking();
var efOrg = await efOrgRepos[i].CreateAsync(org);
efOrgRepos[i].ClearChangeTracking();
cipher.OrganizationId = efOrg.Id;
collection.OrganizationId = efOrg.Id;
var efCollection = await efCollectionRepos[i].CreateAsync(collection);
efCollectionRepos[i].ClearChangeTracking();
IEnumerable<object>[] lists = {efUsers, orgUsers};
var maxOrgUsers = lists.Min(l => l.Count());
orgUsers = orgUsers.Take(maxOrgUsers).ToList();
efUsers = efUsers.Take(maxOrgUsers).ToList();
for (var j = 0; j < maxOrgUsers; j++)
{
orgUsers[j].OrganizationId = efOrg.Id;
orgUsers[j].UserId = efUsers[j].Id;
}
orgUsers = await efOrgUserRepos[i].CreateMany(orgUsers);
var selectionReadOnlyList = new List<SelectionReadOnly>();
orgUsers.ForEach(ou => selectionReadOnlyList.Add(new SelectionReadOnly() { Id = ou.Id }));
await efCollectionRepos[i].UpdateUsersAsync(efCollection.Id, selectionReadOnlyList);
efCollectionRepos[i].ClearChangeTracking();
foreach (var ou in orgUsers)
{
var collectionUser = new CollectionUser() {
CollectionId = efCollection.Id,
OrganizationUserId = ou.Id
};
}
cipher.UserId = null;
var postEfCipher = await sut.CreateAsync(cipher);
sut.ClearChangeTracking();
var query = new UserBumpAccountRevisionDateByCipherIdQuery(cipher);
var modifiedUsers = await sut.Run(query).ToListAsync();
Assert.True(modifiedUsers
.All(u => u.AccountRevisionDate.ToShortDateString() ==
DateTime.UtcNow.ToShortDateString()));
}
}
[CiSkippedTheory, EfUserCipherAutoData, EfOrganizationCipherAutoData]
public async void DeleteAsync_CipherIsDeleted(
Cipher cipher,
User user,
Organization org,
List<EfRepo.CipherRepository> suts,
List<EfRepo.UserRepository> efUserRepos,
List<EfRepo.OrganizationRepository> efOrgRepos
)
{
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var postEfOrg = await efOrgRepos[i].CreateAsync(org);
efOrgRepos[i].ClearChangeTracking();
var postEfUser = await efUserRepos[i].CreateAsync(user);
efUserRepos[i].ClearChangeTracking();
if (cipher.OrganizationId.HasValue)
{
cipher.OrganizationId = postEfOrg.Id;
}
cipher.UserId = postEfUser.Id;
await sut.CreateAsync(cipher);
sut.ClearChangeTracking();
await sut.DeleteAsync(cipher);
sut.ClearChangeTracking();
var savedCipher = await sut.GetByIdAsync(cipher.Id);
Assert.True(savedCipher == null);
}
}
}
}

View File

@ -0,0 +1,55 @@
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.AutoFixture.Attributes;
using Microsoft.EntityFrameworkCore;
using Xunit;
using Bit.Core.Models.Table;
using System.Collections.Generic;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Bit.Core.Test.AutoFixture.CollectionFixtures;
using System.Linq;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class CollectionRepositoryTests
{
[CiSkippedTheory, EfCollectionAutoData]
public async void CreateAsync_Works_DataMatches(
Collection collection,
Organization organization,
CollectionCompare equalityComparer,
List<EfRepo.CollectionRepository> suts,
List<EfRepo.OrganizationRepository> efOrganizationRepos,
SqlRepo.CollectionRepository sqlCollectionRepo,
SqlRepo.OrganizationRepository sqlOrganizationRepo
)
{
var savedCollections = new List<Collection>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efOrganization = await efOrganizationRepos[i].CreateAsync(organization);
sut.ClearChangeTracking();
collection.OrganizationId = efOrganization.Id;
var postEfCollection = await sut.CreateAsync(collection);
sut.ClearChangeTracking();
var savedCollection = await sut.GetByIdAsync(postEfCollection.Id);
savedCollections.Add(savedCollection);
}
var sqlOrganization = await sqlOrganizationRepo.CreateAsync(organization);
collection.OrganizationId = sqlOrganization.Id;
var sqlCollection = await sqlCollectionRepo.CreateAsync(collection);
var savedSqlCollection = await sqlCollectionRepo.GetByIdAsync(sqlCollection.Id);
savedCollections.Add(savedSqlCollection);
var distinctItems = savedCollections.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,49 @@
using Bit.Core.Test.AutoFixture.Attributes;
using Xunit;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using System.Collections.Generic;
using Bit.Core.Models.Table;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using System.Linq;
using Bit.Core.Test.AutoFixture.DeviceFixtures;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class DeviceRepositoryTests
{
[CiSkippedTheory, EfDeviceAutoData]
public async void CreateAsync_Works_DataMatches(Device device, User user,
DeviceCompare equalityComparer, List<EfRepo.DeviceRepository> suts,
List<EfRepo.UserRepository> efUserRepos, SqlRepo.DeviceRepository sqlDeviceRepo,
SqlRepo.UserRepository sqlUserRepo)
{
var savedDevices = new List<Device>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efUser = await efUserRepos[i].CreateAsync(user);
device.UserId = efUser.Id;
sut.ClearChangeTracking();
var postEfDevice = await sut.CreateAsync(device);
sut.ClearChangeTracking();
var savedDevice = await sut.GetByIdAsync(postEfDevice.Id);
savedDevices.Add(savedDevice);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
device.UserId = sqlUser.Id;
var sqlDevice = await sqlDeviceRepo.CreateAsync(device);
var savedSqlDevice = await sqlDeviceRepo.GetByIdAsync(sqlDevice.Id);
savedDevices.Add(savedSqlDevice);
var distinctItems = savedDevices.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,66 @@
using System.Collections.Generic;
using Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.EmergencyAccessFixtures;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Xunit;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using System.Linq;
using AutoFixture;
using Bit.Core.Test.AutoFixture.TransactionFixtures;
using AutoFixture.DataAnnotations;
using AutoFixture.Kernel;
using Bit.Core.Test.AutoFixture.Relays;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class EmergencyAccessRepositoryTests
{
[CiSkippedTheory, EfEmergencyAccessAutoData]
public async void CreateAsync_Works_DataMatches(
EmergencyAccess emergencyAccess,
List<User> users,
EmergencyAccessCompare equalityComparer,
List<EfRepo.EmergencyAccessRepository> suts,
List<EfRepo.UserRepository> efUserRepos,
SqlRepo.EmergencyAccessRepository sqlEmergencyAccessRepo,
SqlRepo.UserRepository sqlUserRepo
)
{
var savedEmergencyAccesss = new List<EmergencyAccess>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
for (int j = 0; j < users.Count; j++)
{
users[j] = await efUserRepos[i].CreateAsync(users[j]);
}
sut.ClearChangeTracking();
emergencyAccess.GrantorId = users[0].Id;
emergencyAccess.GranteeId = users[0].Id;
var postEfEmergencyAccess = await sut.CreateAsync(emergencyAccess);
sut.ClearChangeTracking();
var savedEmergencyAccess = await sut.GetByIdAsync(postEfEmergencyAccess.Id);
savedEmergencyAccesss.Add(savedEmergencyAccess);
}
for (int j = 0; j < users.Count; j++)
{
users[j] = await sqlUserRepo.CreateAsync(users[j]);
}
emergencyAccess.GrantorId = users[0].Id;
emergencyAccess.GranteeId = users[0].Id;
var sqlEmergencyAccess = await sqlEmergencyAccessRepo.CreateAsync(emergencyAccess);
var savedSqlEmergencyAccess = await sqlEmergencyAccessRepo.GetByIdAsync(sqlEmergencyAccess.Id);
savedEmergencyAccesss.Add(savedSqlEmergencyAccess);
var distinctItems = savedEmergencyAccesss.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class CipherCompare: IEqualityComparer<Cipher>
{
public bool Equals(Cipher x, Cipher y)
{
return x.Type == y.Type &&
x.Data == y.Data &&
x.Favorites == y.Favorites &&
x.Attachments == y.Attachments;
}
public int GetHashCode([DisallowNull] Cipher obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class CollectionCompare: IEqualityComparer<Collection>
{
public bool Equals(Collection x, Collection y)
{
return x.Name == y.Name &&
x.ExternalId == y.ExternalId;
}
public int GetHashCode([DisallowNull] Collection obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class DeviceCompare: IEqualityComparer<Device>
{
public bool Equals(Device x, Device y)
{
return x.Name == y.Name &&
x.Type == y.Type &&
x.Identifier == y.Identifier &&
x.PushToken == y.PushToken;
}
public int GetHashCode([DisallowNull] Device obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,25 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class EmergencyAccessCompare: IEqualityComparer<EmergencyAccess>
{
public bool Equals(EmergencyAccess x, EmergencyAccess y)
{
return x.Email == y.Email &&
x.KeyEncrypted == y.KeyEncrypted &&
x.Type == y.Type &&
x.Status == y.Status &&
x.WaitTimeDays == y.WaitTimeDays &&
x.RecoveryInitiatedDate == y.RecoveryInitiatedDate &&
x.LastNotificationDate == y.LastNotificationDate;
}
public int GetHashCode([DisallowNull] EmergencyAccess obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class EventCompare: IEqualityComparer<Event>
{
public bool Equals(Event x, Event y)
{
return x.Date.ToShortDateString() == y.Date.ToShortDateString() &&
x.Type == y.Type &&
x.IpAddress == y.IpAddress;
}
public int GetHashCode([DisallowNull] Event obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class FolderCompare: IEqualityComparer<Folder>
{
public bool Equals(Folder x, Folder y)
{
return x.Name == y.Name;
}
public int GetHashCode([DisallowNull] Folder obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class GrantCompare: IEqualityComparer<Grant>
{
public bool Equals(Grant x, Grant y)
{
return x.Key == y.Key &&
x.Type == y.Type &&
x.SubjectId == y.SubjectId &&
x.ClientId == y.ClientId &&
x.Description == y.Description &&
x.ExpirationDate == y.ExpirationDate &&
x.ConsumedDate == y.ConsumedDate &&
x.Data == y.Data;
}
public int GetHashCode([DisallowNull] Grant obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class GroupCompare: IEqualityComparer<Group>
{
public bool Equals(Group x, Group y)
{
return x.Name == y.Name &&
x.AccessAll == y.AccessAll &&
x.ExternalId == y.ExternalId;
}
public int GetHashCode([DisallowNull] Group obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class InstallationCompare: IEqualityComparer<Installation>
{
public bool Equals(Installation x, Installation y)
{
return x.Email == y.Email &&
x.Key == y.Key &&
x.Enabled == y.Enabled;
}
public int GetHashCode([DisallowNull] Installation obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,54 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class OrganizationCompare: IEqualityComparer<Organization>
{
public bool Equals(Organization x, Organization y)
{
var a = x.ExpirationDate.ToString();
var b = y.ExpirationDate.ToString();
return x.Identifier.Equals(y.Identifier) &&
x.Name.Equals(y.Name) &&
x.BusinessName.Equals(y.BusinessName) &&
x.BusinessAddress1.Equals(y.BusinessAddress1) &&
x.BusinessAddress2.Equals(y.BusinessAddress2) &&
x.BusinessAddress3.Equals(y.BusinessAddress3) &&
x.BusinessCountry.Equals(y.BusinessCountry) &&
x.BusinessTaxNumber.Equals(y.BusinessTaxNumber) &&
x.BillingEmail.Equals(y.BillingEmail) &&
x.Plan.Equals(y.Plan) &&
x.PlanType.Equals(y.PlanType) &&
x.Seats.Equals(y.Seats) &&
x.MaxCollections.Equals(y.MaxCollections) &&
x.UsePolicies.Equals(y.UsePolicies) &&
x.UseSso.Equals(y.UseSso) &&
x.UseGroups.Equals(y.UseGroups) &&
x.UseDirectory.Equals(y.UseDirectory) &&
x.UseEvents.Equals(y.UseEvents) &&
x.UseTotp.Equals(y.UseTotp) &&
x.Use2fa.Equals(y.Use2fa) &&
x.UseApi.Equals(y.UseApi) &&
x.SelfHost.Equals(y.SelfHost) &&
x.UsersGetPremium.Equals(y.UsersGetPremium) &&
x.Storage.Equals(y.Storage) &&
x.MaxStorageGb.Equals(y.MaxStorageGb) &&
x.Gateway.Equals(y.Gateway) &&
x.GatewayCustomerId.Equals(y.GatewayCustomerId) &&
x.GatewaySubscriptionId.Equals(y.GatewaySubscriptionId) &&
x.ReferenceData.Equals(y.ReferenceData) &&
x.Enabled.Equals(y.Enabled) &&
x.LicenseKey.Equals(y.LicenseKey) &&
x.ApiKey.Equals(y.ApiKey) &&
x.TwoFactorProviders.Equals(y.TwoFactorProviders) &&
x.ExpirationDate.ToString().Equals(y.ExpirationDate.ToString());
}
public int GetHashCode([DisallowNull] Organization obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,24 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class OrganizationUserCompare: IEqualityComparer<OrganizationUser>
{
public bool Equals(OrganizationUser x, OrganizationUser y)
{
return x.Email == y.Email &&
x.Status == y.Status &&
x.Type == y.Type &&
x.AccessAll == y.AccessAll &&
x.ExternalId == y.ExternalId &&
x.Permissions == y.Permissions;
}
public int GetHashCode([DisallowNull] OrganizationUser obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class PolicyCompare: IEqualityComparer<Policy>
{
public bool Equals(Policy x, Policy y)
{
return x.Type == y.Type &&
x.Data == y.Data &&
x.Enabled == y.Enabled;
}
public int GetHashCode([DisallowNull] Policy obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,28 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class SendCompare: IEqualityComparer<Send>
{
public bool Equals(Send x, Send y)
{
return x.Type == y.Type &&
x.Data == y.Data &&
x.Key == y.Key &&
x.Password == y.Password &&
x.MaxAccessCount == y.MaxAccessCount &&
x.AccessCount == y.AccessCount &&
x.ExpirationDate?.ToShortDateString() == y.ExpirationDate?.ToShortDateString() &&
x.DeletionDate.ToShortDateString() == y.DeletionDate.ToShortDateString() &&
x.Disabled == y.Disabled &&
x.HideEmail == y.HideEmail;
}
public int GetHashCode([DisallowNull] Send obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class SsoConfigCompare: IEqualityComparer<SsoConfig>
{
public bool Equals(SsoConfig x, SsoConfig y)
{
return x.Enabled == y.Enabled &&
x.OrganizationId == y.OrganizationId &&
x.Data == y.Data;
}
public int GetHashCode([DisallowNull] SsoConfig obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,19 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class SsoUserCompare: IEqualityComparer<SsoUser>
{
public bool Equals(SsoUser x, SsoUser y)
{
return x.ExternalId == y.ExternalId;
}
public int GetHashCode([DisallowNull] SsoUser obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,23 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class TaxRateCompare: IEqualityComparer<TaxRate>
{
public bool Equals(TaxRate x, TaxRate y)
{
return x.Country == y.Country &&
x.State == y.State &&
x.PostalCode == y.PostalCode &&
x.Rate == y.Rate &&
x.Active == y.Active;
}
public int GetHashCode([DisallowNull] TaxRate obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,25 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class TransactionCompare: IEqualityComparer<Transaction>
{
public bool Equals(Transaction x, Transaction y)
{
return x.Type == y.Type &&
x.Amount == y.Amount &&
x.Refunded == y.Refunded &&
x.Details == y.Details &&
x.PaymentMethodType == y.PaymentMethodType &&
x.Gateway == y.Gateway &&
x.GatewayId == y.GatewayId;
}
public int GetHashCode([DisallowNull] Transaction obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class U2fCompare: IEqualityComparer<U2f>
{
public bool Equals(U2f x, U2f y)
{
return x.KeyHandle == y.KeyHandle &&
x.Challenge == y.Challenge &&
x.AppId == y.AppId &&
x.Version == y.Version;
}
public int GetHashCode([DisallowNull] U2f obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,41 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Table;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class UserCompare: IEqualityComparer<User>
{
public bool Equals(User x, User y)
{
return x.Name == y.Name &&
x.Email == y.Email &&
x.EmailVerified == y.EmailVerified &&
x.MasterPassword == y.MasterPassword &&
x.MasterPasswordHint == y.MasterPasswordHint &&
x.Culture == y.Culture &&
x.SecurityStamp == y.SecurityStamp &&
x.TwoFactorProviders == y.TwoFactorProviders &&
x.TwoFactorRecoveryCode == y.TwoFactorRecoveryCode &&
x.EquivalentDomains == y.EquivalentDomains &&
x.Key == y.Key &&
x.PublicKey == y.PublicKey &&
x.PrivateKey == y.PrivateKey &&
x.Premium == y.Premium &&
x.Storage == y.Storage &&
x.MaxStorageGb == y.MaxStorageGb &&
x.Gateway == y.Gateway &&
x.GatewayCustomerId == y.GatewayCustomerId &&
x.ReferenceData == y.ReferenceData &&
x.LicenseKey == y.LicenseKey &&
x.ApiKey == y.ApiKey &&
x.Kdf == y.Kdf &&
x.KdfIterations == y.KdfIterations;
}
public int GetHashCode([DisallowNull] User obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Bit.Core.Models.Data;
namespace Bit.Core.Test.Repositories.EntityFramework.EqualityComparers
{
public class UserKdfInformationCompare: IEqualityComparer<UserKdfInformation>
{
public bool Equals(UserKdfInformation x, UserKdfInformation y)
{
return x.Kdf == y.Kdf &&
x.KdfIterations == y.KdfIterations;
}
public int GetHashCode([DisallowNull] UserKdfInformation obj)
{
return base.GetHashCode();
}
}
}

View File

@ -0,0 +1,52 @@
using System.Collections.Generic;
using Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.FolderFixtures;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Microsoft.EntityFrameworkCore;
using Xunit;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using System.Linq;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class FolderRepositoryTests
{
[CiSkippedTheory, EfFolderAutoData]
public async void CreateAsync_Works_DataMatches(
Folder folder,
User user,
FolderCompare equalityComparer,
List<EfRepo.FolderRepository> suts,
List<EfRepo.UserRepository> efUserRepos,
SqlRepo.FolderRepository sqlFolderRepo,
SqlRepo.UserRepository sqlUserRepo)
{
var savedFolders = new List<Folder>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efUser = await efUserRepos[i].CreateAsync(user);
sut.ClearChangeTracking();
folder.UserId = efUser.Id;
var postEfFolder = await sut.CreateAsync(folder);
sut.ClearChangeTracking();
var savedFolder = await sut.GetByIdAsync(folder.Id);
savedFolders.Add(savedFolder);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
folder.UserId = sqlUser.Id;
var sqlFolder = await sqlFolderRepo.CreateAsync(folder);
savedFolders.Add(await sqlFolderRepo.GetByIdAsync(sqlFolder.Id));
var distinctItems = savedFolders.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,41 @@
using System.Collections.Generic;
using Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.InstallationFixtures;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Xunit;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using System.Linq;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class InstallationRepositoryTests
{
[CiSkippedTheory, EfInstallationAutoData]
public async void CreateAsync_Works_DataMatches(
Installation installation,
InstallationCompare equalityComparer,
List<EfRepo.InstallationRepository> suts,
SqlRepo.InstallationRepository sqlInstallationRepo
)
{
var savedInstallations = new List<Installation>();
foreach (var sut in suts)
{
var postEfInstallation = await sut.CreateAsync(installation);
sut.ClearChangeTracking();
var savedInstallation = await sut.GetByIdAsync(postEfInstallation.Id);
savedInstallations.Add(savedInstallation);
}
var sqlInstallation = await sqlInstallationRepo.CreateAsync(installation);
var savedSqlInstallation = await sqlInstallationRepo.GetByIdAsync(sqlInstallation.Id);
savedInstallations.Add(savedSqlInstallation);
var distinctItems = savedInstallations.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,158 @@
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.Helpers.Factories;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using System.Collections.Generic;
using System.Linq;
using TableModel = Bit.Core.Models.Table;
using Bit.Core.Models.Data;
using Xunit;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Bit.Core.Test.AutoFixture.OrganizationFixtures;
using Bit.Core.Test.AutoFixture.Attributes;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class OrganizationRepositoryTests
{
[CiSkippedTheory, EfOrganizationAutoData]
public async void CreateAsync_Works_DataMatches(
TableModel.Organization organization,
SqlRepo.OrganizationRepository sqlOrganizationRepo, OrganizationCompare equalityComparer,
List<EfRepo.OrganizationRepository> suts)
{
var savedOrganizations = new List<TableModel.Organization>();
foreach (var sut in suts)
{
var postEfOrganization = await sut.CreateAsync(organization);
sut.ClearChangeTracking();
var savedOrganization = await sut.GetByIdAsync(organization.Id);
savedOrganizations.Add(savedOrganization);
}
var sqlOrganization = await sqlOrganizationRepo.CreateAsync(organization);
savedOrganizations.Add(await sqlOrganizationRepo.GetByIdAsync(sqlOrganization.Id));
var distinctItems = savedOrganizations.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfOrganizationAutoData]
public async void ReplaceAsync_Works_DataMatches(TableModel.Organization postOrganization,
TableModel.Organization replaceOrganization, SqlRepo.OrganizationRepository sqlOrganizationRepo,
OrganizationCompare equalityComparer, List<EfRepo.OrganizationRepository> suts)
{
var savedOrganizations = new List<TableModel.Organization>();
foreach (var sut in suts)
{
var postEfOrganization = await sut.CreateAsync(postOrganization);
sut.ClearChangeTracking();
replaceOrganization.Id = postEfOrganization.Id;
await sut.ReplaceAsync(replaceOrganization);
sut.ClearChangeTracking();
var replacedOrganization = await sut.GetByIdAsync(replaceOrganization.Id);
savedOrganizations.Add(replacedOrganization);
}
var postSqlOrganization = await sqlOrganizationRepo.CreateAsync(postOrganization);
replaceOrganization.Id = postSqlOrganization.Id;
await sqlOrganizationRepo.ReplaceAsync(replaceOrganization);
savedOrganizations.Add(await sqlOrganizationRepo.GetByIdAsync(replaceOrganization.Id));
var distinctItems = savedOrganizations.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfOrganizationAutoData]
public async void DeleteAsync_Works_DataMatches(TableModel.Organization organization,
SqlRepo.OrganizationRepository sqlOrganizationRepo, OrganizationCompare equalityComparer,
List<EfRepo.OrganizationRepository> suts)
{
foreach (var sut in suts)
{
var postEfOrganization = await sut.CreateAsync(organization);
sut.ClearChangeTracking();
var savedEfOrganization = await sut.GetByIdAsync(postEfOrganization.Id);
sut.ClearChangeTracking();
Assert.True(savedEfOrganization != null);
await sut.DeleteAsync(savedEfOrganization);
sut.ClearChangeTracking();
savedEfOrganization = await sut.GetByIdAsync(savedEfOrganization.Id);
Assert.True(savedEfOrganization == null);
}
var postSqlOrganization = await sqlOrganizationRepo.CreateAsync(organization);
var savedSqlOrganization = await sqlOrganizationRepo.GetByIdAsync(postSqlOrganization.Id);
Assert.True(savedSqlOrganization != null);
await sqlOrganizationRepo.DeleteAsync(postSqlOrganization);
savedSqlOrganization = await sqlOrganizationRepo.GetByIdAsync(postSqlOrganization.Id);
Assert.True(savedSqlOrganization == null);
}
[CiSkippedTheory, EfOrganizationAutoData]
public async void GetByIdentifierAsync_Works_DataMatches(TableModel.Organization organization,
SqlRepo.OrganizationRepository sqlOrganizationRepo, OrganizationCompare equalityComparer,
List<EfRepo.OrganizationRepository> suts)
{
var returnedOrgs = new List<TableModel.Organization>();
foreach (var sut in suts)
{
var postEfOrg = await sut.CreateAsync(organization);
sut.ClearChangeTracking();
var returnedOrg = await sut.GetByIdentifierAsync(postEfOrg.Identifier.ToUpperInvariant());
returnedOrgs.Add(returnedOrg);
}
var postSqlOrg = await sqlOrganizationRepo.CreateAsync(organization);
returnedOrgs.Add(await sqlOrganizationRepo.GetByIdentifierAsync(postSqlOrg.Identifier.ToUpperInvariant()));
var distinctItems = returnedOrgs.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfOrganizationAutoData]
public async void GetManyByEnabledAsync_Works_DataMatches(TableModel.Organization organization,
SqlRepo.OrganizationRepository sqlOrganizationRepo, OrganizationCompare equalityCompare,
List<EfRepo.OrganizationRepository> suts)
{
var returnedOrgs = new List<TableModel.Organization>();
foreach (var sut in suts)
{
var postEfOrg = await sut.CreateAsync(organization);
sut.ClearChangeTracking();
var efReturnedOrgs = await sut.GetManyByEnabledAsync();
returnedOrgs.Concat(efReturnedOrgs);
}
var postSqlOrg = await sqlOrganizationRepo.CreateAsync(organization);
returnedOrgs.Concat(await sqlOrganizationRepo.GetManyByEnabledAsync());
Assert.True(returnedOrgs.All(o => o.Enabled));
}
// testing data matches here would require manipulating all organization abilities in the db
[CiSkippedTheory, EfOrganizationAutoData]
public async void GetManyAbilitiesAsync_Works(TableModel.Organization organization,
SqlRepo.OrganizationRepository sqlOrganizationRepo, OrganizationCompare equalityComparer,
List<EfRepo.OrganizationRepository> suts)
{
var list = new List<OrganizationAbility>();
foreach (var sut in suts)
{
list.Concat(await sut.GetManyAbilitiesAsync());
}
list.Concat(await sqlOrganizationRepo.GetManyAbilitiesAsync());
Assert.True(list.All(x => x.GetType() == typeof(OrganizationAbility)));
}
}
}

View File

@ -0,0 +1,152 @@
using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using System.Collections.Generic;
using System.Linq;
using TableModel = Bit.Core.Models.Table;
using Xunit;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Bit.Core.Models.Data;
using System;
using Bit.Core.Test.AutoFixture.Attributes;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class OrganizationUserRepositoryTests
{
[CiSkippedTheory, EfOrganizationUserAutoData]
public async void CreateAsync_Works_DataMatches(TableModel.OrganizationUser orgUser, TableModel.User user, TableModel.Organization org,
OrganizationUserCompare equalityComparer, List<EfRepo.OrganizationUserRepository> suts,
List<EfRepo.OrganizationRepository> efOrgRepos, List<EfRepo.UserRepository> efUserRepos,
SqlRepo.OrganizationUserRepository sqlOrgUserRepo, SqlRepo.UserRepository sqlUserRepo,
SqlRepo.OrganizationRepository sqlOrgRepo)
{
var savedOrgUsers = new List<TableModel.OrganizationUser>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var postEfUser = await efUserRepos[i].CreateAsync(user);
var postEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
orgUser.UserId = postEfUser.Id;
orgUser.OrganizationId = postEfOrg.Id;
var postEfOrgUser = await sut.CreateAsync(orgUser);
sut.ClearChangeTracking();
var savedOrgUser = await sut.GetByIdAsync(postEfOrgUser.Id);
savedOrgUsers.Add(savedOrgUser);
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
var postSqlOrg = await sqlOrgRepo.CreateAsync(org);
orgUser.UserId = postSqlUser.Id;
orgUser.OrganizationId = postSqlOrg.Id;
var sqlOrgUser = await sqlOrgUserRepo.CreateAsync(orgUser);
var savedSqlOrgUser = await sqlOrgUserRepo.GetByIdAsync(sqlOrgUser.Id);
savedOrgUsers.Add(savedSqlOrgUser);
var distinctItems = savedOrgUsers.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfOrganizationUserAutoData]
public async void ReplaceAsync_Works_DataMatches(
TableModel.OrganizationUser postOrgUser,
TableModel.OrganizationUser replaceOrgUser,
TableModel.User user,
TableModel.Organization org,
OrganizationUserCompare equalityComparer,
List<EfRepo.OrganizationUserRepository> suts,
List<EfRepo.UserRepository> efUserRepos,
List<EfRepo.OrganizationRepository> efOrgRepos,
SqlRepo.OrganizationUserRepository sqlOrgUserRepo,
SqlRepo.UserRepository sqlUserRepo,
SqlRepo.OrganizationRepository sqlOrgRepo
)
{
var savedOrgUsers = new List<TableModel.OrganizationUser>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var postEfUser = await efUserRepos[i].CreateAsync(user);
var postEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
postOrgUser.UserId = replaceOrgUser.UserId = postEfUser.Id;
postOrgUser.OrganizationId = replaceOrgUser.OrganizationId = postEfOrg.Id;
var postEfOrgUser = await sut.CreateAsync(postOrgUser);
sut.ClearChangeTracking();
replaceOrgUser.Id = postOrgUser.Id;
await sut.ReplaceAsync(replaceOrgUser);
sut.ClearChangeTracking();
var replacedOrganizationUser = await sut.GetByIdAsync(replaceOrgUser.Id);
savedOrgUsers.Add(replacedOrganizationUser);
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
var postSqlOrg = await sqlOrgRepo.CreateAsync(org);
postOrgUser.UserId = replaceOrgUser.UserId = postSqlUser.Id;
postOrgUser.OrganizationId = replaceOrgUser.OrganizationId = postSqlOrg.Id;
var postSqlOrgUser = await sqlOrgUserRepo.CreateAsync(postOrgUser);
replaceOrgUser.Id = postSqlOrgUser.Id;
await sqlOrgUserRepo.ReplaceAsync(replaceOrgUser);
var replacedSqlUser = await sqlOrgUserRepo.GetByIdAsync(replaceOrgUser.Id);
var distinctItems = savedOrgUsers.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfOrganizationUserAutoData]
public async void DeleteAsync_Works_DataMatches(TableModel.OrganizationUser orgUser, TableModel.User user, TableModel.Organization org,
OrganizationUserCompare equalityComparer, List<EfRepo.OrganizationUserRepository> suts,
List<EfRepo.UserRepository> efUserRepos, List<EfRepo.OrganizationRepository> efOrgRepos,
SqlRepo.OrganizationUserRepository sqlOrgUserRepo, SqlRepo.UserRepository sqlUserRepo,
SqlRepo.OrganizationRepository sqlOrgRepo)
{
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var postEfUser = await efUserRepos[i].CreateAsync(user);
var postEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
orgUser.UserId = postEfUser.Id;
orgUser.OrganizationId = postEfOrg.Id;
var postEfOrgUser = await sut.CreateAsync(orgUser);
sut.ClearChangeTracking();
var savedEfOrgUser = await sut.GetByIdAsync(postEfOrgUser.Id);
Assert.True(savedEfOrgUser != null);
sut.ClearChangeTracking();
await sut.DeleteAsync(savedEfOrgUser);
sut.ClearChangeTracking();
savedEfOrgUser = await sut.GetByIdAsync(savedEfOrgUser.Id);
Assert.True(savedEfOrgUser == null);
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
var postSqlOrg = await sqlOrgRepo.CreateAsync(org);
orgUser.UserId = postSqlUser.Id;
orgUser.OrganizationId = postSqlOrg.Id;
var postSqlOrgUser = await sqlOrgUserRepo.CreateAsync(orgUser);
var savedSqlOrgUser = await sqlOrgUserRepo.GetByIdAsync(postSqlOrgUser.Id);
Assert.True(savedSqlOrgUser != null);
await sqlOrgUserRepo.DeleteAsync(postSqlOrgUser);
savedSqlOrgUser = await sqlOrgUserRepo.GetByIdAsync(postSqlOrgUser.Id);
Assert.True(savedSqlOrgUser == null);
}
}
}

View File

@ -0,0 +1,56 @@
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.PolicyFixtures;
using Microsoft.EntityFrameworkCore;
using Xunit;
using TableModel = Bit.Core.Models.Table;
using System.Linq;
using System.Collections.Generic;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class PolicyRepositoryTests
{
[CiSkippedTheory, EfPolicyAutoData]
public async void CreateAsync_Works_DataMatches(
TableModel.Policy policy,
TableModel.Organization organization,
PolicyCompare equalityComparer,
List<EfRepo.PolicyRepository> suts,
List<EfRepo.OrganizationRepository> efOrganizationRepos,
SqlRepo.PolicyRepository sqlPolicyRepo,
SqlRepo.OrganizationRepository sqlOrganizationRepo
)
{
var savedPolicys = new List<TableModel.Policy>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efOrganization = await efOrganizationRepos[i].CreateAsync(organization);
sut.ClearChangeTracking();
policy.OrganizationId = efOrganization.Id;
var postEfPolicy = await sut.CreateAsync(policy);
sut.ClearChangeTracking();
var savedPolicy = await sut.GetByIdAsync(postEfPolicy.Id);
savedPolicys.Add(savedPolicy);
}
var sqlOrganization = await sqlOrganizationRepo.CreateAsync(organization);
policy.OrganizationId = sqlOrganization.Id;
var sqlPolicy = await sqlPolicyRepo.CreateAsync(policy);
var savedSqlPolicy = await sqlPolicyRepo.GetByIdAsync(sqlPolicy.Id);
savedPolicys.Add(savedSqlPolicy);
var distinctItems = savedPolicys.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,67 @@
using System.Collections.Generic;
using Bit.Core.Models.Table;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.SendFixtures;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Xunit;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using System.Linq;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class SendRepositoryTests
{
[CiSkippedTheory, EfUserSendAutoData, EfOrganizationSendAutoData]
public async void CreateAsync_Works_DataMatches(
Send send,
User user,
Organization org,
SendCompare equalityComparer,
List<EfRepo.SendRepository> suts,
List<EfRepo.UserRepository> efUserRepos,
List<EfRepo.OrganizationRepository> efOrgRepos,
SqlRepo.SendRepository sqlSendRepo,
SqlRepo.UserRepository sqlUserRepo,
SqlRepo.OrganizationRepository sqlOrgRepo
)
{
var savedSends = new List<Send>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
if (send.OrganizationId.HasValue)
{
var efOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
send.OrganizationId = efOrg.Id;
}
var efUser = await efUserRepos[i].CreateAsync(user);
sut.ClearChangeTracking();
send.UserId = efUser.Id;
var postEfSend = await sut.CreateAsync(send);
sut.ClearChangeTracking();
var savedSend = await sut.GetByIdAsync(postEfSend.Id);
savedSends.Add(savedSend);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
if (send.OrganizationId.HasValue)
{
var sqlOrg = await sqlOrgRepo.CreateAsync(org);
send.OrganizationId = sqlOrg.Id;
}
send.UserId = sqlUser.Id;
var sqlSend = await sqlSendRepo.CreateAsync(send);
var savedSqlSend = await sqlSendRepo.GetByIdAsync(sqlSend.Id);
savedSends.Add(savedSqlSend);
var distinctItems = savedSends.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,233 @@
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.Helpers.Factories;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using System.Collections.Generic;
using System.Linq;
using Bit.Core.Models.Table;
using Xunit;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Bit.Core.Test.AutoFixture.SsoConfigFixtures;
using System;
using Bit.Core.Test.AutoFixture.Attributes;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class SsoConfigRepositoryTests
{
[CiSkippedTheory, EfSsoConfigAutoData]
public async void CreateAsync_Works_DataMatches(SsoConfig ssoConfig, Organization org,
SsoConfigCompare equalityComparer, List<EfRepo.SsoConfigRepository> suts,
List<EfRepo.OrganizationRepository> efOrgRepos, SqlRepo.SsoConfigRepository sqlSsoConfigRepo,
SqlRepo.OrganizationRepository sqlOrganizationRepo)
{
var savedSsoConfigs = new List<SsoConfig>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var savedEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
ssoConfig.OrganizationId = savedEfOrg.Id;
var postEfSsoConfig = await sut.CreateAsync(ssoConfig);
sut.ClearChangeTracking();
var savedEfSsoConfig = await sut.GetByIdAsync(ssoConfig.Id);
Assert.True(savedEfSsoConfig != null);
savedSsoConfigs.Add(savedEfSsoConfig);
}
var sqlOrganization = await sqlOrganizationRepo.CreateAsync(org);
ssoConfig.OrganizationId = sqlOrganization.Id;
var sqlSsoConfig = await sqlSsoConfigRepo.CreateAsync(ssoConfig);
var savedSqlSsoConfig = await sqlSsoConfigRepo.GetByIdAsync(sqlSsoConfig.Id);
Assert.True(savedSqlSsoConfig != null);
savedSsoConfigs.Add(savedSqlSsoConfig);
var distinctItems = savedSsoConfigs.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfSsoConfigAutoData]
public async void ReplaceAsync_Works_DataMatches(SsoConfig postSsoConfig, SsoConfig replaceSsoConfig,
Organization org, SsoConfigCompare equalityComparer, List<EfRepo.SsoConfigRepository> suts,
List<EfRepo.OrganizationRepository> efOrgRepos, SqlRepo.SsoConfigRepository sqlSsoConfigRepo,
SqlRepo.OrganizationRepository sqlOrganizationRepo)
{
var savedSsoConfigs = new List<SsoConfig>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var savedEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
postSsoConfig.OrganizationId = replaceSsoConfig.OrganizationId = savedEfOrg.Id;
var postEfSsoConfig = await sut.CreateAsync(postSsoConfig);
sut.ClearChangeTracking();
replaceSsoConfig.Id = postEfSsoConfig.Id;
savedSsoConfigs.Add(postEfSsoConfig);
await sut.ReplaceAsync(replaceSsoConfig);
sut.ClearChangeTracking();
var replacedSsoConfig = await sut.GetByIdAsync(replaceSsoConfig.Id);
Assert.True(replacedSsoConfig != null);
savedSsoConfigs.Add(replacedSsoConfig);
}
var sqlOrganization = await sqlOrganizationRepo.CreateAsync(org);
postSsoConfig.OrganizationId = sqlOrganization.Id;
var postSqlSsoConfig = await sqlSsoConfigRepo.CreateAsync(postSsoConfig);
replaceSsoConfig.Id = postSqlSsoConfig.Id;
savedSsoConfigs.Add(postSqlSsoConfig);
await sqlSsoConfigRepo.ReplaceAsync(replaceSsoConfig);
var replacedSqlSsoConfig = await sqlSsoConfigRepo.GetByIdAsync(replaceSsoConfig.Id);
Assert.True(replacedSqlSsoConfig != null);
savedSsoConfigs.Add(replacedSqlSsoConfig);
var distinctItems = savedSsoConfigs.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(2).Any());
}
[CiSkippedTheory, EfSsoConfigAutoData]
public async void DeleteAsync_Works_DataMatches(SsoConfig ssoConfig, Organization org,
SsoConfigCompare equalityComparer, List<EfRepo.SsoConfigRepository> suts,
List<EfRepo.OrganizationRepository> efOrgRepos, SqlRepo.SsoConfigRepository sqlSsoConfigRepo,
SqlRepo.OrganizationRepository sqlOrganizationRepo)
{
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var savedEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
ssoConfig.OrganizationId = savedEfOrg.Id;
var postEfSsoConfig = await sut.CreateAsync(ssoConfig);
sut.ClearChangeTracking();
var savedEfSsoConfig = await sut.GetByIdAsync(postEfSsoConfig.Id);
Assert.True(savedEfSsoConfig != null);
sut.ClearChangeTracking();
await sut.DeleteAsync(savedEfSsoConfig);
var deletedEfSsoConfig= await sut.GetByIdAsync(savedEfSsoConfig.Id);
Assert.True(deletedEfSsoConfig == null);
}
var sqlOrganization = await sqlOrganizationRepo.CreateAsync(org);
ssoConfig.OrganizationId = sqlOrganization.Id;
var postSqlSsoConfig = await sqlSsoConfigRepo.CreateAsync(ssoConfig);
var savedSqlSsoConfig = await sqlSsoConfigRepo.GetByIdAsync(postSqlSsoConfig.Id);
Assert.True(savedSqlSsoConfig != null);
await sqlSsoConfigRepo.DeleteAsync(savedSqlSsoConfig);
savedSqlSsoConfig = await sqlSsoConfigRepo.GetByIdAsync(postSqlSsoConfig.Id);
Assert.True(savedSqlSsoConfig == null);
}
[CiSkippedTheory, EfSsoConfigAutoData]
public async void GetByOrganizationIdAsync_Works_DataMatches(SsoConfig ssoConfig, Organization org,
SsoConfigCompare equalityComparer, List<EfRepo.SsoConfigRepository> suts,
List<EfRepo.OrganizationRepository> efOrgRepos, SqlRepo.SsoConfigRepository sqlSsoConfigRepo,
SqlRepo.OrganizationRepository sqlOrgRepo)
{
var returnedList = new List<SsoConfig>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var savedEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
ssoConfig.OrganizationId = savedEfOrg.Id;
await sut.CreateAsync(ssoConfig);
sut.ClearChangeTracking();
var savedEfUser = await sut.GetByOrganizationIdAsync(savedEfOrg.Id);
Assert.True(savedEfUser != null);
returnedList.Add(savedEfUser);
}
var savedSqlOrg = await sqlOrgRepo.CreateAsync(org);
ssoConfig.OrganizationId = savedSqlOrg.Id;
var postSqlSsoConfig = await sqlSsoConfigRepo.CreateAsync(ssoConfig);
var savedSqlSsoConfig = await sqlSsoConfigRepo.GetByOrganizationIdAsync(ssoConfig.OrganizationId);
Assert.True(savedSqlSsoConfig != null);
returnedList.Add(savedSqlSsoConfig);
var distinctItems = returnedList.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfSsoConfigAutoData]
public async void GetByIdentifierAsync_Works_DataMatches(SsoConfig ssoConfig, Organization org,
SsoConfigCompare equalityComparer, List<EfRepo.SsoConfigRepository> suts,
List<EfRepo.OrganizationRepository> efOrgRepos, SqlRepo.SsoConfigRepository sqlSsoConfigRepo,
SqlRepo.OrganizationRepository sqlOrgRepo)
{
var returnedList = new List<SsoConfig>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var savedEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
ssoConfig.OrganizationId = savedEfOrg.Id;
await sut.CreateAsync(ssoConfig);
sut.ClearChangeTracking();
var savedEfSsoConfig = await sut.GetByIdentifierAsync(org.Identifier);
Assert.True(savedEfSsoConfig != null);
returnedList.Add(savedEfSsoConfig);
}
var savedSqlOrg = await sqlOrgRepo.CreateAsync(org);
ssoConfig.OrganizationId = savedSqlOrg.Id;
var postSqlSsoConfig = await sqlSsoConfigRepo.CreateAsync(ssoConfig);
var savedSqlSsoConfig = await sqlSsoConfigRepo.GetByIdentifierAsync(org.Identifier);
Assert.True(savedSqlSsoConfig != null);
returnedList.Add(savedSqlSsoConfig);
var distinctItems = returnedList.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
// Testing that data matches here would involve manipulating all SsoConfig records in the db
[CiSkippedTheory, EfSsoConfigAutoData]
public async void GetManyByRevisionNotBeforeDate_Works(SsoConfig ssoConfig, DateTime notBeforeDate,
Organization org, SsoConfigCompare equalityComparer, List<EfRepo.SsoConfigRepository> suts,
List<EfRepo.OrganizationRepository> efOrgRepos)
{
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var savedEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
ssoConfig.OrganizationId = savedEfOrg.Id;
await sut.CreateAsync(ssoConfig);
sut.ClearChangeTracking();
var returnedEfSsoConfigs = await sut.GetManyByRevisionNotBeforeDate(notBeforeDate);
Assert.True(returnedEfSsoConfigs.All(sc => sc.RevisionDate >= notBeforeDate));
}
}
}
}

View File

@ -0,0 +1,192 @@
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.Helpers.Factories;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using System.Collections.Generic;
using System.Linq;
using Bit.Core.Models.Table;
using Xunit;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Bit.Core.Test.AutoFixture.SsoUserFixtures;
using Bit.Core.Test.AutoFixture.Attributes;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class SsoUserRepositoryTests
{
[CiSkippedTheory, EfSsoUserAutoData]
public async void CreateAsync_Works_DataMatches(SsoUser ssoUser, User user, Organization org,
SsoUserCompare equalityComparer, List<EfRepo.SsoUserRepository> suts,
List<EfRepo.OrganizationRepository> efOrgRepos, List<EfRepo.UserRepository> efUserRepos,
SqlRepo.SsoUserRepository sqlSsoUserRepo, SqlRepo.OrganizationRepository sqlOrgRepo,
SqlRepo.UserRepository sqlUserRepo)
{
var createdSsoUsers = new List<SsoUser>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efUser = await efUserRepos[i].CreateAsync(user);
var efOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
ssoUser.UserId = efUser.Id;
ssoUser.OrganizationId = efOrg.Id;
var postEfSsoUser = await sut.CreateAsync(ssoUser);
sut.ClearChangeTracking();
var savedSsoUser = await sut.GetByIdAsync(ssoUser.Id);
createdSsoUsers.Add(savedSsoUser);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
var sqlOrganization = await sqlOrgRepo.CreateAsync(org);
ssoUser.UserId = sqlUser.Id;
ssoUser.OrganizationId = sqlOrganization.Id;
var sqlSsoUser = await sqlSsoUserRepo.CreateAsync(ssoUser);
createdSsoUsers.Add(await sqlSsoUserRepo.GetByIdAsync(sqlSsoUser.Id));
var distinctSsoUsers = createdSsoUsers.Distinct(equalityComparer);
Assert.True(!distinctSsoUsers.Skip(1).Any());
}
[CiSkippedTheory, EfSsoUserAutoData]
public async void ReplaceAsync_Works_DataMatches(SsoUser postSsoUser, SsoUser replaceSsoUser,
Organization org, User user, SsoUserCompare equalityComparer,
List<EfRepo.SsoUserRepository> suts, List<EfRepo.UserRepository> efUserRepos,
List<EfRepo.OrganizationRepository> efOrgRepos, SqlRepo.SsoUserRepository sqlSsoUserRepo,
SqlRepo.OrganizationRepository sqlOrgRepo, SqlRepo.UserRepository sqlUserRepo)
{
var savedSsoUsers = new List<SsoUser>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efUser = await efUserRepos[i].CreateAsync(user);
var efOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
postSsoUser.UserId = efUser.Id;
postSsoUser.OrganizationId = efOrg.Id;
var postEfSsoUser = await sut.CreateAsync(postSsoUser);
sut.ClearChangeTracking();
replaceSsoUser.Id = postEfSsoUser.Id;
replaceSsoUser.UserId = postEfSsoUser.UserId;
replaceSsoUser.OrganizationId = postEfSsoUser.OrganizationId;
await sut.ReplaceAsync(replaceSsoUser);
sut.ClearChangeTracking();
var replacedSsoUser = await sut.GetByIdAsync(replaceSsoUser.Id);
savedSsoUsers.Add(replacedSsoUser);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
var sqlOrganization = await sqlOrgRepo.CreateAsync(org);
postSsoUser.UserId = sqlUser.Id;
postSsoUser.OrganizationId = sqlOrganization.Id;
var postSqlSsoUser = await sqlSsoUserRepo.CreateAsync(postSsoUser);
replaceSsoUser.Id = postSqlSsoUser.Id;
replaceSsoUser.UserId = postSqlSsoUser.UserId;
replaceSsoUser.OrganizationId = postSqlSsoUser.OrganizationId;
await sqlSsoUserRepo.ReplaceAsync(replaceSsoUser);
savedSsoUsers.Add(await sqlSsoUserRepo.GetByIdAsync(replaceSsoUser.Id));
var distinctItems = savedSsoUsers.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfSsoUserAutoData]
public async void DeleteAsync_Works_DataMatches(SsoUser ssoUser, Organization org, User user,
SsoUserCompare equalityComparer, List<EfRepo.SsoUserRepository> suts,
List<EfRepo.UserRepository> efUserRepos, List<EfRepo.OrganizationRepository> efOrgRepos,
SqlRepo.SsoUserRepository sqlSsoUserRepo, SqlRepo.UserRepository sqlUserRepo,
SqlRepo.OrganizationRepository sqlOrganizationRepo)
{
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var savedEfUser = await efUserRepos[i].CreateAsync(user);
var savedEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
ssoUser.UserId = savedEfUser.Id;
ssoUser.OrganizationId = savedEfOrg.Id;
var postEfSsoUser = await sut.CreateAsync(ssoUser);
sut.ClearChangeTracking();
var savedEfSsoUser = await sut.GetByIdAsync(postEfSsoUser.Id);
Assert.True(savedEfSsoUser != null);
sut.ClearChangeTracking();
await sut.DeleteAsync(savedEfSsoUser);
savedEfSsoUser = await sut.GetByIdAsync(savedEfSsoUser.Id);
Assert.True(savedEfSsoUser == null);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
var sqlOrganization = await sqlOrganizationRepo.CreateAsync(org);
ssoUser.UserId = sqlUser.Id;
ssoUser.OrganizationId = sqlOrganization.Id;
var postSqlSsoUser = await sqlSsoUserRepo.CreateAsync(ssoUser);
var savedSqlSsoUser = await sqlSsoUserRepo.GetByIdAsync(postSqlSsoUser.Id);
Assert.True(savedSqlSsoUser != null);
await sqlSsoUserRepo.DeleteAsync(savedSqlSsoUser);
savedSqlSsoUser = await sqlSsoUserRepo.GetByIdAsync(postSqlSsoUser.Id);
Assert.True(savedSqlSsoUser == null);
}
[CiSkippedTheory, EfSsoUserAutoData]
public async void DeleteAsync_UserIdOrganizationId_Works_DataMatches(SsoUser ssoUser,
User user, Organization org, SsoUserCompare equalityComparer, List<EfRepo.SsoUserRepository> suts,
List<EfRepo.UserRepository> efUserRepos, List<EfRepo.OrganizationRepository> efOrgRepos,
SqlRepo.SsoUserRepository sqlSsoUserRepo, SqlRepo.UserRepository sqlUserRepo, SqlRepo.OrganizationRepository sqlOrgRepo
)
{
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var savedEfUser = await efUserRepos[i].CreateAsync(user);
var savedEfOrg = await efOrgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
ssoUser.UserId = savedEfUser.Id;
ssoUser.OrganizationId = savedEfOrg.Id;
var postEfSsoUser = await sut.CreateAsync(ssoUser);
sut.ClearChangeTracking();
var savedEfSsoUser = await sut.GetByIdAsync(postEfSsoUser.Id);
Assert.True(savedEfSsoUser != null);
sut.ClearChangeTracking();
await sut.DeleteAsync(savedEfSsoUser.UserId, savedEfSsoUser.OrganizationId);
sut.ClearChangeTracking();
savedEfSsoUser = await sut.GetByIdAsync(savedEfSsoUser.Id);
Assert.True(savedEfSsoUser == null);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
var sqlOrganization = await sqlOrgRepo.CreateAsync(org);
ssoUser.UserId = sqlUser.Id;
ssoUser.OrganizationId = sqlOrganization.Id;
var postSqlSsoUser = await sqlSsoUserRepo.CreateAsync(ssoUser);
var savedSqlSsoUser = await sqlSsoUserRepo.GetByIdAsync(postSqlSsoUser.Id);
Assert.True(savedSqlSsoUser != null);
await sqlSsoUserRepo.DeleteAsync(savedSqlSsoUser.UserId, savedSqlSsoUser.OrganizationId);
savedSqlSsoUser = await sqlSsoUserRepo.GetByIdAsync(postSqlSsoUser.Id);
Assert.True(savedSqlSsoUser == null);
}
}
}

View File

@ -0,0 +1,42 @@
using System.Collections.Generic;
using System.Linq;
using Bit.Core.Models.Table;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.TaxRateFixtures;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Xunit;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class TaxRateRepositoryTests
{
[CiSkippedTheory, EfTaxRateAutoData]
public async void CreateAsync_Works_DataMatches(
TaxRate taxRate,
TaxRateCompare equalityComparer,
List<EfRepo.TaxRateRepository> suts,
SqlRepo.TaxRateRepository sqlTaxRateRepo
)
{
var savedTaxRates = new List<TaxRate>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var postEfTaxRate = await sut.CreateAsync(taxRate);
sut.ClearChangeTracking();
var savedTaxRate = await sut.GetByIdAsync(postEfTaxRate.Id);
savedTaxRates.Add(savedTaxRate);
}
var sqlTaxRate = await sqlTaxRateRepo.CreateAsync(taxRate);
var savedSqlTaxRate = await sqlTaxRateRepo.GetByIdAsync(sqlTaxRate.Id);
savedTaxRates.Add(savedSqlTaxRate);
var distinctItems = savedTaxRates.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,69 @@
using System.Collections.Generic;
using Bit.Core.Models.Table;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.TransactionFixtures;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Microsoft.EntityFrameworkCore;
using Xunit;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using System.Linq;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class TransactionRepositoryTests
{
[CiSkippedTheory, EfUserTransactionAutoData, EfOrganizationTransactionAutoData]
public async void CreateAsync_Works_DataMatches(
Transaction transaction,
User user,
Organization org,
TransactionCompare equalityComparer,
List<EfRepo.TransactionRepository> suts,
List<EfRepo.UserRepository> efUserRepos,
List<EfRepo.OrganizationRepository> efOrgRepos,
SqlRepo.TransactionRepository sqlTransactionRepo,
SqlRepo.UserRepository sqlUserRepo,
SqlRepo.OrganizationRepository sqlOrgRepo
)
{
var savedTransactions = new List<Transaction>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efUser = await efUserRepos[i].CreateAsync(user);
if (transaction.OrganizationId.HasValue)
{
var efOrg = await efOrgRepos[i].CreateAsync(org);
transaction.OrganizationId = efOrg.Id;
}
sut.ClearChangeTracking();
transaction.UserId = efUser.Id;
var postEfTransaction = await sut.CreateAsync(transaction);
sut.ClearChangeTracking();
var savedTransaction = await sut.GetByIdAsync(postEfTransaction.Id);
savedTransactions.Add(savedTransaction);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
if (transaction.OrganizationId.HasValue)
{
var sqlOrg = await sqlOrgRepo.CreateAsync(org);
transaction.OrganizationId = sqlOrg.Id;
}
transaction.UserId = sqlUser.Id;
var sqlTransaction = await sqlTransactionRepo.CreateAsync(transaction);
var savedSqlTransaction = await sqlTransactionRepo.GetByIdAsync(sqlTransaction.Id);
savedTransactions.Add(savedSqlTransaction);
var distinctItems = savedTransactions.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,57 @@
using System.Collections.Generic;
using System.Linq;
using Bit.Core.Models.Table;
using Bit.Core.Repositories.EntityFramework;
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.U2fFixtures;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Microsoft.EntityFrameworkCore;
using Xunit;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class U2fRepositoryTests
{
[CiSkippedTheory, EfU2fAutoData]
public async void CreateAsync_Works_DataMatches(
U2f u2f,
User user,
U2fCompare equalityComparer,
List<EfRepo.U2fRepository> suts,
List<EfRepo.UserRepository> efUserRepos,
SqlRepo.U2fRepository sqlU2fRepo,
SqlRepo.UserRepository sqlUserRepo
)
{
var savedU2fs = new List<U2f>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var efUser = await efUserRepos[i].CreateAsync(user);
sut.ClearChangeTracking();
u2f.UserId = efUser.Id;
var postEfU2f = await sut.CreateAsync(u2f);
sut.ClearChangeTracking();
var savedU2f = await sut.GetByIdAsync(postEfU2f.Id);
savedU2fs.Add(savedU2f);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
u2f.UserId = sqlUser.Id;
var sqlU2f = await sqlU2fRepo.CreateAsync(u2f);
var savedSqlU2f = await sqlU2fRepo.GetByIdAsync(sqlU2f.Id);
savedU2fs.Add(savedSqlU2f);
var distinctItems = savedU2fs.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -0,0 +1,294 @@
using Bit.Core.Test.AutoFixture.UserFixtures;
using EfRepo = Bit.Core.Repositories.EntityFramework;
using SqlRepo = Bit.Core.Repositories.SqlServer;
using System.Collections.Generic;
using System.Linq;
using Bit.Core.Models.Table;
using Xunit;
using Bit.Core.Test.Repositories.EntityFramework.EqualityComparers;
using Bit.Core.Models.Data;
using System;
using Bit.Core.Test.AutoFixture.Attributes;
namespace Bit.Core.Test.Repositories.EntityFramework
{
public class UserRepositoryTests
{
[CiSkippedTheory, EfUserAutoData]
public async void CreateAsync_Works_DataMatches(
User user, UserCompare equalityComparer,
List<EfRepo.UserRepository> suts,
SqlRepo.UserRepository sqlUserRepo
)
{
var savedUsers = new List<User>();
foreach (var sut in suts)
{
var postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
var savedUser = await sut.GetByIdAsync(postEfUser.Id);
savedUsers.Add(savedUser);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
savedUsers.Add(await sqlUserRepo.GetByIdAsync(sqlUser.Id));
var distinctItems = savedUsers.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfUserAutoData]
public async void ReplaceAsync_Works_DataMatches(User postUser, User replaceUser,
UserCompare equalityComparer, List<EfRepo.UserRepository> suts,
SqlRepo.UserRepository sqlUserRepo)
{
var savedUsers = new List<User>();
foreach (var sut in suts)
{
var postEfUser = await sut.CreateAsync(postUser);
replaceUser.Id = postEfUser.Id;
await sut.ReplaceAsync(replaceUser);
var replacedUser = await sut.GetByIdAsync(replaceUser.Id);
savedUsers.Add(replacedUser);
}
var postSqlUser = await sqlUserRepo.CreateAsync(postUser);
replaceUser.Id = postSqlUser.Id;
await sqlUserRepo.ReplaceAsync(replaceUser);
savedUsers.Add(await sqlUserRepo.GetByIdAsync(replaceUser.Id));
var distinctItems = savedUsers.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfUserAutoData]
public async void DeleteAsync_Works_DataMatches(User user, UserCompare equalityComparer,
List<EfRepo.UserRepository> suts, SqlRepo.UserRepository sqlUserRepo)
{
foreach (var sut in suts)
{
var postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
var savedEfUser = await sut.GetByIdAsync(postEfUser.Id);
Assert.True(savedEfUser != null);
sut.ClearChangeTracking();
await sut.DeleteAsync(savedEfUser);
sut.ClearChangeTracking();
savedEfUser = await sut.GetByIdAsync(savedEfUser.Id);
Assert.True(savedEfUser == null);
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
var savedSqlUser = await sqlUserRepo.GetByIdAsync(postSqlUser.Id);
Assert.True(savedSqlUser != null);
await sqlUserRepo.DeleteAsync(postSqlUser);
savedSqlUser = await sqlUserRepo.GetByIdAsync(postSqlUser.Id);
Assert.True(savedSqlUser == null);
}
[CiSkippedTheory, EfUserAutoData]
public async void GetByEmailAsync_Works_DataMatches(User user, UserCompare equalityComparer,
List<EfRepo.UserRepository> suts, SqlRepo.UserRepository sqlUserRepo)
{
var savedUsers = new List<User>();
foreach (var sut in suts)
{
var postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
var savedUser = await sut.GetByEmailAsync(postEfUser.Email.ToUpperInvariant());
savedUsers.Add(savedUser);
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
savedUsers.Add(await sqlUserRepo.GetByEmailAsync(postSqlUser.Email.ToUpperInvariant()));
var distinctItems = savedUsers.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfUserAutoData]
public async void GetKdfInformationByEmailAsync_Works_DataMatches(User user,
UserKdfInformationCompare equalityComparer, List<EfRepo.UserRepository> suts,
SqlRepo.UserRepository sqlUserRepo)
{
var savedKdfInformation = new List<UserKdfInformation>();
foreach (var sut in suts)
{
var postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
var kdfInformation = await sut.GetKdfInformationByEmailAsync(postEfUser.Email.ToUpperInvariant());
savedKdfInformation.Add(kdfInformation);
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
var sqlKdfInformation = await sqlUserRepo.GetKdfInformationByEmailAsync(postSqlUser.Email);
savedKdfInformation.Add(sqlKdfInformation);
var distinctItems = savedKdfInformation.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfUserAutoData]
public async void SearchAsync_Works_DataMatches(User user, int skip, int take,
UserCompare equalityCompare, List<EfRepo.UserRepository> suts,
SqlRepo.UserRepository sqlUserRepo)
{
var searchedEfUsers = new List<User>();
foreach (var sut in suts)
{
var postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
var searchedEfUsersCollection = await sut.SearchAsync(postEfUser.Email.ToUpperInvariant(), skip, take);
searchedEfUsers.Concat(searchedEfUsersCollection.ToList());
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
var searchedSqlUsers = await sqlUserRepo.SearchAsync(postSqlUser.Email.ToUpperInvariant(), skip, take);
var distinctItems = searchedEfUsers.Concat(searchedSqlUsers).Distinct(equalityCompare);
Assert.True(!distinctItems.Skip(1).Any());
}
[CiSkippedTheory, EfUserAutoData]
public async void GetManyByPremiumAsync_Works_DataMatches(User user,
List<EfRepo.UserRepository> suts, SqlRepo.UserRepository sqlUserRepo)
{
var returnedUsers = new List<User>();
foreach (var sut in suts)
{
var postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
var searchedEfUsers = await sut.GetManyByPremiumAsync(user.Premium);
returnedUsers.Concat(searchedEfUsers.ToList());
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
var searchedSqlUsers = await sqlUserRepo.GetManyByPremiumAsync(user.Premium);
returnedUsers.Concat(searchedSqlUsers.ToList());
Assert.True(returnedUsers.All(x => x.Premium == user.Premium));
}
[CiSkippedTheory, EfUserAutoData]
public async void GetPublicKeyAsync_Works_DataMatches(User user, List<EfRepo.UserRepository> suts,
SqlRepo.UserRepository sqlUserRepo)
{
var returnedKeys = new List<string>();
foreach (var sut in suts)
{
var postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
var efKey = await sut.GetPublicKeyAsync(postEfUser.Id);
returnedKeys.Add(efKey);
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
var sqlKey = await sqlUserRepo.GetPublicKeyAsync(postSqlUser.Id);
returnedKeys.Add(sqlKey);
Assert.True(!returnedKeys.Distinct().Skip(1).Any());
}
[CiSkippedTheory, EfUserAutoData]
public async void GetAccountRevisionDateAsync(User user, List<EfRepo.UserRepository> suts,
SqlRepo.UserRepository sqlUserRepo)
{
var returnedKeys = new List<string>();
foreach (var sut in suts)
{
var postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
var efKey = await sut.GetPublicKeyAsync(postEfUser.Id);
returnedKeys.Add(efKey);
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
var sqlKey = await sqlUserRepo.GetPublicKeyAsync(postSqlUser.Id);
returnedKeys.Add(sqlKey);
Assert.True(!returnedKeys.Distinct().Skip(1).Any());
}
[CiSkippedTheory, EfUserAutoData]
public async void UpdateRenewalReminderDateAsync_Works_DataMatches(User user,
DateTime updatedReminderDate, List<EfRepo.UserRepository> suts,
SqlRepo.UserRepository sqlUserRepo)
{
var savedDates = new List<DateTime?>();
foreach (var sut in suts)
{
var postEfUser = user;
postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
await sut.UpdateRenewalReminderDateAsync(postEfUser.Id, updatedReminderDate);
sut.ClearChangeTracking();
var replacedUser = await sut.GetByIdAsync(postEfUser.Id);
savedDates.Add(replacedUser.RenewalReminderDate);
}
var postSqlUser = await sqlUserRepo.CreateAsync(user);
await sqlUserRepo.UpdateRenewalReminderDateAsync(postSqlUser.Id, updatedReminderDate);
var replacedSqlUser = await sqlUserRepo.GetByIdAsync(postSqlUser.Id);
savedDates.Add(replacedSqlUser.RenewalReminderDate);
var distinctItems = savedDates.GroupBy(e => e.ToString());
Assert.True(!distinctItems.Skip(1).Any() &&
savedDates.All(e => e.ToString() == updatedReminderDate.ToString()));
}
[CiSkippedTheory, EfUserAutoData]
public async void GetBySsoUserAsync_Works_DataMatches(User user, Organization org,
SsoUser ssoUser, UserCompare equalityComparer, List<EfRepo.UserRepository> suts,
List<EfRepo.SsoUserRepository> ssoUserRepos, List<EfRepo.OrganizationRepository> orgRepos,
SqlRepo.UserRepository sqlUserRepo, SqlRepo.SsoUserRepository sqlSsoUserRepo,
SqlRepo.OrganizationRepository sqlOrgRepo)
{
var returnedList = new List<User>();
foreach (var sut in suts)
{
var i = suts.IndexOf(sut);
var postEfUser = await sut.CreateAsync(user);
sut.ClearChangeTracking();
var efOrg = await orgRepos[i].CreateAsync(org);
sut.ClearChangeTracking();
ssoUser.UserId = postEfUser.Id;
ssoUser.OrganizationId = efOrg.Id;
var postEfSsoUser = await ssoUserRepos[i].CreateAsync(ssoUser);
sut.ClearChangeTracking();
var returnedUser = await sut.GetBySsoUserAsync(postEfSsoUser.ExternalId.ToUpperInvariant(), efOrg.Id);
returnedList.Add(returnedUser);
}
var sqlUser = await sqlUserRepo.CreateAsync(user);
var sqlOrganization = await sqlOrgRepo.CreateAsync(org);
ssoUser.UserId = sqlUser.Id;
ssoUser.OrganizationId = sqlOrganization.Id;
var postSqlSsoUser = await sqlSsoUserRepo.CreateAsync(ssoUser);
var returnedSqlUser = await sqlUserRepo
.GetBySsoUserAsync(postSqlSsoUser.ExternalId, sqlOrganization.Id);
returnedList.Add(returnedSqlUser);
var distinctItems = returnedList.Distinct(equalityComparer);
Assert.True(!distinctItems.Skip(1).Any());
}
}
}

View File

@ -9,6 +9,7 @@ using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.CollectionFixtures;
using NSubstitute;
using Xunit;

View File

@ -9,6 +9,7 @@ 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 NSubstitute;
using Xunit;

View File

@ -20,6 +20,7 @@ using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
using Organization = Bit.Core.Models.Table.Organization;
using OrganizationUser = Bit.Core.Models.Table.OrganizationUser;
using Policy = Bit.Core.Models.Table.Policy;
using Bit.Core.Test.AutoFixture.PolicyFixtures;
namespace Bit.Core.Test.Services
{

View File

@ -8,6 +8,7 @@ using Bit.Core.Services;
using Bit.Core.Test.AutoFixture;
using Bit.Core.Test.AutoFixture.Attributes;
using Bit.Core.Test.AutoFixture.OrganizationUserFixtures;
using PolicyFixtures = Bit.Core.Test.AutoFixture.PolicyFixtures;
using NSubstitute;
using Xunit;
@ -16,7 +17,7 @@ namespace Bit.Core.Test.Services
public class PolicyServiceTests
{
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_OrganizationDoesNotExist_ThrowsBadRequest([Policy(Enums.PolicyType.DisableSend)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
public async Task SaveAsync_OrganizationDoesNotExist_ThrowsBadRequest([PolicyFixtures.Policy(Enums.PolicyType.DisableSend)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
{
SetupOrg(sutProvider, policy.OrganizationId, null);
@ -38,7 +39,7 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_OrganizationCannotUsePolicies_ThrowsBadRequest([Policy(Enums.PolicyType.DisableSend)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
public async Task SaveAsync_OrganizationCannotUsePolicies_ThrowsBadRequest([PolicyFixtures.Policy(Enums.PolicyType.DisableSend)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
{
var orgId = Guid.NewGuid();
@ -65,7 +66,7 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_SingleOrg_RequireSsoEnabled_ThrowsBadRequest([Policy(Enums.PolicyType.SingleOrg)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
public async Task SaveAsync_SingleOrg_RequireSsoEnabled_ThrowsBadRequest([PolicyFixtures.Policy(Enums.PolicyType.SingleOrg)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
{
policy.Enabled = false;
@ -97,7 +98,7 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_RequireSsoPolicy_NotEnabled_ThrowsBadRequestAsync([Policy(Enums.PolicyType.RequireSso)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
public async Task SaveAsync_RequireSsoPolicy_NotEnabled_ThrowsBadRequestAsync([PolicyFixtures.Policy(Enums.PolicyType.RequireSso)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
{
policy.Enabled = true;
@ -129,7 +130,7 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_NewPolicy_Created([Policy(Enums.PolicyType.MasterPassword)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
public async Task SaveAsync_NewPolicy_Created([PolicyFixtures.Policy(Enums.PolicyType.MasterPassword)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
{
policy.Id = default;
@ -154,7 +155,7 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_ExistingPolicy_UpdateTwoFactor([Policy(Enums.PolicyType.TwoFactorAuthentication)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
public async Task SaveAsync_ExistingPolicy_UpdateTwoFactor([PolicyFixtures.Policy(Enums.PolicyType.TwoFactorAuthentication)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
{
// If the policy that this is updating isn't enabled then do some work now that the current one is enabled
@ -223,7 +224,7 @@ namespace Bit.Core.Test.Services
}
[Theory, CustomAutoData(typeof(SutProviderCustomization))]
public async Task SaveAsync_ExistingPolicy_UpdateSingleOrg([Policy(Enums.PolicyType.TwoFactorAuthentication)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
public async Task SaveAsync_ExistingPolicy_UpdateSingleOrg([PolicyFixtures.Policy(Enums.PolicyType.TwoFactorAuthentication)] Core.Models.Table.Policy policy, SutProvider<PolicyService> sutProvider)
{
// If the policy that this is updating isn't enabled then do some work now that the current one is enabled