diff --git a/Directory.Build.props b/Directory.Build.props
index a98aa02c2a..bd7e8db982 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -1,9 +1,9 @@
 <Project>
 
 	<PropertyGroup>
+		<TargetFramework>net5.0</TargetFramework>
 		<Version>1.41.5</Version>
-		<TargetFramework>netcoreapp3.1</TargetFramework>
 		<RootNamespace>Bit.$(MSBuildProjectName)</RootNamespace>
 	</PropertyGroup>
 
-</Project>
\ No newline at end of file
+</Project>
diff --git a/README.md b/README.md
index 9083fb1318..ea5cc68c53 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ Please read the [Setup guide](https://github.com/bitwarden/server/blob/master/SE
 
 ### Requirements
 
-- [.NET Core 3.1 SDK](https://www.microsoft.com/net/download/core)
+- [.NET Core 5.0 SDK](https://www.microsoft.com/net/download/core)
 - [SQL Server 2017](https://docs.microsoft.com/en-us/sql/index)
 
 *These dependencies are free to use.*
diff --git a/SETUP.md b/SETUP.md
index 77c9b43b6e..06c1ef74eb 100644
--- a/SETUP.md
+++ b/SETUP.md
@@ -91,7 +91,7 @@ User secrets are a method for managing application settings on a per-developer b
 
 User secrets override the settings in `appsettings.json` of each project. Your user secrets file should match the structure of the `appsettings.json` file for the settings you intend to override.
 
-For more information, see: [Safe storage of app secrets in development in ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-3.1).
+For more information, see: [Safe storage of app secrets in development in ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0).
 
 Open the server solution file (`bitwarden-server.sln`) in Visual Studio before proceeding.
 
diff --git a/bitwarden-server.sln b/bitwarden-server.sln
index 75d09e19d2..39f7dc8211 100644
--- a/bitwarden-server.sln
+++ b/bitwarden-server.sln
@@ -72,6 +72,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CommCore.Test", "bitwarden_
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test - Bitwarden License", "test - Bitwarden License", "{287CFF34-BBDB-4BC4-AF88-1E19A5A4679B}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MySqlMigrations", "util\MySqlMigrations\MySqlMigrations.csproj", "{BDC1D592-5947-47ED-9903-7CDBB12A50C8}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PostgresMigrations", "util\PostgresMigrations\PostgresMigrations.csproj", "{F72E0229-2EF7-49B3-9004-FF4C0043816E}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -152,6 +156,15 @@ Global
 		{C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{C7BA2255-C1B1-4789-8BB9-C27540DA6FB8}.Release|Any CPU.Build.0 = Release|Any CPU
+		{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{BDC1D592-5947-47ED-9903-7CDBB12A50C8}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{F72E0229-2EF7-49B3-9004-FF4C0043816E}.Release|Any CPU.Build.0 = Release|Any CPU
+
 		{EDC0D688-D58C-4CE1-AA07-3606AC6874B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 		{EDC0D688-D58C-4CE1-AA07-3606AC6874B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{EDC0D688-D58C-4CE1-AA07-3606AC6874B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -183,6 +196,8 @@ Global
 		{BA852F18-852F-4154-973B-77D577B8CA04} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A}
 		{4866AF64-6640-4C65-A662-A31E02FF9064} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A}
 		{C7BA2255-C1B1-4789-8BB9-C27540DA6FB8} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F}
+		{BDC1D592-5947-47ED-9903-7CDBB12A50C8} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
+		{F72E0229-2EF7-49B3-9004-FF4C0043816E} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E}
 		{EDC0D688-D58C-4CE1-AA07-3606AC6874B8} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A}
 		{0E99A21B-684B-4C59-9831-90F775CAB6F7} = {287CFF34-BBDB-4BC4-AF88-1E19A5A4679B}
 	EndGlobalSection
diff --git a/bitwarden_license/src/CommCore/CommCore.csproj b/bitwarden_license/src/CommCore/CommCore.csproj
index d77902c605..a562ebbe94 100644
--- a/bitwarden_license/src/CommCore/CommCore.csproj
+++ b/bitwarden_license/src/CommCore/CommCore.csproj
@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <TargetFramework>net5.0</TargetFramework>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/bitwarden_license/src/Portal/Dockerfile b/bitwarden_license/src/Portal/Dockerfile
index e361700faa..8668004ffb 100644
--- a/bitwarden_license/src/Portal/Dockerfile
+++ b/bitwarden_license/src/Portal/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden"
 
diff --git a/bitwarden_license/src/Sso/Dockerfile b/bitwarden_license/src/Sso/Dockerfile
index e361700faa..8668004ffb 100644
--- a/bitwarden_license/src/Sso/Dockerfile
+++ b/bitwarden_license/src/Sso/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden"
 
diff --git a/bitwarden_license/test/CmmCore.Test/CommCore.Test.csproj b/bitwarden_license/test/CmmCore.Test/CommCore.Test.csproj
index 50d12b4f8c..5a319e5e89 100644
--- a/bitwarden_license/test/CmmCore.Test/CommCore.Test.csproj
+++ b/bitwarden_license/test/CmmCore.Test/CommCore.Test.csproj
@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <TargetFramework>net5.0</TargetFramework>
 
     <IsPackable>false</IsPackable>
   </PropertyGroup>
diff --git a/src/Admin/Dockerfile b/src/Admin/Dockerfile
index 156091819a..f5a46d67f4 100644
--- a/src/Admin/Dockerfile
+++ b/src/Admin/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden"
 
diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj
index 84264f890f..3a5b1847f5 100644
--- a/src/Api/Api.csproj
+++ b/src/Api/Api.csproj
@@ -28,7 +28,7 @@
   </Choose>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.6" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.2" />
     <PackageReference Include="NewRelic.Agent" Version="8.30.0" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
     <PackageReference Include="Microsoft.Azure.EventGrid" Version="3.2.0" />
diff --git a/src/Api/Dockerfile b/src/Api/Dockerfile
index e361700faa..8668004ffb 100644
--- a/src/Api/Dockerfile
+++ b/src/Api/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden"
 
diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj
index 5db7064b39..5367890044 100644
--- a/src/Core/Core.csproj
+++ b/src/Core/Core.csproj
@@ -27,18 +27,20 @@
     <PackageReference Include="Fido2.AspNet" Version="1.1.0" />
     <PackageReference Include="Handlebars.Net" Version="1.10.1" />
     <PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
+    <PackageReference Include="linq2db.EntityFrameworkCore" Version="5.2.1" />
     <PackageReference Include="MailKit" Version="2.8.0" />
-    <PackageReference Include="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="3.1.6" />
-    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.6" />
+    <PackageReference Include="Microsoft.AspNetCore.DataProtection.AzureStorage" Version="3.1.16" />
+    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="5.0.2" />
     <PackageReference Include="Microsoft.Azure.Cosmos.Table" Version="1.0.7" />
     <PackageReference Include="Microsoft.Azure.NotificationHubs" Version="3.3.0" />
     <PackageReference Include="Microsoft.Azure.ServiceBus" Version="4.1.3" />
     <PackageReference Include="Microsoft.Azure.Storage.Blob" Version="11.1.7" />
-    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="3.1.6" />
-    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="3.1.6" />
-    <PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="3.1.6" />
-    <PackageReference Include="Npgsql" Version="4.1.4" />
-    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.4" />
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="5.0.5" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="5.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="5.0.0" />
+    <PackageReference Include="Microsoft.Extensions.Identity.Stores" Version="5.0.2" />
+    <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2" />
+    <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.0" />
     <PackageReference Include="Quartz" Version="3.1.0" />
     <PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
     <PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
diff --git a/src/Core/Enums/CipherStateAction.cs b/src/Core/Enums/CipherStateAction.cs
new file mode 100644
index 0000000000..1d2c1dcf6d
--- /dev/null
+++ b/src/Core/Enums/CipherStateAction.cs
@@ -0,0 +1,9 @@
+namespace Bit.Core.Enums
+{
+      public enum CipherStateAction 
+      {
+         Restore,
+         SoftDelete,
+         HardDelete,
+      }
+}
diff --git a/src/Core/Enums/SupportedDatabaseProviders.cs b/src/Core/Enums/SupportedDatabaseProviders.cs
new file mode 100644
index 0000000000..301297d4b8
--- /dev/null
+++ b/src/Core/Enums/SupportedDatabaseProviders.cs
@@ -0,0 +1,10 @@
+namespace Bit.Core.Enums
+{
+    public enum SupportedDatabaseProviders 
+    {
+        SqlServer,
+        MySql,
+        Postgres,
+    }
+}
+
diff --git a/src/Core/Models/Api/Response/ProfileOrganizationResponseModel.cs b/src/Core/Models/Api/Response/ProfileOrganizationResponseModel.cs
index e7b563b046..b3728e812a 100644
--- a/src/Core/Models/Api/Response/ProfileOrganizationResponseModel.cs
+++ b/src/Core/Models/Api/Response/ProfileOrganizationResponseModel.cs
@@ -52,8 +52,8 @@ namespace Bit.Core.Models.Api
         public bool UseBusinessPortal => UsePolicies || UseSso; // TODO add events if needed
         public bool UsersGetPremium { get; set; }
         public bool SelfHost { get; set; }
-        public int Seats { get; set; }
-        public int MaxCollections { get; set; }
+        public int? Seats { get; set; }
+        public short? MaxCollections { get; set; }
         public short? MaxStorageGb { get; set; }
         public string Key { get; set; }
         public OrganizationUserStatusType Status { get; set; }
diff --git a/src/Core/Models/Data/GroupWithCollections.cs b/src/Core/Models/Data/GroupWithCollections.cs
new file mode 100644
index 0000000000..a3cbe786fa
--- /dev/null
+++ b/src/Core/Models/Data/GroupWithCollections.cs
@@ -0,0 +1,10 @@
+using System.Data;
+using Bit.Core.Models.Table;
+
+namespace Bit.Core.Models.Data
+{
+    public class GroupWithCollections : Group
+    {
+        public DataTable Collections { get; set; }
+    }
+}
diff --git a/src/Core/Models/Data/OrganizationUserOrganizationDetails.cs b/src/Core/Models/Data/OrganizationUserOrganizationDetails.cs
index 4e6748ce11..dc5c13f2e3 100644
--- a/src/Core/Models/Data/OrganizationUserOrganizationDetails.cs
+++ b/src/Core/Models/Data/OrganizationUserOrganizationDetails.cs
@@ -19,8 +19,8 @@ namespace Bit.Core.Models.Data
         public bool UseBusinessPortal => UsePolicies || UseSso;
         public bool SelfHost { get; set; }
         public bool UsersGetPremium { get; set; }
-        public int Seats { get; set; }
-        public int MaxCollections { get; set; }
+        public int? Seats { get; set; }
+        public short? MaxCollections { get; set; }
         public short? MaxStorageGb { get; set; }
         public string Key { get; set; }
         public Enums.OrganizationUserStatusType Status { get; set; }
diff --git a/src/Core/Models/Data/OrganizationUserWithCollections.cs b/src/Core/Models/Data/OrganizationUserWithCollections.cs
new file mode 100644
index 0000000000..f1b7d11f64
--- /dev/null
+++ b/src/Core/Models/Data/OrganizationUserWithCollections.cs
@@ -0,0 +1,10 @@
+using System.Data;
+using Bit.Core.Models.Table;
+
+namespace Bit.Core.Models.Data
+{
+    public class OrganizationUserWithCollections : OrganizationUser
+    {
+        public DataTable Collections { get; set; }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Cipher.cs b/src/Core/Models/EntityFramework/Cipher.cs
index 6edfe8773b..59b21cc14c 100644
--- a/src/Core/Models/EntityFramework/Cipher.cs
+++ b/src/Core/Models/EntityFramework/Cipher.cs
@@ -1,57 +1,14 @@
-using System.Text.Json;
+using System.Collections.Generic;
+using System.Text.Json;
 using AutoMapper;
 
 namespace Bit.Core.Models.EntityFramework
 {
     public class Cipher : Table.Cipher
     {
-        private JsonDocument _dataJson;
-        private JsonDocument _attachmentsJson;
-        private JsonDocument _favoritesJson;
-        private JsonDocument _foldersJson;
-
-        public User User { get; set; }
-        public Organization Organization { get; set; }
-        [IgnoreMap]
-        public JsonDocument DataJson
-        {
-            get => _dataJson;
-            set
-            {
-                Data = value?.ToString();
-                _dataJson = value;
-            }
-        }
-        [IgnoreMap]
-        public JsonDocument AttachmentsJson
-        {
-            get => _attachmentsJson;
-            set
-            {
-                Attachments = value?.ToString();
-                _attachmentsJson = value;
-            }
-        }
-        [IgnoreMap]
-        public JsonDocument FavoritesJson
-        {
-            get => _favoritesJson;
-            set
-            {
-                Favorites = value?.ToString();
-                _favoritesJson = value;
-            }
-        }
-        [IgnoreMap]
-        public JsonDocument FoldersJson
-        {
-            get => _foldersJson;
-            set
-            {
-                Folders = value?.ToString();
-                _foldersJson = value;
-            }
-        }
+        public virtual User User { get; set; }
+        public virtual Organization Organization { get; set; }
+        public virtual ICollection<CollectionCipher> CollectionCiphers { get; set; }
     }
 
     public class CipherMapperProfile : Profile
diff --git a/src/Core/Models/EntityFramework/Collection.cs b/src/Core/Models/EntityFramework/Collection.cs
new file mode 100644
index 0000000000..697f724d96
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Collection.cs
@@ -0,0 +1,22 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Collection : Table.Collection
+    {
+        public virtual Organization Organization { get; set; }
+        public virtual ICollection<CollectionUser> CollectionUsers { get; set; }
+        public virtual ICollection<CollectionCipher> CollectionCiphers { get; set; }
+        public virtual ICollection<CollectionGroup> CollectionGroups { get; set; }
+    }
+
+    public class CollectionMapperProfile : Profile
+    {
+        public CollectionMapperProfile()
+        {
+            CreateMap<Table.Collection, Collection>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/CollectionCipher.cs b/src/Core/Models/EntityFramework/CollectionCipher.cs
new file mode 100644
index 0000000000..00650b92d4
--- /dev/null
+++ b/src/Core/Models/EntityFramework/CollectionCipher.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class CollectionCipher : Table.CollectionCipher
+    {
+        public virtual Cipher Cipher { get; set; }
+        public virtual Collection Collection { get; set; }
+    }
+
+    public class CollectionCipherMapperProfile : Profile
+    {
+        public CollectionCipherMapperProfile()
+        {
+            CreateMap<Table.CollectionCipher, CollectionCipher>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/CollectionGroup.cs b/src/Core/Models/EntityFramework/CollectionGroup.cs
new file mode 100644
index 0000000000..afd714fdff
--- /dev/null
+++ b/src/Core/Models/EntityFramework/CollectionGroup.cs
@@ -0,0 +1,18 @@
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class CollectionGroup : Table.CollectionGroup
+    {
+        public virtual Collection Collection { get; set; }
+        public virtual Group Group { get; set; }
+    }
+
+    public class CollectionGroupMapperProfile : Profile
+    {
+        public CollectionGroupMapperProfile()
+        {
+            CreateMap<Table.CollectionGroup, CollectionGroup>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/CollectionUser.cs b/src/Core/Models/EntityFramework/CollectionUser.cs
new file mode 100644
index 0000000000..ec5a7e62ec
--- /dev/null
+++ b/src/Core/Models/EntityFramework/CollectionUser.cs
@@ -0,0 +1,18 @@
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class CollectionUser : Table.CollectionUser
+    {
+        public virtual Collection Collection { get; set; }
+        public virtual OrganizationUser OrganizationUser { get; set; }
+    }
+
+    public class CollectionUserMapperProfile : Profile
+    {
+        public CollectionUserMapperProfile()
+        {
+            CreateMap<Table.CollectionUser, CollectionUser>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Device.cs b/src/Core/Models/EntityFramework/Device.cs
new file mode 100644
index 0000000000..a70e97cc32
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Device.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Device : Table.Device
+    {
+        public virtual User User { get; set; }
+    }
+
+    public class DeviceMapperProfile : Profile
+    {
+        public DeviceMapperProfile()
+        {
+            CreateMap<Table.Device, Device>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/EmergencyAccess.cs b/src/Core/Models/EntityFramework/EmergencyAccess.cs
new file mode 100644
index 0000000000..950e386b75
--- /dev/null
+++ b/src/Core/Models/EntityFramework/EmergencyAccess.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class EmergencyAccess : Table.EmergencyAccess
+    {
+        public virtual User Grantee { get; set; }
+        public virtual User Grantor { get; set; }
+    }
+
+    public class EmergencyAccessMapperProfile : Profile
+    {
+        public EmergencyAccessMapperProfile()
+        {
+            CreateMap<Table.EmergencyAccess, EmergencyAccess>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Event.cs b/src/Core/Models/EntityFramework/Event.cs
new file mode 100644
index 0000000000..3e9faa2bc7
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Event.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Event : Table.Event
+    {
+    }
+
+    public class EventMapperProfile : Profile
+    {
+        public EventMapperProfile()
+        {
+            CreateMap<Table.Event, Event>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Folder.cs b/src/Core/Models/EntityFramework/Folder.cs
new file mode 100644
index 0000000000..6e5bdaf0f9
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Folder.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Folder : Table.Folder
+    {
+        public virtual User User { get; set; }
+    }
+
+    public class FolderMapperProfile : Profile
+    {
+        public FolderMapperProfile()
+        {
+            CreateMap<Table.Folder, Folder>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Grant.cs b/src/Core/Models/EntityFramework/Grant.cs
new file mode 100644
index 0000000000..e110233d9e
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Grant.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Grant : Table.Grant
+    {
+    }
+
+    public class GrantMapperProfile : Profile
+    {
+        public GrantMapperProfile()
+        {
+            CreateMap<Table.Grant, Grant>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Group.cs b/src/Core/Models/EntityFramework/Group.cs
new file mode 100644
index 0000000000..122ded667b
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Group.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Group : Table.Group
+    {
+        public virtual Organization Organization { get; set; }
+        public virtual ICollection<GroupUser> GroupUsers { get; set; }
+    }
+
+    public class GroupMapperProfile : Profile
+    {
+        public GroupMapperProfile()
+        {
+            CreateMap<Table.Group, Group>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/GroupUser.cs b/src/Core/Models/EntityFramework/GroupUser.cs
new file mode 100644
index 0000000000..55f18d8ad2
--- /dev/null
+++ b/src/Core/Models/EntityFramework/GroupUser.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class GroupUser : Table.GroupUser
+    {
+        public virtual Group Group { get; set; }
+        public virtual OrganizationUser OrganizationUser { get; set; }
+    }
+
+    public class GroupUserMapperProfile : Profile
+    {
+        public GroupUserMapperProfile()
+        {
+            CreateMap<Table.GroupUser, GroupUser>().ReverseMap();
+        }
+    }
+}
+
diff --git a/src/Core/Models/EntityFramework/Installation.cs b/src/Core/Models/EntityFramework/Installation.cs
new file mode 100644
index 0000000000..6b65fdd291
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Installation.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Installation : Table.Installation
+    {
+    }
+
+    public class InstallationMapperProfile : Profile
+    {
+        public InstallationMapperProfile()
+        {
+            CreateMap<Table.Installation, Installation>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Organization.cs b/src/Core/Models/EntityFramework/Organization.cs
index 2ee5c4c190..ff3d29b9a4 100644
--- a/src/Core/Models/EntityFramework/Organization.cs
+++ b/src/Core/Models/EntityFramework/Organization.cs
@@ -1,25 +1,17 @@
 using System.Collections.Generic;
-using System.Text.Json;
 using AutoMapper;
 
 namespace Bit.Core.Models.EntityFramework
 {
     public class Organization : Table.Organization
     {
-        private JsonDocument _twoFactorProvidersJson;
-
-        public ICollection<Cipher> Ciphers { get; set; }
-        
-        [IgnoreMap]
-        public JsonDocument TwoFactorProvidersJson
-        {
-            get => _twoFactorProvidersJson;
-            set
-            {
-                TwoFactorProviders = value?.ToString();
-                _twoFactorProvidersJson = value;
-            }
-        }
+        public virtual ICollection<Cipher> Ciphers { get; set; }
+        public virtual ICollection<OrganizationUser> OrganizationUsers { get; set; }
+        public virtual ICollection<Group> Groups { get; set; }
+        public virtual ICollection<Policy> Policies { get; set; }
+        public virtual ICollection<SsoConfig> SsoConfigs { get; set; }
+        public virtual ICollection<SsoUser> SsoUsers { get; set; }
+        public virtual ICollection<Transaction> Transactions { get; set; }
     }
 
     public class OrganizationMapperProfile : Profile
diff --git a/src/Core/Models/EntityFramework/OrganizationUser.cs b/src/Core/Models/EntityFramework/OrganizationUser.cs
new file mode 100644
index 0000000000..de75f24d6e
--- /dev/null
+++ b/src/Core/Models/EntityFramework/OrganizationUser.cs
@@ -0,0 +1,21 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class OrganizationUser : Table.OrganizationUser
+    {
+        public virtual Organization Organization { get; set; }
+        public virtual User User { get; set; }
+        public virtual ICollection<CollectionUser> CollectionUsers { get; set; }
+    }
+
+    public class OrganizationUserMapperProfile : Profile
+    {
+        public OrganizationUserMapperProfile()
+        {
+            CreateMap<Table.OrganizationUser, OrganizationUser>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Policy.cs b/src/Core/Models/EntityFramework/Policy.cs
new file mode 100644
index 0000000000..3646e58ad9
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Policy.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Policy : Table.Policy
+    {
+        public virtual Organization Organization { get; set; }
+    }
+
+    public class PolicyMapperProfile : Profile
+    {
+        public PolicyMapperProfile()
+        {
+            CreateMap<Table.Policy, Policy>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Provider/Provider.cs b/src/Core/Models/EntityFramework/Provider/Provider.cs
new file mode 100644
index 0000000000..fc595b4498
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Provider/Provider.cs
@@ -0,0 +1,16 @@
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework.Provider
+{
+    public class Provider : Table.Provider.Provider
+    {
+    }
+
+    public class ProviderMapperProfile : Profile
+    {
+        public ProviderMapperProfile()
+        {
+            CreateMap<Table.Provider.Provider, Provider>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Provider/ProviderOrganization.cs b/src/Core/Models/EntityFramework/Provider/ProviderOrganization.cs
new file mode 100644
index 0000000000..5f1077d81c
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Provider/ProviderOrganization.cs
@@ -0,0 +1,18 @@
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework.Provider
+{
+    public class ProviderOrganization : Table.Provider.ProviderOrganization
+    {
+        public virtual Provider Provider { get; set; }
+        public virtual Organization Organization { get; set; }
+    }
+
+    public class ProviderOrganizationMapperProfile : Profile
+    {
+        public ProviderOrganizationMapperProfile()
+        {
+            CreateMap<Table.Provider.ProviderOrganization, ProviderOrganization>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Provider/ProviderOrganizationProviderUser.cs b/src/Core/Models/EntityFramework/Provider/ProviderOrganizationProviderUser.cs
new file mode 100644
index 0000000000..70db4fb7ed
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Provider/ProviderOrganizationProviderUser.cs
@@ -0,0 +1,18 @@
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework.Provider
+{
+    public class ProviderOrganizationProviderUser : Table.Provider.ProviderOrganizationProviderUser
+    {
+        public virtual ProviderOrganization ProviderOrganization { get; set; }
+        public virtual ProviderUser ProviderUser { get; set; }
+    }
+
+    public class ProviderOrganizationProviderUserMapperProfile : Profile
+    {
+        public ProviderOrganizationProviderUserMapperProfile()
+        {
+            CreateMap<Table.Provider.ProviderOrganizationProviderUser, ProviderOrganizationProviderUser>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Provider/ProviderUser.cs b/src/Core/Models/EntityFramework/Provider/ProviderUser.cs
new file mode 100644
index 0000000000..14d22764f7
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Provider/ProviderUser.cs
@@ -0,0 +1,18 @@
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework.Provider
+{
+    public class ProviderUser : Table.Provider.ProviderUser
+    {
+        public virtual User User { get; set; }
+        public virtual Provider Provider { get; set; }
+    }
+
+    public class ProviderUserMapperProfile : Profile
+    {
+        public ProviderUserMapperProfile()
+        {
+            CreateMap<Table.Provider.ProviderUser, ProviderUser>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Role.cs b/src/Core/Models/EntityFramework/Role.cs
new file mode 100644
index 0000000000..706e6cbd19
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Role.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Role : Table.Role
+    {
+    }
+
+    public class RoleMapperProfile : Profile
+    {
+        public RoleMapperProfile()
+        {
+            CreateMap<Table.Role, Role>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Send.cs b/src/Core/Models/EntityFramework/Send.cs
new file mode 100644
index 0000000000..517e077496
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Send.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Send : Table.Send
+    {
+        public virtual Organization Organization { get; set; }
+        public virtual User User { get; set; }
+    }
+
+    public class SendMapperProfile : Profile
+    {
+        public SendMapperProfile()
+        {
+            CreateMap<Table.Send, Send>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/SsoConfig.cs b/src/Core/Models/EntityFramework/SsoConfig.cs
new file mode 100644
index 0000000000..74b83f6618
--- /dev/null
+++ b/src/Core/Models/EntityFramework/SsoConfig.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class SsoConfig : Table.SsoConfig
+    {
+        public virtual Organization Organization { get; set; }
+    }
+
+    public class SsoConfigMapperProfile : Profile
+    {
+        public SsoConfigMapperProfile()
+        {
+            CreateMap<Table.SsoConfig, SsoConfig>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/SsoUser.cs b/src/Core/Models/EntityFramework/SsoUser.cs
new file mode 100644
index 0000000000..616e4d8649
--- /dev/null
+++ b/src/Core/Models/EntityFramework/SsoUser.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class SsoUser : Table.SsoUser
+    {
+        public virtual Organization Organization { get; set; }
+        public virtual User User { get; set; }
+    }
+
+    public class SsoUserMapperProfile : Profile
+    {
+        public SsoUserMapperProfile()
+        {
+            CreateMap<Table.SsoUser, SsoUser>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/TaxRate.cs b/src/Core/Models/EntityFramework/TaxRate.cs
new file mode 100644
index 0000000000..1fe2b499e9
--- /dev/null
+++ b/src/Core/Models/EntityFramework/TaxRate.cs
@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class TaxRate : Table.TaxRate
+    {
+    }
+
+    public class TaxRateMapperProfile : Profile
+    {
+        public TaxRateMapperProfile()
+        {
+            CreateMap<Table.TaxRate, TaxRate>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/Transaction.cs b/src/Core/Models/EntityFramework/Transaction.cs
new file mode 100644
index 0000000000..bef6271dff
--- /dev/null
+++ b/src/Core/Models/EntityFramework/Transaction.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class Transaction : Table.Transaction
+    {
+        public virtual Organization Organization { get; set; }
+        public virtual User User { get; set; }
+    }
+
+    public class TransactionMapperProfile : Profile
+    {
+        public TransactionMapperProfile()
+        {
+            CreateMap<Table.Transaction, Transaction>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/U2f.cs b/src/Core/Models/EntityFramework/U2f.cs
new file mode 100644
index 0000000000..206baff10a
--- /dev/null
+++ b/src/Core/Models/EntityFramework/U2f.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Text.Json;
+using AutoMapper;
+
+namespace Bit.Core.Models.EntityFramework
+{
+    public class U2f : Table.U2f
+    {
+        public virtual User User { get; set; }
+    }
+
+    public class U2fMapperProfile : Profile
+    {
+        public U2fMapperProfile()
+        {
+            CreateMap<Table.U2f, U2f>().ReverseMap();
+        }
+    }
+}
diff --git a/src/Core/Models/EntityFramework/User.cs b/src/Core/Models/EntityFramework/User.cs
index 5f1aff6daa..1836bec44f 100644
--- a/src/Core/Models/EntityFramework/User.cs
+++ b/src/Core/Models/EntityFramework/User.cs
@@ -6,20 +6,14 @@ namespace Bit.Core.Models.EntityFramework
 {
     public class User : Table.User
     {
-        private JsonDocument _twoFactorProvidersJson;
-
-        public ICollection<Cipher> Ciphers { get; set; }
-
-        [IgnoreMap]
-        public JsonDocument TwoFactorProvidersJson
-        {
-            get => _twoFactorProvidersJson;
-            set
-            {
-                TwoFactorProviders = value?.ToString();
-                _twoFactorProvidersJson = value;
-            }
-        }
+        public virtual ICollection<Cipher> Ciphers { get; set; }
+        public virtual ICollection<Folder> Folders { get; set; }
+        public virtual ICollection<CollectionUser> CollectionUsers { get; set; }
+        public virtual ICollection<GroupUser> GroupUsers { get; set; }
+        public virtual ICollection<OrganizationUser> OrganizationUsers { get; set; }
+        public virtual ICollection<SsoUser> SsoUsers { get; set; }
+        public virtual ICollection<Transaction> Transactions { get; set; }
+        public virtual ICollection<U2f> U2fs { get; set; }
     }
 
     public class UserMapperProfile : Profile
diff --git a/src/Core/Models/Table/Collection.cs b/src/Core/Models/Table/Collection.cs
index 369592789e..85cb287386 100644
--- a/src/Core/Models/Table/Collection.cs
+++ b/src/Core/Models/Table/Collection.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 using Bit.Core.Utilities;
 
 namespace Bit.Core.Models.Table
@@ -8,6 +9,7 @@ namespace Bit.Core.Models.Table
         public Guid Id { get; set; }
         public Guid OrganizationId { get; set; }
         public string Name { get; set; }
+        [MaxLength(300)]
         public string ExternalId { get; set; }
         public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
         public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
diff --git a/src/Core/Models/Table/CollectionGroup.cs b/src/Core/Models/Table/CollectionGroup.cs
new file mode 100644
index 0000000000..b510e05e08
--- /dev/null
+++ b/src/Core/Models/Table/CollectionGroup.cs
@@ -0,0 +1,13 @@
+using System;
+using Bit.Core.Utilities;
+
+namespace Bit.Core.Models.Table
+{
+    public class CollectionGroup
+    {
+        public Guid CollectionId { get; set; }
+        public Guid GroupId { get; set; }
+        public bool ReadOnly { get; set; }
+        public bool HidePasswords { get; set; }
+    }
+}
diff --git a/src/Core/Models/Table/CollectionUser.cs b/src/Core/Models/Table/CollectionUser.cs
new file mode 100644
index 0000000000..3bcf15d706
--- /dev/null
+++ b/src/Core/Models/Table/CollectionUser.cs
@@ -0,0 +1,13 @@
+using System;
+using Bit.Core.Utilities;
+
+namespace Bit.Core.Models.Table
+{
+    public class CollectionUser
+    {
+        public Guid CollectionId { get; set; }
+        public Guid OrganizationUserId { get; set; }
+        public bool ReadOnly { get; set; }
+        public bool HidePasswords { get; set; }
+    }
+}
diff --git a/src/Core/Models/Table/Device.cs b/src/Core/Models/Table/Device.cs
index 4fb20652df..b4e740e5be 100644
--- a/src/Core/Models/Table/Device.cs
+++ b/src/Core/Models/Table/Device.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 using Bit.Core.Utilities;
 
 namespace Bit.Core.Models.Table
@@ -7,9 +8,12 @@ namespace Bit.Core.Models.Table
     {
         public Guid Id { get; set; }
         public Guid UserId { get; set; }
+        [MaxLength(50)]
         public string Name { get; set; }
         public Enums.DeviceType Type { get; set; }
+        [MaxLength(50)]
         public string Identifier { get; set; }
+        [MaxLength(255)]
         public string PushToken { get; set; }
         public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
         public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
diff --git a/src/Core/Models/Table/EmergencyAccess.cs b/src/Core/Models/Table/EmergencyAccess.cs
index fe118ca76a..0e256cff37 100644
--- a/src/Core/Models/Table/EmergencyAccess.cs
+++ b/src/Core/Models/Table/EmergencyAccess.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 using Bit.Core.Enums;
 using Bit.Core.Utilities;
 
@@ -9,6 +10,7 @@ namespace Bit.Core.Models.Table
         public Guid Id { get; set; }
         public Guid GrantorId { get; set; }
         public Guid? GranteeId { get; set; }
+        [MaxLength(256)]
         public string Email { get; set; }
         public string KeyEncrypted { get; set; }
         public EmergencyAccessType Type { get; set; }
diff --git a/src/Core/Models/Table/Event.cs b/src/Core/Models/Table/Event.cs
index 6b00a7b81c..eb68289fb8 100644
--- a/src/Core/Models/Table/Event.cs
+++ b/src/Core/Models/Table/Event.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 using Bit.Core.Enums;
 using Bit.Core.Models.Data;
 using Bit.Core.Utilities;
@@ -36,6 +37,7 @@ namespace Bit.Core.Models.Table
         public Guid? GroupId { get; set; }
         public Guid? OrganizationUserId { get; set; }
         public DeviceType? DeviceType { get; set; }
+        [MaxLength(50)]
         public string IpAddress { get; set; }
         public Guid? ActingUserId { get; set; }
 
diff --git a/src/Core/Models/Table/Grant.cs b/src/Core/Models/Table/Grant.cs
index 785fa5d1a0..e8b052d114 100644
--- a/src/Core/Models/Table/Grant.cs
+++ b/src/Core/Models/Table/Grant.cs
@@ -1,14 +1,21 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 
 namespace Bit.Core.Models.Table
 {
     public class Grant
     {
+        [MaxLength(200)]
         public string Key { get; set; }
+        [MaxLength(50)]
         public string Type { get; set; }
+        [MaxLength(200)]
         public string SubjectId { get; set; }
+        [MaxLength(100)]
         public string SessionId { get; set; }
+        [MaxLength(200)]
         public string ClientId { get; set; }
+        [MaxLength(200)]
         public string Description { get; set; }
         public DateTime CreationDate { get; set; }
         public DateTime? ExpirationDate { get; set; }
diff --git a/src/Core/Models/Table/Group.cs b/src/Core/Models/Table/Group.cs
index bdb72b4d5d..d732746886 100644
--- a/src/Core/Models/Table/Group.cs
+++ b/src/Core/Models/Table/Group.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 using Bit.Core.Utilities;
 
 namespace Bit.Core.Models.Table
@@ -7,8 +8,10 @@ namespace Bit.Core.Models.Table
     {
         public Guid Id { get; set; }
         public Guid OrganizationId { get; set; }
+        [MaxLength(100)]
         public string Name { get; set; }
         public bool AccessAll { get; set; }
+        [MaxLength(300)]
         public string ExternalId { get; set; }
         public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
         public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
diff --git a/src/Core/Models/Table/Installation.cs b/src/Core/Models/Table/Installation.cs
index e7abc7d0d7..631fa5bf6d 100644
--- a/src/Core/Models/Table/Installation.cs
+++ b/src/Core/Models/Table/Installation.cs
@@ -1,12 +1,15 @@
 using Bit.Core.Utilities;
 using System;
+using System.ComponentModel.DataAnnotations;
 
 namespace Bit.Core.Models.Table
 {
     public class Installation : ITableObject<Guid>
     {
         public Guid Id { get; set; }
+        [MaxLength(256)]
         public string Email { get; set; }
+        [MaxLength(150)]
         public string Key { get; set; }
         public bool Enabled { get; set; }
         public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
diff --git a/src/Core/Models/Table/Organization.cs b/src/Core/Models/Table/Organization.cs
index 6af3e46656..4a23bcd163 100644
--- a/src/Core/Models/Table/Organization.cs
+++ b/src/Core/Models/Table/Organization.cs
@@ -4,6 +4,7 @@ using Bit.Core.Enums;
 using System.Collections.Generic;
 using Newtonsoft.Json;
 using System.Linq;
+using System.ComponentModel.DataAnnotations;
 
 namespace Bit.Core.Models.Table
 {
@@ -12,15 +13,25 @@ namespace Bit.Core.Models.Table
         private Dictionary<TwoFactorProviderType, TwoFactorProvider> _twoFactorProviders;
 
         public Guid Id { get; set; }
+        [MaxLength(50)]
         public string Identifier { get; set; }
+        [MaxLength(50)]
         public string Name { get; set; }
+        [MaxLength(50)]
         public string BusinessName { get; set; }
+        [MaxLength(50)]
         public string BusinessAddress1 { get; set; }
+        [MaxLength(50)]
         public string BusinessAddress2 { get; set; }
+        [MaxLength(50)]
         public string BusinessAddress3 { get; set; }
+        [MaxLength(2)]
         public string BusinessCountry { get; set; }
+        [MaxLength(30)]
         public string BusinessTaxNumber { get; set; }
+        [MaxLength(256)]
         public string BillingEmail { get; set; }
+        [MaxLength(50)]
         public string Plan { get; set; }
         public PlanType PlanType { get; set; }
         public int? Seats { get; set; }
@@ -39,11 +50,15 @@ namespace Bit.Core.Models.Table
         public long? Storage { get; set; }
         public short? MaxStorageGb { get; set; }
         public GatewayType? Gateway { get; set; }
+        [MaxLength(50)]
         public string GatewayCustomerId { get; set; }
+        [MaxLength(50)]
         public string GatewaySubscriptionId { get; set; }
         public string ReferenceData { get; set; }
         public bool Enabled { get; set; } = true;
+        [MaxLength(100)]
         public string LicenseKey { get; set; }
+        [MaxLength(30)]
         public string ApiKey { get; set; }
         public string PublicKey { get; set; }
         public string PrivateKey { get; set; }
diff --git a/src/Core/Models/Table/OrganizationUser.cs b/src/Core/Models/Table/OrganizationUser.cs
index 13ab71ab3f..5a275ec753 100644
--- a/src/Core/Models/Table/OrganizationUser.cs
+++ b/src/Core/Models/Table/OrganizationUser.cs
@@ -1,6 +1,7 @@
 using System;
 using Bit.Core.Utilities;
 using Bit.Core.Enums;
+using System.ComponentModel.DataAnnotations;
 
 namespace Bit.Core.Models.Table
 {
@@ -9,12 +10,14 @@ namespace Bit.Core.Models.Table
         public Guid Id { get; set; }
         public Guid OrganizationId { get; set; }
         public Guid? UserId { get; set; }
+        [MaxLength(256)]
         public string Email { get; set; }
         public string Key { get; set; }
         public string ResetPasswordKey { get; set; }
         public OrganizationUserStatusType Status { get; set; }
         public OrganizationUserType Type { get; set; }
         public bool AccessAll { get; set; }
+        [MaxLength(300)]
         public string ExternalId { get; set; }
         public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
         public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow;
diff --git a/src/Core/Models/Table/Send.cs b/src/Core/Models/Table/Send.cs
index 2660e9e8a6..36607d965f 100644
--- a/src/Core/Models/Table/Send.cs
+++ b/src/Core/Models/Table/Send.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 using Bit.Core.Enums;
 using Bit.Core.Utilities;
 
@@ -12,6 +13,7 @@ namespace Bit.Core.Models.Table
         public SendType Type { get; set; }
         public string Data { get; set; }
         public string Key { get; set; }
+        [MaxLength(300)]
         public string Password { get; set; }
         public int? MaxAccessCount { get; set; }
         public int AccessCount { get; set; }
diff --git a/src/Core/Models/Table/SsoConfig.cs b/src/Core/Models/Table/SsoConfig.cs
index 5e5d47f4a2..6a1b232126 100644
--- a/src/Core/Models/Table/SsoConfig.cs
+++ b/src/Core/Models/Table/SsoConfig.cs
@@ -13,7 +13,8 @@ namespace Bit.Core.Models.Table
         
         public void SetNewId()
         {
-            // nothing - int will be auto-populated
+            // int will be auto-populated
+            Id = 0;
         }
     }
 }
diff --git a/src/Core/Models/Table/SsoUser.cs b/src/Core/Models/Table/SsoUser.cs
index da4e38528e..6c7cd6257f 100644
--- a/src/Core/Models/Table/SsoUser.cs
+++ b/src/Core/Models/Table/SsoUser.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 
 namespace Bit.Core.Models.Table
 {
@@ -7,12 +8,14 @@ namespace Bit.Core.Models.Table
         public long Id { get; set; }
         public Guid UserId { get; set; }
         public Guid? OrganizationId { get; set; }
+        [MaxLength(50)]
         public string ExternalId { get; set; }
         public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
 
         public void SetNewId()
         {
-            // nothing - int will be auto-populated
+            // int will be auto-populated
+            Id = 0;
         }
     }
 }
diff --git a/src/Core/Models/Table/TaxRate.cs b/src/Core/Models/Table/TaxRate.cs
index 195465efda..a9a7585774 100644
--- a/src/Core/Models/Table/TaxRate.cs
+++ b/src/Core/Models/Table/TaxRate.cs
@@ -1,10 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+
 namespace Bit.Core.Models.Table
 {
    public class TaxRate: ITableObject<string>
    {
+      [MaxLength(40)]
       public string Id { get; set; }
+      [MaxLength(50)]
       public string Country { get; set; }
+      [MaxLength(2)]
       public string State { get; set; }
+      [MaxLength(10)]
       public string PostalCode { get; set; }
       public decimal Rate { get; set; }
       public bool Active { get; set; } 
diff --git a/src/Core/Models/Table/Transaction.cs b/src/Core/Models/Table/Transaction.cs
index 637f40f403..0f5e80e457 100644
--- a/src/Core/Models/Table/Transaction.cs
+++ b/src/Core/Models/Table/Transaction.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 using Bit.Core.Enums;
 using Bit.Core.Utilities;
 
@@ -13,9 +14,11 @@ namespace Bit.Core.Models.Table
         public decimal Amount { get; set; }
         public bool? Refunded { get; set; }
         public decimal? RefundedAmount { get; set; }
+        [MaxLength(100)]
         public string Details { get; set; }
         public PaymentMethodType? PaymentMethodType { get; set; }
         public GatewayType? Gateway { get; set; }
+        [MaxLength(50)]
         public string GatewayId { get; set; }
         public DateTime CreationDate { get; set; } = DateTime.UtcNow;
 
diff --git a/src/Core/Models/Table/U2f.cs b/src/Core/Models/Table/U2f.cs
index e8a97c7fe5..5d089dacaa 100644
--- a/src/Core/Models/Table/U2f.cs
+++ b/src/Core/Models/Table/U2f.cs
@@ -1,4 +1,5 @@
 using System;
+using System.ComponentModel.DataAnnotations;
 
 namespace Bit.Core.Models.Table
 {
@@ -6,15 +7,20 @@ namespace Bit.Core.Models.Table
     {
         public int Id { get; set; }
         public Guid UserId { get; set; }
+        [MaxLength(200)]
         public string KeyHandle { get; set; }
+        [MaxLength(200)]
         public string Challenge { get; set; }
+        [MaxLength(50)]
         public string AppId { get; set; }
+        [MaxLength(20)]
         public string Version { get; set; }
         public DateTime CreationDate { get; internal set; } = DateTime.UtcNow;
 
         public void SetNewId()
         {
-            // do nothing since it is an identity
+            // int will be auto-populated
+            Id = 0;
         }
     }
 }
diff --git a/src/Core/Models/Table/User.cs b/src/Core/Models/Table/User.cs
index 20513e0967..12c3f50d28 100644
--- a/src/Core/Models/Table/User.cs
+++ b/src/Core/Models/Table/User.cs
@@ -4,6 +4,7 @@ using Bit.Core.Utilities;
 using System.Collections.Generic;
 using Newtonsoft.Json;
 using Microsoft.AspNetCore.Identity;
+using System.ComponentModel.DataAnnotations;
 
 namespace Bit.Core.Models.Table
 {
@@ -12,14 +13,23 @@ namespace Bit.Core.Models.Table
         private Dictionary<TwoFactorProviderType, TwoFactorProvider> _twoFactorProviders;
 
         public Guid Id { get; set; }
+        [MaxLength(50)]
         public string Name { get; set; }
+        [Required]
+        [MaxLength(256)]
         public string Email { get; set; }
         public bool EmailVerified { get; set; }
+        [MaxLength(300)]
         public string MasterPassword { get; set; }
+        [MaxLength(50)]
         public string MasterPasswordHint { get; set; }
+        [MaxLength(10)]
         public string Culture { get; set; } = "en-US";
+        [Required]
+        [MaxLength(50)]
         public string SecurityStamp { get; set; }
         public string TwoFactorProviders { get; set; }
+        [MaxLength(32)]
         public string TwoFactorRecoveryCode { get; set; }
         public string EquivalentDomains { get; set; }
         public string ExcludedGlobalEquivalentDomains { get; set; }
@@ -33,10 +43,15 @@ namespace Bit.Core.Models.Table
         public long? Storage { get; set; }
         public short? MaxStorageGb { get; set; }
         public GatewayType? Gateway { get; set; }
+        [MaxLength(50)]
         public string GatewayCustomerId { get; set; }
+        [MaxLength(50)]
         public string GatewaySubscriptionId { get; set; }
         public string ReferenceData { get; set; }
+        [MaxLength(100)]
         public string LicenseKey { get; set; }
+        [Required]
+        [MaxLength(30)]
         public string ApiKey { get; set; }
         public KdfType Kdf { get; set; } = KdfType.PBKDF2_SHA256;
         public int KdfIterations { get; set; } = 5000;
diff --git a/src/Core/Repositories/EntityFramework/BaseEntityFrameworkRepository.cs b/src/Core/Repositories/EntityFramework/BaseEntityFrameworkRepository.cs
index fd20430111..d1b20764de 100644
--- a/src/Core/Repositories/EntityFramework/BaseEntityFrameworkRepository.cs
+++ b/src/Core/Repositories/EntityFramework/BaseEntityFrameworkRepository.cs
@@ -1,10 +1,28 @@
 using AutoMapper;
+using Bit.Core.Models.Table;
+using Bit.Core.Repositories.EntityFramework.Queries;
+using EfModel = Bit.Core.Models.EntityFramework;
+using LinqToDB.Data;
+using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json;
+using System.Threading.Tasks;
+using System;
+using Bit.Core.Enums;
+using Bit.Core.Enums.Provider;
 
 namespace Bit.Core.Repositories.EntityFramework
 {
     public abstract class BaseEntityFrameworkRepository
     {
+        protected BulkCopyOptions DefaultBulkCopyOptions { get; set; } = new BulkCopyOptions
+        {
+            KeepIdentity = true,
+            BulkCopyType = BulkCopyType.MultipleRows,
+        };
+
         public BaseEntityFrameworkRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
         {
             ServiceScopeFactory = serviceScopeFactory;
@@ -18,5 +36,233 @@ namespace Bit.Core.Repositories.EntityFramework
         {
             return serviceScope.ServiceProvider.GetRequiredService<DatabaseContext>();
         }
+
+        public void ClearChangeTracking()
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                dbContext.ChangeTracker.Clear();
+            }
+        }
+
+        public async Task<int> GetCountFromQuery<T>(IQuery<T> query)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                return await query.Run(GetDatabaseContext(scope)).CountAsync();
+            }
+        }
+
+        protected async Task UserBumpAccountRevisionDateByCipherId(Cipher cipher)
+        {
+            var list = new List<Cipher> { cipher };
+            await UserBumpAccountRevisionDateByCipherId(list);
+        }
+
+        protected async Task UserBumpAccountRevisionDateByCipherId(IEnumerable<Cipher> ciphers)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                foreach (var cipher in ciphers)
+                {
+                    var dbContext = GetDatabaseContext(scope);
+                    var query = new UserBumpAccountRevisionDateByCipherIdQuery(cipher);
+                    var users = query.Run(dbContext);
+
+                    await users.ForEachAsync(e => 
+                    {
+                        dbContext.Attach(e);
+                        e.RevisionDate = DateTime.UtcNow;
+                    });
+                    await dbContext.SaveChangesAsync();
+                }
+            }
+        }
+
+        protected async Task UserBumpAccountRevisionDateByOrganizationId(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new UserBumpAccountRevisionDateByOrganizationIdQuery(organizationId);
+                var users = query.Run(dbContext);
+                await users.ForEachAsync(e => 
+                {
+                    dbContext.Attach(e);
+                    e.RevisionDate = DateTime.UtcNow;
+                });
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        protected async Task UserBumpAccountRevisionDate(Guid userId)
+        {
+            await UserBumpManyAccountRevisionDates(new[] { userId });
+        }
+
+        protected async Task UserBumpManyAccountRevisionDates(ICollection<Guid> userIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var users = dbContext.Users.Where(u => userIds.Contains(u.Id));
+                await users.ForEachAsync(u => 
+                {
+                    dbContext.Attach(u);
+                    u.RevisionDate = DateTime.UtcNow;
+                });
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        protected async Task OrganizationUpdateStorage(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var attachments = await dbContext.Ciphers
+                    .Where(e => e.UserId == null &&
+                        e.OrganizationId == organizationId &&
+                        !string.IsNullOrWhiteSpace(e.Attachments))
+                    .Select(e => e.Attachments)
+                    .ToListAsync();
+                var storage = attachments.Sum(e => JsonDocument.Parse(e)?.RootElement.EnumerateArray()
+                    .Sum(p => p.GetProperty("Size").GetInt64()) ?? 0);
+                var organization = new EfModel.Organization
+                {
+                    Id = organizationId,
+                    RevisionDate = DateTime.UtcNow,
+                    Storage = storage,
+                };
+                dbContext.Organizations.Attach(organization);
+                var entry = dbContext.Entry(organization);
+                entry.Property(e => e.RevisionDate).IsModified = true;
+                entry.Property(e => e.Storage).IsModified = true;
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        protected async Task UserUpdateStorage(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var attachments = await dbContext.Ciphers
+                    .Where(e => e.UserId.HasValue &&
+                        e.UserId.Value == userId &&
+                        e.OrganizationId == null &&
+                        !string.IsNullOrWhiteSpace(e.Attachments))
+                    .Select(e => e.Attachments)
+                    .ToListAsync();
+                var storage = attachments.Sum(e => JsonDocument.Parse(e)?.RootElement.EnumerateArray()
+                    .Sum(p => p.GetProperty("Size").GetInt64()) ?? 0);
+                var user = new EfModel.User
+                {
+                    Id = userId,
+                    RevisionDate = DateTime.UtcNow,
+                    Storage = storage,
+                };
+                dbContext.Users.Attach(user);
+                var entry = dbContext.Entry(user);
+                entry.Property(e => e.RevisionDate).IsModified = true;
+                entry.Property(e => e.Storage).IsModified = true;
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        protected async Task UserUpdateKeys(User user)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entity = await dbContext.Users.FindAsync(user.Id);
+                if (entity == null)
+                {
+                    return;
+                }
+                entity.SecurityStamp = user.SecurityStamp;
+                entity.Key = user.Key;
+                entity.PrivateKey = user.PrivateKey;
+                entity.RevisionDate = DateTime.UtcNow;
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        protected async Task UserBumpAccountRevisionDateByCollectionId(Guid collectionId, Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from u in dbContext.Users
+                    join ou in dbContext.OrganizationUsers
+                        on u.Id equals ou.UserId
+                    join cu in dbContext.CollectionUsers
+                        on ou.Id equals cu.OrganizationUserId into cu_g
+                    from cu in cu_g.DefaultIfEmpty()
+                    where !ou.AccessAll && cu.CollectionId.Equals(collectionId)
+                    join gu in dbContext.GroupUsers
+                        on ou.Id equals gu.OrganizationUserId into gu_g
+                    from gu in gu_g.DefaultIfEmpty()
+                    where cu.CollectionId == default(Guid) && !ou.AccessAll
+                    join g in dbContext.Groups
+                        on gu.GroupId equals g.Id into g_g
+                    from g in g_g.DefaultIfEmpty()
+                    join cg in dbContext.CollectionGroups
+                        on gu.GroupId equals cg.GroupId into cg_g
+                    from cg in cg_g.DefaultIfEmpty()
+                    where !g.AccessAll && cg.CollectionId == collectionId &&
+                        (ou.OrganizationId == organizationId && ou.Status == OrganizationUserStatusType.Confirmed &&
+                        (cu.CollectionId != default(Guid) || cg.CollectionId != default(Guid) || ou.AccessAll || g.AccessAll))
+                    select new { u, ou, cu, gu, g, cg };
+                var users = query.Select(x => x.u);
+                await users.ForEachAsync(u => 
+                {
+                    dbContext.Attach(u);
+                    u.RevisionDate = DateTime.UtcNow; 
+                });
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        protected async Task UserBumpAccountRevisionDateByOrganizationUserId(Guid organizationUserId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from u in dbContext.Users
+                    join ou in dbContext.OrganizationUsers
+                        on u.Id equals ou.UserId
+                    where ou.Id.Equals(organizationUserId) && ou.Status.Equals(OrganizationUserStatusType.Confirmed)
+                    select new { u, ou };
+                var users = query.Select(x => x.u);
+                await users.ForEachAsync(u => 
+                {
+                    dbContext.Attach(u);
+                    u.AccountRevisionDate = DateTime.UtcNow;
+                });
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        protected async Task UserBumpAccountRevisionDateByProviderUserIds(ICollection<Guid> providerUserIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from pu in dbContext.ProviderUsers
+                    join u in dbContext.Users
+                        on pu.UserId equals u.Id
+                    where pu.Status.Equals(ProviderUserStatusType.Confirmed) &&
+                        providerUserIds.Contains(pu.Id)
+                    select new { pu, u };
+                var users = query.Select(x => x.u);
+                await users.ForEachAsync(u => {
+                    dbContext.Attach(u);
+                    u.AccountRevisionDate = DateTime.UtcNow;
+                });
+                await dbContext.SaveChangesAsync();
+            }
+        }
     }
 }
diff --git a/src/Core/Repositories/EntityFramework/CipherRepository.cs b/src/Core/Repositories/EntityFramework/CipherRepository.cs
new file mode 100644
index 0000000000..f365d0da02
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/CipherRepository.cs
@@ -0,0 +1,642 @@
+using AutoMapper;
+using Bit.Core.Models.Data;
+using Bit.Core.Models.Table;
+using Bit.Core.Repositories.EntityFramework.Queries;
+using Bit.Core.Utilities;
+using Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using LinqToDB.Data;
+using LinqToDB.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System;
+using TableModel = Bit.Core.Models.Table;
+using Bit.Core.Enums;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class CipherRepository : Repository<TableModel.Cipher, EfModel.Cipher, Guid>, ICipherRepository
+    {
+        public CipherRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Ciphers)
+        { }
+
+        public override async Task<Cipher> CreateAsync(Cipher cipher)
+        {
+            cipher = await base.CreateAsync(cipher);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                if (cipher.OrganizationId.HasValue)
+                {
+                    await UserBumpAccountRevisionDateByCipherId(cipher);
+                }
+                else if (cipher.UserId.HasValue)
+                {
+                    await UserBumpAccountRevisionDate(cipher.UserId.Value);
+                }
+            }
+            return cipher;
+        }
+
+        public IQueryable<User> GetBumpedAccountsByCipherId(Cipher cipher)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new UserBumpAccountRevisionDateByCipherIdQuery(cipher);
+                return query.Run(dbContext);
+            }
+        }
+
+        public async Task CreateAsync(Cipher cipher, IEnumerable<Guid> collectionIds)
+        {
+            cipher = await base.CreateAsync(cipher);
+            await UpdateCollections(cipher, collectionIds);
+        }
+
+        private async Task UpdateCollections(Cipher cipher, IEnumerable<Guid> collectionIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var cipherEntity = await dbContext.Ciphers.FindAsync(cipher.Id);
+                var query = new CipherUpdateCollectionsQuery(cipherEntity, collectionIds).Run(dbContext);
+                await dbContext.AddRangeAsync(query);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task CreateAsync(CipherDetails cipher)
+        {
+            await CreateAsyncReturnCipher(cipher);
+        }
+
+        private async Task<CipherDetails> CreateAsyncReturnCipher(CipherDetails cipher)
+        {
+            cipher.SetNewId();
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var userIdKey = $"\"{cipher.UserId}\"";
+                cipher.UserId = cipher.OrganizationId.HasValue ? null : cipher.UserId;
+                cipher.Favorites = cipher.Favorite ? 
+                    $"{{{userIdKey}:true}}" : 
+                    null;
+                cipher.Folders = cipher.FolderId.HasValue ?
+                    $"{{{userIdKey}:\"{cipher.FolderId}\"}}" :
+                    null;
+                var entity = Mapper.Map<EfModel.Cipher>((TableModel.Cipher)cipher);
+                await dbContext.AddAsync(entity);
+                await dbContext.SaveChangesAsync();
+            }
+            await UserBumpAccountRevisionDateByCipherId(cipher);
+            return cipher;
+        }
+
+        public async Task CreateAsync(CipherDetails cipher, IEnumerable<Guid> collectionIds)
+        {
+            cipher = await CreateAsyncReturnCipher(cipher);
+            await UpdateCollections(cipher, collectionIds);
+        }
+
+        public async Task CreateAsync(IEnumerable<Cipher> ciphers, IEnumerable<Folder> folders)
+        {
+            if (!ciphers.Any())
+            {
+                return;
+            }
+
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var folderEntities = Mapper.Map<List<EfModel.Folder>>(folders);
+                await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, folderEntities);
+                var cipherEntities = Mapper.Map<List<EfModel.Cipher>>(ciphers);
+                await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, cipherEntities);
+                await UserBumpAccountRevisionDateByCipherId(ciphers);
+            }
+        }
+
+        public async Task CreateAsync(IEnumerable<Cipher> ciphers, IEnumerable<Collection> collections, IEnumerable<CollectionCipher> collectionCiphers)
+        {
+            if (!ciphers.Any()) 
+            {
+                return; 
+            }
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var cipherEntities = Mapper.Map<List<EfModel.Cipher>>(ciphers);
+                await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, cipherEntities);
+                if (collections.Any())
+                {
+                    var collectionEntities = Mapper.Map<List<EfModel.Collection>>(collections);
+                    await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, collectionEntities);
+
+                    if (collectionCiphers.Any())
+                    {
+                        var collectionCipherEntities = Mapper.Map<List<EfModel.CollectionCipher>>(collectionCiphers);
+                        await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, collectionCipherEntities);
+                    }
+                }
+                await UserBumpAccountRevisionDateByOrganizationId(ciphers.First().OrganizationId.Value);
+            }
+        }
+
+        public async Task DeleteAsync(IEnumerable<Guid> ids, Guid userId)
+        {
+            await ToggleCipherStates(ids, userId, CipherStateAction.HardDelete);
+        }
+
+        public async Task DeleteAttachmentAsync(Guid cipherId, string attachmentId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var cipher = await dbContext.Ciphers.FindAsync(cipherId);
+                var attachmentsJson = JObject.Parse(cipher.Attachments);
+                attachmentsJson.Remove(attachmentId);
+                cipher.Attachments = JsonConvert.SerializeObject(attachmentsJson);
+                await dbContext.SaveChangesAsync();
+
+                if (cipher.OrganizationId.HasValue)
+                {
+                    await OrganizationUpdateStorage(cipher.OrganizationId.Value);
+                    await UserBumpAccountRevisionDateByCipherId(cipher);
+                }
+                else if (cipher.UserId.HasValue)
+                {
+                    await UserUpdateStorage(cipher.UserId.Value);
+                    await UserBumpAccountRevisionDate(cipher.UserId.Value);
+                }
+            }
+        }
+
+        public async Task DeleteByIdsOrganizationIdAsync(IEnumerable<Guid> ids, Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var ciphers = from c in dbContext.Ciphers
+                              where c.OrganizationId == organizationId &&
+                                    ids.Contains(c.Id)
+                              select c;
+                dbContext.RemoveRange(ciphers);
+                await dbContext.SaveChangesAsync();
+            }
+            await OrganizationUpdateStorage(organizationId);
+            await UserBumpAccountRevisionDateByOrganizationId(organizationId);
+        }
+
+        public async Task DeleteByOrganizationIdAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+
+                var collectionCiphers = from cc in dbContext.CollectionCiphers
+                    join c in dbContext.Collections
+                        on cc.CollectionId equals c.Id
+                    where c.OrganizationId == organizationId
+                    select cc;
+                dbContext.RemoveRange(collectionCiphers);
+
+                var ciphers = from c in dbContext.Ciphers
+                    where c.OrganizationId == organizationId
+                    select c;
+                dbContext.RemoveRange(ciphers);
+
+                await dbContext.SaveChangesAsync();
+            }
+            await OrganizationUpdateStorage(organizationId);
+            await UserBumpAccountRevisionDateByOrganizationId(organizationId);
+        }
+
+        public async Task DeleteByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var ciphers = from c in dbContext.Ciphers
+                    where c.UserId == userId
+                    select c;
+                dbContext.RemoveRange(ciphers);
+                var folders = from f in dbContext.Folders
+                    where f.UserId == userId
+                    select f;
+                dbContext.RemoveRange(folders);
+                await dbContext.SaveChangesAsync();
+                await UserUpdateStorage(userId);
+                await UserBumpAccountRevisionDate(userId);
+            }
+
+        }
+
+        public async Task DeleteDeletedAsync(DateTime deletedDateBefore)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = dbContext.Ciphers.Where(c => c.DeletedDate < deletedDateBefore);
+                dbContext.RemoveRange(query);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task<CipherDetails> GetByIdAsync(Guid id, Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var userCipherDetails = new UserCipherDetailsQuery(userId);
+                var data = await userCipherDetails.Run(dbContext).FirstOrDefaultAsync(c => c.Id == id);
+                return data;
+            }
+        }
+
+        public async Task<bool> GetCanEditByIdAsync(Guid userId, Guid cipherId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new CipherReadCanEditByIdUserIdQuery(userId, cipherId);
+                var canEdit = await query.Run(dbContext).AnyAsync();
+                return canEdit;
+            }
+        }
+
+        public async Task<ICollection<Cipher>> GetManyByOrganizationIdAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = dbContext.Ciphers.Where(x => !x.UserId.HasValue && x.OrganizationId == organizationId);
+                var data = await query.ToListAsync();
+                return Mapper.Map<List<TableModel.Cipher>>(data);
+            }
+        }
+
+        public async Task<ICollection<CipherDetails>> GetManyByUserIdAsync(Guid userId, bool withOrganizations = true)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                IQueryable<CipherDetails> cipherDetailsView = withOrganizations ? 
+                    new UserCipherDetailsQuery(userId).Run(dbContext) :
+                    new CipherDetailsQuery(userId).Run(dbContext);
+                if (!withOrganizations)
+                {
+                    cipherDetailsView = from c in cipherDetailsView
+                        where c.UserId == userId
+                        select new CipherDetails {
+                            Id = c.Id,
+                            UserId = c.UserId,
+                            OrganizationId = c.OrganizationId,
+                            Type= c.Type,
+                            Data = c.Data,
+                            Attachments = c.Attachments,
+                            CreationDate = c.CreationDate,
+                            RevisionDate = c.RevisionDate,
+                            DeletedDate = c.DeletedDate,
+                            Favorite = c.Favorite,
+                            FolderId = c.FolderId,
+                            Edit = true,
+                            ViewPassword = true,
+                            OrganizationUseTotp = false,
+                        };
+                }
+                var ciphers = await cipherDetailsView.ToListAsync();
+                return ciphers;
+            }
+        }
+
+        public async Task<CipherOrganizationDetails> GetOrganizationDetailsByIdAsync(Guid id)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new CipherOrganizationDetailsReadByIdQuery(id);
+                var data = await query.Run(dbContext).FirstOrDefaultAsync();
+                return data;
+            }
+        }
+
+        public async Task MoveAsync(IEnumerable<Guid> ids, Guid? folderId, Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var cipherEntities = dbContext.Ciphers.Where(c => ids.Contains(c.Id));
+                var userCipherDetails = new UserCipherDetailsQuery(userId).Run(dbContext);
+                var idsToMove = from ucd in userCipherDetails
+                    join c in cipherEntities
+                        on ucd.Id equals c.Id
+                    where ucd.Edit
+                    select c;
+                await idsToMove.ForEachAsync(cipher => 
+                {
+                    var foldersJson = string.IsNullOrWhiteSpace(cipher.Folders) ? 
+                        new JObject() :
+                        JObject.Parse(cipher.Folders);
+
+                    if (folderId.HasValue)
+                    {
+                        foldersJson.Remove(userId.ToString());
+                        foldersJson.Add(userId.ToString(), folderId.Value.ToString());
+                    }
+                    else if (!string.IsNullOrWhiteSpace(cipher.Folders))
+                    {
+                        foldersJson.Remove(userId.ToString());
+                    }
+                    dbContext.Attach(cipher);
+                    cipher.Folders = JsonConvert.SerializeObject(foldersJson);
+                });          
+                await dbContext.SaveChangesAsync();
+                await UserBumpAccountRevisionDate(userId);
+            }
+        }
+
+        public async Task ReplaceAsync(CipherDetails cipher)
+        {
+            cipher.UserId = cipher.OrganizationId.HasValue ?
+                null :
+                cipher.UserId;
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entity = await dbContext.Ciphers.FindAsync(cipher.Id);
+                if (entity != null)
+                {
+                    var userIdKey = $"\"{cipher.UserId}\"";
+                    if (cipher.Favorite)
+                    {
+                        if (cipher.Favorites == null)
+                        {
+                            cipher.Favorites = $"{{{userIdKey}:true}}";
+                        }
+                        else
+                        {
+                            var favorites = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, bool>>(cipher.Favorites);
+                            favorites.Add(cipher.UserId.Value, true);
+                            cipher.Favorites = JsonConvert.SerializeObject(favorites);
+                        }
+                    }
+                    else
+                    {
+                        if (cipher.Favorites != null && cipher.Favorites.Contains(cipher.UserId.Value.ToString()))
+                        {
+                            var favorites = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, bool>>(cipher.Favorites);
+                            favorites.Remove(cipher.UserId.Value);
+                            cipher.Favorites = JsonConvert.SerializeObject(favorites);
+                        }
+                    }
+                    if (cipher.FolderId.HasValue)
+                    {
+                        if (cipher.Folders == null)
+                        {
+                            cipher.Folders = $"{{{userIdKey}:\"{cipher.FolderId}\"}}";
+                        }
+                        else
+                        {
+                            var folders = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, Guid>>(cipher.Folders);
+                            folders.Add(cipher.UserId.Value, cipher.FolderId.Value);
+                            cipher.Folders = JsonConvert.SerializeObject(folders);
+                        }
+                    }
+                    else
+                    {
+                        if (cipher.Folders != null && cipher.Folders.Contains(cipher.UserId.Value.ToString()))
+                        {
+                            var folders = CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, bool>>(cipher.Favorites);
+                            folders.Remove(cipher.UserId.Value);
+                            cipher.Favorites = JsonConvert.SerializeObject(folders);
+                        }
+                    }
+                    var mappedEntity = Mapper.Map<EfModel.Cipher>((TableModel.Cipher)cipher);
+                    dbContext.Entry(entity).CurrentValues.SetValues(mappedEntity);
+                    await UserBumpAccountRevisionDateByCipherId(cipher);
+                    await dbContext.SaveChangesAsync();
+                }
+            }
+        }
+
+        public async Task<bool> ReplaceAsync(Cipher obj, IEnumerable<Guid> collectionIds)
+        {
+            await UpdateCollections(obj, collectionIds);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var cipher = await dbContext.Ciphers.FindAsync(obj.Id);
+                cipher.UserId = null;
+                cipher.OrganizationId = obj.OrganizationId;
+                cipher.Data = obj.Data;
+                cipher.Attachments = obj.Attachments;
+                cipher.RevisionDate = obj.RevisionDate;
+                cipher.DeletedDate = obj.DeletedDate;
+                await dbContext.SaveChangesAsync();
+
+                if (!string.IsNullOrWhiteSpace(cipher.Attachments))
+                {
+                    if (cipher.OrganizationId.HasValue)
+                    {
+                        await OrganizationUpdateStorage(cipher.OrganizationId.Value);
+                    }
+                    else if (cipher.UserId.HasValue)
+                    {
+                        await UserUpdateStorage(cipher.UserId.Value);
+                    }
+                }
+
+                await UserBumpAccountRevisionDateByCipherId(cipher);
+                return true;
+            }
+        }
+
+        public async Task<DateTime> RestoreAsync(IEnumerable<Guid> ids, Guid userId)
+        {
+            return await ToggleCipherStates(ids, userId, CipherStateAction.Restore);
+        }
+
+        public async Task SoftDeleteAsync(IEnumerable<Guid> ids, Guid userId)
+        {
+            await ToggleCipherStates(ids, userId, CipherStateAction.SoftDelete);
+        }
+
+        private async Task<DateTime> ToggleCipherStates(IEnumerable<Guid> ids, Guid userId, CipherStateAction action)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var userCipherDetailsQuery = new UserCipherDetailsQuery(userId);
+                var cipherEntitiesToCheck = await (dbContext.Ciphers.Where(c => ids.Contains(c.Id))).ToListAsync();
+                var query = from ucd in await (userCipherDetailsQuery.Run(dbContext)).ToListAsync()
+                    join c in cipherEntitiesToCheck
+                        on ucd.Id equals c.Id
+                    where ucd.Edit && ucd.DeletedDate == null
+                    select c;
+
+                var utcNow = DateTime.UtcNow;
+                var cipherIdsToModify = query.Select(c => c.Id);
+                var cipherEntitiesToModify = dbContext.Ciphers.Where(x => cipherIdsToModify.Contains(x.Id));
+                if (action == CipherStateAction.HardDelete)
+                {
+                    dbContext.RemoveRange(cipherEntitiesToModify);
+                }
+                else 
+                {
+                    await cipherEntitiesToModify.ForEachAsync(cipher => 
+                    {
+                        dbContext.Attach(cipher);
+                        cipher.DeletedDate = action == CipherStateAction.Restore ? null : utcNow;
+                        cipher.RevisionDate = utcNow;
+                    });
+                }
+
+                var orgIds = query
+                    .Where(c => c.OrganizationId.HasValue)
+                    .GroupBy(c => c.OrganizationId).Select(x => x.Key);
+
+                foreach (var orgId in orgIds)
+                {
+                    await OrganizationUpdateStorage(orgId.Value);
+                    await UserBumpAccountRevisionDateByOrganizationId(orgId.Value);
+                }
+                if (query.Any(c => c.UserId.HasValue && !string.IsNullOrWhiteSpace(c.Attachments)))
+                {
+                    await UserUpdateStorage(userId);
+                }
+                await UserBumpAccountRevisionDate(userId);
+                await dbContext.SaveChangesAsync();
+                return utcNow;
+            }
+        }
+
+        public async Task SoftDeleteByIdsOrganizationIdAsync(IEnumerable<Guid> ids, Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var utcNow = DateTime.UtcNow;
+                var ciphers = dbContext.Ciphers.Where(c => ids.Contains(c.Id) && c.OrganizationId == organizationId);
+                await ciphers.ForEachAsync(cipher => 
+                {
+                    dbContext.Attach(cipher);
+                    cipher.DeletedDate = utcNow;
+                    cipher.RevisionDate = utcNow;
+                }); 
+                await dbContext.SaveChangesAsync();
+                await OrganizationUpdateStorage(organizationId);
+                await UserBumpAccountRevisionDateByOrganizationId(organizationId);
+            }
+        }
+
+        public async Task UpdateAttachmentAsync(CipherAttachment attachment)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var cipher = await dbContext.Ciphers.FindAsync(attachment.Id);
+                var attachmentsJson = string.IsNullOrWhiteSpace(cipher.Attachments) ? new JObject() : JObject.Parse(cipher.Attachments);
+                attachmentsJson.Add(attachment.AttachmentId, attachment.AttachmentData);
+                cipher.Attachments = JsonConvert.SerializeObject(attachmentsJson);
+                await dbContext.SaveChangesAsync();
+
+                if (attachment.OrganizationId.HasValue)
+                {
+                    await OrganizationUpdateStorage(cipher.OrganizationId.Value);
+                    await UserBumpAccountRevisionDateByCipherId(new List<Cipher> { cipher });
+                }
+                else if (attachment.UserId.HasValue)
+                {
+                    await UserUpdateStorage(attachment.UserId.Value);
+                    await UserBumpAccountRevisionDate(attachment.UserId.Value);
+                }
+            }
+        }
+
+        public async Task UpdateCiphersAsync(Guid userId, IEnumerable<Cipher> ciphers)
+        {
+            if (!ciphers.Any()) 
+            {
+                return; 
+            }
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entities = Mapper.Map<List<EfModel.Cipher>>(ciphers);
+                await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, entities);
+                await UserBumpAccountRevisionDate(userId);
+            }
+        }
+
+        public async Task UpdatePartialAsync(Guid id, Guid userId, Guid? folderId, bool favorite)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var cipher = await dbContext.Ciphers.FindAsync(id);
+
+                var foldersJson = JObject.Parse(cipher.Folders);
+                if (foldersJson == null && folderId.HasValue)
+                {
+                    foldersJson.Add(userId.ToString(), folderId.Value);
+                }
+                else if (foldersJson != null && folderId.HasValue)
+                {
+                    foldersJson[userId] = folderId.Value;
+                }
+                else 
+                {
+                    foldersJson.Remove(userId.ToString());
+                }
+
+                var favoritesJson = JObject.Parse(cipher.Favorites);
+                if (favorite)
+                {
+                    favoritesJson.Add(userId.ToString(), favorite);
+                }
+                else 
+                {
+                    favoritesJson.Remove(userId.ToString());
+                }
+
+                await dbContext.SaveChangesAsync();
+                await UserBumpAccountRevisionDate(userId);
+            }
+        }
+
+        public async Task UpdateUserKeysAndCiphersAsync(User user, IEnumerable<Cipher> ciphers, IEnumerable<Folder> folders, IEnumerable<Send> sends)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                await UserUpdateKeys(user);
+                var cipherEntities = Mapper.Map<List<EfModel.Cipher>>(ciphers);
+                await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, cipherEntities);
+                var folderEntities = Mapper.Map<List<EfModel.Folder>>(folders);
+                await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, folderEntities);
+                var sendEntities = Mapper.Map<List<EfModel.Send>>(sends);
+                await dbContext.BulkCopyAsync(base.DefaultBulkCopyOptions, sendEntities);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task UpsertAsync(CipherDetails cipher)
+        {
+            if (cipher.Id.Equals(default))
+            {
+                await CreateAsync(cipher);
+            }
+            else
+            {
+                await ReplaceAsync(cipher);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/CollectionCipherRepository.cs b/src/Core/Repositories/EntityFramework/CollectionCipherRepository.cs
new file mode 100644
index 0000000000..e1e788d69f
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/CollectionCipherRepository.cs
@@ -0,0 +1,242 @@
+using AutoMapper;
+using Bit.Core.Enums;
+using Bit.Core.Models.Table;
+using Bit.Core.Repositories.EntityFramework.Queries;
+using EfModel = Bit.Core.Models.EntityFramework;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class CollectionCipherRepository : BaseEntityFrameworkRepository, ICollectionCipherRepository
+    {
+        public CollectionCipherRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper)
+        { }
+
+        public async Task<CollectionCipher> CreateAsync(CollectionCipher obj)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entity = Mapper.Map<EfModel.CollectionCipher>(obj);
+                dbContext.Add(entity);
+                await dbContext.SaveChangesAsync();
+                var organizationId = (await dbContext.Ciphers.FirstOrDefaultAsync(c => c.Id.Equals(obj.CipherId))).OrganizationId;
+                if (organizationId.HasValue)
+                {
+                    await UserBumpAccountRevisionDateByCollectionId(obj.CollectionId, organizationId.Value);
+                }
+                return obj;
+            }
+        }
+
+        public async Task<ICollection<CollectionCipher>> GetManyByOrganizationIdAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var data = await (from cc in dbContext.CollectionCiphers
+                    join c in dbContext.Collections 
+                        on cc.CollectionId equals c.Id
+                    where c.OrganizationId == organizationId
+                    select cc).ToArrayAsync();
+                return data;
+            }
+        }
+
+        public async Task<ICollection<CollectionCipher>> GetManyByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var data = await new CollectionCipherReadByUserIdQuery(userId)
+                    .Run(dbContext)
+                    .ToArrayAsync();
+                return data;
+            }
+        }
+
+        public async Task<ICollection<CollectionCipher>> GetManyByUserIdCipherIdAsync(Guid userId, Guid cipherId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var data = await new CollectionCipherReadByUserIdCipherIdQuery(userId, cipherId)
+                    .Run(dbContext)
+                    .ToArrayAsync();
+                return data;
+            }
+        }
+
+        public async Task UpdateCollectionsAsync(Guid cipherId, Guid userId, IEnumerable<Guid> collectionIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var organizationId = (await dbContext.Ciphers.FindAsync(cipherId)).OrganizationId;
+                var availableCollectionsCte = from c in dbContext.Collections
+                    join o in dbContext.Organizations
+                        on c.OrganizationId equals o.Id
+                    join ou in dbContext.OrganizationUsers
+                        on o.Id equals ou.OrganizationId
+                    where ou.UserId == userId
+                    join cu in dbContext.CollectionUsers
+                        on ou.Id equals cu.OrganizationUserId into cu_g
+                    from cu in cu_g.DefaultIfEmpty()
+                    where !ou.AccessAll && cu.CollectionId == c.Id
+                    join gu in dbContext.GroupUsers
+                        on ou.Id equals gu.OrganizationUserId into gu_g
+                    from gu in gu_g.DefaultIfEmpty()
+                    where cu.CollectionId == null && !ou.AccessAll
+                    join g in dbContext.Groups
+                        on gu.GroupId equals g.Id into g_g
+                    from g in g_g.DefaultIfEmpty()
+                    join cg in dbContext.CollectionGroups
+                        on gu.GroupId equals cg.GroupId into cg_g
+                    from cg in cg_g.DefaultIfEmpty()
+                    where !g.AccessAll && cg.CollectionId == c.Id &&
+                    (o.Id == organizationId && o.Enabled && ou.Status == OrganizationUserStatusType.Confirmed && (
+                    ou.AccessAll || !cu.ReadOnly || g.AccessAll || !cg.ReadOnly))
+                    select new { c, o, cu, gu, g, cg };
+                var target = from cc in dbContext.CollectionCiphers
+                    where cc.CipherId == cipherId
+                    select new { cc.CollectionId, cc.CipherId };
+                var source = collectionIds.Select(x => new { CollectionId = x, CipherId = cipherId });
+                var merge1 = from t in target
+                    join s in source
+                        on t.CollectionId equals s.CollectionId into s_g
+                    from s in s_g.DefaultIfEmpty()
+                    where t.CipherId == s.CipherId
+                    select new { t, s };
+                var merge2 = from s in source
+                    join t in target
+                        on s.CollectionId equals t.CollectionId into t_g
+                    from t in t_g.DefaultIfEmpty()
+                    where t.CipherId == s.CipherId
+                    select new { t, s };
+                var union = merge1.Union(merge2).Distinct();
+                var insert = union
+                    .Where(x => x.t == null && collectionIds.Contains(x.s.CollectionId))
+                    .Select(x => new EfModel.CollectionCipher
+                    {
+                        CollectionId = x.s.CollectionId,
+                        CipherId = x.s.CipherId,
+                    });
+                var delete = union
+                    .Where(x => x.s == null && x.t.CipherId == cipherId && collectionIds.Contains(x.t.CollectionId))
+                    .Select(x => new EfModel.CollectionCipher
+                    {
+                        CollectionId = x.t.CollectionId,
+                        CipherId = x.t.CipherId,
+                    });
+                await dbContext.AddRangeAsync(insert);
+                dbContext.RemoveRange(delete);
+                await dbContext.SaveChangesAsync();
+
+                if (organizationId.HasValue)
+                {
+                    await UserBumpAccountRevisionDateByOrganizationId(organizationId.Value);
+                }
+            }
+        }
+
+        public async Task UpdateCollectionsForAdminAsync(Guid cipherId, Guid organizationId, IEnumerable<Guid> collectionIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var availableCollectionsCte = from c in dbContext.Collections
+                    where c.OrganizationId == organizationId
+                    select c;
+                var target = from cc in dbContext.CollectionCiphers
+                    where cc.CipherId == cipherId
+                    select new { cc.CollectionId, cc.CipherId };
+                var source = collectionIds.Select(x => new { CollectionId = x, CipherId = cipherId });
+                var merge1 = from t in target
+                    join s in source
+                        on t.CollectionId equals s.CollectionId into s_g
+                    from s in s_g.DefaultIfEmpty()
+                    where t.CipherId == s.CipherId
+                    select new { t, s };
+                var merge2 = from s in source
+                    join t in target
+                        on s.CollectionId equals t.CollectionId into t_g
+                    from t in t_g.DefaultIfEmpty()
+                    where t.CipherId == s.CipherId
+                    select new { t, s };
+                var union = merge1.Union(merge2).Distinct();
+                var insert = union
+                    .Where(x => x.t == null && collectionIds.Contains(x.s.CollectionId))
+                    .Select(x => new EfModel.CollectionCipher 
+                    {
+                        CollectionId = x.s.CollectionId,
+                        CipherId = x.s.CipherId,
+                    });
+                var delete = union
+                    .Where(x => x.s == null && x.t.CipherId == cipherId)
+                    .Select(x => new EfModel.CollectionCipher
+                    {
+                        CollectionId = x.t.CollectionId,
+                        CipherId = x.t.CipherId,
+                    });
+                await dbContext.AddRangeAsync(insert);
+                dbContext.RemoveRange(delete);
+                await dbContext.SaveChangesAsync();
+                await UserBumpAccountRevisionDateByOrganizationId(organizationId);
+            }
+        }
+
+        public async Task UpdateCollectionsForCiphersAsync(IEnumerable<Guid> cipherIds, Guid userId, Guid organizationId, IEnumerable<Guid> collectionIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var availibleCollections = from c in dbContext.Collections
+                    join o in dbContext.Organizations
+                        on c.OrganizationId equals o.Id
+                    join ou in dbContext.OrganizationUsers
+                        on o.Id equals ou.OrganizationId
+                    where ou.UserId == userId
+                    join cu in dbContext.CollectionUsers
+                        on ou.Id equals cu.OrganizationUserId into cu_g
+                    from cu in cu_g.DefaultIfEmpty()
+                    where !ou.AccessAll && cu.CollectionId == c.Id
+                    join gu in dbContext.GroupUsers
+                        on ou.Id equals gu.OrganizationUserId into gu_g
+                    from gu in gu_g.DefaultIfEmpty()
+                    where cu.CollectionId == null && !ou.AccessAll
+                    join g in dbContext.Groups
+                        on gu.GroupId equals g.Id into g_g
+                    from g in g_g.DefaultIfEmpty()
+                    join cg in dbContext.CollectionGroups
+                        on gu.GroupId equals cg.GroupId into cg_g
+                    from cg in cg_g.DefaultIfEmpty()
+                    where !g.AccessAll && cg.CollectionId == c.Id &&
+                    (o.Id == organizationId && o.Enabled && ou.Status == OrganizationUserStatusType.Confirmed && 
+                    (ou.AccessAll || !cu.ReadOnly || g.AccessAll || !cg.ReadOnly))
+                    select new { c, o, ou, cu, gu, g, cg };
+                var count = await availibleCollections.CountAsync();
+                if (await availibleCollections.CountAsync() < 1)
+                {
+                    return;
+                }
+
+                var insertData = from collectionId in collectionIds
+                    from cipherId in cipherIds
+                    where availibleCollections.Select(x => x.c.Id).Contains(collectionId)
+                    select new EfModel.CollectionCipher
+                    {
+                        CollectionId = collectionId,
+                        CipherId = cipherId,
+                    };
+                await dbContext.AddRangeAsync(insertData);
+                await UserBumpAccountRevisionDateByOrganizationId(organizationId);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/CollectionRepository.cs b/src/Core/Repositories/EntityFramework/CollectionRepository.cs
new file mode 100644
index 0000000000..33823bd3e0
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/CollectionRepository.cs
@@ -0,0 +1,247 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Data;
+using Bit.Core.Models.Table;
+using Bit.Core.Repositories.EntityFramework.Queries;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class CollectionRepository : Repository<TableModel.Collection, EfModel.Collection, Guid>, ICollectionRepository
+    {
+        public CollectionRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Collections)
+        { }
+
+        public override async Task<TableModel.Collection> CreateAsync(Collection obj)
+        {
+            await base.CreateAsync(obj);
+            await UserBumpAccountRevisionDateByCollectionId(obj.Id, obj.OrganizationId);
+            return obj;
+        }
+
+        public async Task CreateAsync(Collection obj, IEnumerable<SelectionReadOnly> groups)
+        {
+            await base.CreateAsync(obj);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var availibleGroups = await (from g in dbContext.Groups
+                    where g.OrganizationId == obj.OrganizationId
+                    select g.Id).ToListAsync();
+                var collectionGroups = groups
+                    .Where(g => availibleGroups.Contains(g.Id))
+                    .Select(g => new EfModel.CollectionGroup
+                    {
+                        CollectionId = obj.Id,
+                        GroupId = g.Id,
+                        ReadOnly = g.ReadOnly,
+                        HidePasswords = g.HidePasswords,
+                    });
+                await dbContext.AddRangeAsync(collectionGroups);
+                await dbContext.SaveChangesAsync();
+                await UserBumpAccountRevisionDateByOrganizationId(obj.OrganizationId);
+            }
+        }
+
+        public async Task DeleteUserAsync(Guid collectionId, Guid organizationUserId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from cu in dbContext.CollectionUsers
+                    where cu.CollectionId == collectionId &&
+                        cu.OrganizationUserId == organizationUserId
+                    select cu;
+                dbContext.RemoveRange(await query.ToListAsync());
+                await dbContext.SaveChangesAsync();
+                await UserBumpAccountRevisionDateByOrganizationUserId(organizationUserId);
+            }
+        }
+
+        public async Task<CollectionDetails> GetByIdAsync(Guid id, Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new UserCollectionDetailsQuery(userId);
+                var collection = await query.Run(dbContext).FirstOrDefaultAsync();
+                return collection;
+            }
+        }
+
+        public async Task<Tuple<Collection, ICollection<SelectionReadOnly>>> GetByIdWithGroupsAsync(Guid id)
+        {
+            var collection =  await base.GetByIdAsync(id);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var collectionGroups = await (from cg in dbContext.CollectionGroups
+                    where cg.CollectionId == id
+                    select cg).ToListAsync();
+                var selectionReadOnlys = collectionGroups.Select(cg => new SelectionReadOnly 
+                {
+                    Id = cg.GroupId,
+                    ReadOnly = cg.ReadOnly,
+                    HidePasswords = cg.HidePasswords,
+                }).ToList();
+                return new Tuple<Collection, ICollection<SelectionReadOnly>>(collection, selectionReadOnlys);
+            }
+        }
+
+        public async Task<Tuple<CollectionDetails, ICollection<SelectionReadOnly>>> GetByIdWithGroupsAsync(Guid id, Guid userId)
+        {
+            var collection = await GetByIdAsync(id, userId);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from cg in dbContext.CollectionGroups
+                    where cg.CollectionId.Equals(id)
+                    select new SelectionReadOnly 
+                    { 
+                        Id = cg.GroupId,
+                        ReadOnly = cg.ReadOnly,
+                        HidePasswords = cg.HidePasswords, 
+                    };
+                var configurations = await query.ToArrayAsync();
+                return new Tuple<CollectionDetails, ICollection<SelectionReadOnly>>(collection, configurations);
+            }
+        }
+
+        public async Task<int> GetCountByOrganizationIdAsync(Guid organizationId)
+        {
+            var query = new CollectionReadCountByOrganizationIdQuery(organizationId);
+            return await GetCountFromQuery(query);
+        }
+
+        public async Task<ICollection<Collection>> GetManyByOrganizationIdAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from c in dbContext.Collections
+                    where c.OrganizationId == organizationId
+                    select c;
+                var collections = await query.ToArrayAsync();
+                return collections;
+            }
+        }
+
+        public async Task<ICollection<CollectionDetails>> GetManyByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new UserCollectionDetailsQuery(userId).Run(dbContext);
+                var data = await query.ToListAsync();
+                return data.GroupBy(c => c.Id).Select(c => c.First()).ToList();
+            }
+        }
+
+        public async Task<ICollection<SelectionReadOnly>> GetManyUsersByIdAsync(Guid id)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from cu in dbContext.CollectionUsers
+                    where cu.CollectionId == id
+                    select cu;
+                var collectionUsers = await query.ToListAsync();
+                return collectionUsers.Select(cu => new SelectionReadOnly 
+                {
+                    Id = cu.OrganizationUserId,
+                    ReadOnly = cu.ReadOnly,
+                    HidePasswords = cu.HidePasswords,
+                }).ToArray();
+            }
+        }
+
+        public async Task ReplaceAsync(Collection collection, IEnumerable<SelectionReadOnly> groups)
+        {
+            await base.ReplaceAsync(collection);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var groupsInOrg = dbContext.Groups.Where(g => g.OrganizationId == collection.OrganizationId);
+                var modifiedGroupEntities = dbContext.Groups.Where(x => groups.Select(x => x.Id).Contains(x.Id));
+                var target = (from cg in dbContext.CollectionGroups
+                    join g in modifiedGroupEntities 
+                        on cg.CollectionId equals collection.Id into s_g
+                    from g in s_g.DefaultIfEmpty()
+                    where g == null || cg.GroupId == g.Id
+                    select new {cg, g}).AsNoTracking();
+                var source = (from g in modifiedGroupEntities
+                    from cg in dbContext.CollectionGroups
+                        .Where(cg => cg.CollectionId == collection.Id && cg.GroupId == g.Id).DefaultIfEmpty()
+                    select new {cg, g}).AsNoTracking();
+                var union = await target
+                    .Union(source)
+                    .Where(x => 
+                        x.cg == null ||
+                        ((x.g == null || x.g.Id == x.cg.GroupId) && 
+                        (x.cg.CollectionId == collection.Id)))
+                    .AsNoTracking()
+                    .ToListAsync();
+                var insert = union.Where(x => x.cg == null && groupsInOrg.Any(c => x.g.Id == c.Id))
+                    .Select(x => new EfModel.CollectionGroup 
+                    {
+                        CollectionId = collection.Id,
+                        GroupId = x.g.Id,
+                        ReadOnly = groups.FirstOrDefault(g => g.Id == x.g.Id).ReadOnly,
+                        HidePasswords = groups.FirstOrDefault(g => g.Id == x.g.Id).HidePasswords,
+                    }).ToList();
+                var update = union
+                    .Where(
+                        x => x.g != null && 
+                        x.cg != null && 
+                        (x.cg.ReadOnly != groups.FirstOrDefault(g => g.Id == x.g.Id).ReadOnly || 
+                        x.cg.HidePasswords != groups.FirstOrDefault(g => g.Id == x.g.Id).HidePasswords)
+                    )
+                    .Select(x => new EfModel.CollectionGroup 
+                    {
+                        CollectionId = collection.Id, 
+                        GroupId = x.g.Id,
+                        ReadOnly = groups.FirstOrDefault(g => g.Id == x.g.Id).ReadOnly,
+                        HidePasswords = groups.FirstOrDefault(g => g.Id == x.g.Id).HidePasswords,
+                    });
+                var delete = union
+                    .Where(
+                        x => x.g == null && 
+                        x.cg.CollectionId == collection.Id
+                    )
+                    .Select(x => new EfModel.CollectionGroup 
+                    { 
+                        CollectionId = collection.Id, 
+                        GroupId = x.cg.GroupId,
+                    })
+                    .ToList();
+                
+                await dbContext.AddRangeAsync(insert);
+                dbContext.UpdateRange(update);
+                dbContext.RemoveRange(delete);
+                await dbContext.SaveChangesAsync();
+                await UserBumpAccountRevisionDateByCollectionId(collection.Id, collection.OrganizationId);
+            }
+        }
+
+        public async Task UpdateUsersAsync(Guid id, IEnumerable<SelectionReadOnly> users)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var procedure = new CollectionUserUpdateUsersQuery(id, users);
+                var updateData = await procedure.Update.BuildInMemory(dbContext);
+                dbContext.UpdateRange(updateData);
+                var insertData = await procedure.Insert.BuildInMemory(dbContext);
+                await dbContext.AddRangeAsync(insertData);
+                dbContext.RemoveRange(await procedure.Delete.Run(dbContext).ToListAsync()); 
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/DatabaseContext.cs b/src/Core/Repositories/EntityFramework/DatabaseContext.cs
index df418a0ee0..c0940d330b 100644
--- a/src/Core/Repositories/EntityFramework/DatabaseContext.cs
+++ b/src/Core/Repositories/EntityFramework/DatabaseContext.cs
@@ -1,39 +1,136 @@
-using System;
-using Bit.Core.Models.EntityFramework;
+using Bit.Core.Models.EntityFramework;
+using Bit.Core.Models.EntityFramework.Provider;
 using Microsoft.EntityFrameworkCore;
 
 namespace Bit.Core.Repositories.EntityFramework
 {
     public class DatabaseContext : DbContext
     {
+        public const string postgresIndetermanisticCollation = "postgresIndetermanisticCollation";
+
         public DatabaseContext(DbContextOptions<DatabaseContext> options)
             : base(options)
         { }
 
-        public DbSet<User> Users { get; set; }
         public DbSet<Cipher> Ciphers { get; set; }
+        public DbSet<Collection> Collections { get; set; }
+        public DbSet<CollectionCipher> CollectionCiphers { get; set; }
+        public DbSet<CollectionGroup> CollectionGroups { get; set; }
+        public DbSet<CollectionUser> CollectionUsers { get; set; }
+        public DbSet<Device> Devices { get; set; }
+        public DbSet<EmergencyAccess> EmergencyAccesses { get; set; }
+        public DbSet<Event> Events { get; set; }
+        public DbSet<Folder> Folders { get; set; }
+        public DbSet<Grant> Grants { get; set; }
+        public DbSet<Group> Groups { get; set; }
+        public DbSet<GroupUser> GroupUsers { get; set; }
+        public DbSet<Installation> Installations { get; set; }
         public DbSet<Organization> Organizations { get; set; }
-
+        public DbSet<OrganizationUser> OrganizationUsers { get; set; }
+        public DbSet<Policy> Policies { get; set; }
+        public DbSet<Provider> Providers { get; set; }
+        public DbSet<ProviderUser> ProviderUsers { get; set; }
+        public DbSet<ProviderOrganization> ProviderOrganizations { get; set; }
+        public DbSet<ProviderOrganizationProviderUser> ProviderOrganizationProviderUsers { get; set; }
+        public DbSet<Send> Sends { get; set; }
+        public DbSet<SsoConfig> SsoConfigs { get; set; }
+        public DbSet<SsoUser> SsoUsers { get; set; }
+        public DbSet<TaxRate> TaxRates { get; set; }
+        public DbSet<Transaction> Transactions { get; set; }
+        public DbSet<U2f> U2fs { get; set; }
+        public DbSet<User> Users { get; set; }
+        
         protected override void OnModelCreating(ModelBuilder builder)
         {
-            builder.Entity<Cipher>().Ignore(e => e.Data);
-            builder.Entity<Cipher>().Property(e => e.DataJson).HasColumnName("Data");
-            builder.Entity<Cipher>().Ignore(e => e.Attachments);
-            builder.Entity<Cipher>().Property(e => e.AttachmentsJson).HasColumnName("Attachments");
-            builder.Entity<Cipher>().Ignore(e => e.Favorites);
-            builder.Entity<Cipher>().Property(e => e.FavoritesJson).HasColumnName("Favorites");
-            builder.Entity<Cipher>().Ignore(e => e.Folders);
-            builder.Entity<Cipher>().Property(e => e.FoldersJson).HasColumnName("Folders");
+            var eCipher = builder.Entity<Cipher>();
+            var eCollection = builder.Entity<Collection>();
+            var eCollectionCipher = builder.Entity<CollectionCipher>();
+            var eCollectionUser = builder.Entity<CollectionUser>();
+            var eCollectionGroup = builder.Entity<CollectionGroup>();
+            var eDevice = builder.Entity<Device>();
+            var eEmergencyAccess = builder.Entity<EmergencyAccess>();
+            var eEvent = builder.Entity<Event>();
+            var eFolder = builder.Entity<Folder>();
+            var eGrant = builder.Entity<Grant>();
+            var eGroup = builder.Entity<Group>();
+            var eGroupUser = builder.Entity<GroupUser>();
+            var eInstallation = builder.Entity<Installation>();
+            var eOrganization = builder.Entity<Organization>();
+            var eOrganizationUser = builder.Entity<OrganizationUser>();
+            var ePolicy = builder.Entity<Policy>();
+            var eProvider = builder.Entity<Provider>();
+            var eProviderUser = builder.Entity<ProviderUser>();
+            var eProviderOrganization = builder.Entity<ProviderOrganization>();
+            var eProviderOrganizationProviderUser = builder.Entity<ProviderOrganizationProviderUser>();
+            var eSend = builder.Entity<Send>();
+            var eSsoConfig = builder.Entity<SsoConfig>();
+            var eSsoUser = builder.Entity<SsoUser>();
+            var eTaxRate = builder.Entity<TaxRate>();
+            var eTransaction = builder.Entity<Transaction>();
+            var eU2f = builder.Entity<U2f>();
+            var eUser = builder.Entity<User>();
 
-            builder.Entity<User>().Ignore(e => e.TwoFactorProviders);
-            builder.Entity<User>().Property(e => e.TwoFactorProvidersJson).HasColumnName("TwoFactorProviders");
+            eCipher.Property(c => c.Id).ValueGeneratedNever();
+            eCollection.Property(c => c.Id).ValueGeneratedNever();
+            eEmergencyAccess.Property(c => c.Id).ValueGeneratedNever();
+            eEvent.Property(c => c.Id).ValueGeneratedNever();
+            eFolder.Property(c => c.Id).ValueGeneratedNever();
+            eGroup.Property(c => c.Id).ValueGeneratedNever();
+            eInstallation.Property(c => c.Id).ValueGeneratedNever();
+            eOrganization.Property(c => c.Id).ValueGeneratedNever();
+            eOrganizationUser.Property(c => c.Id).ValueGeneratedNever();
+            ePolicy.Property(c => c.Id).ValueGeneratedNever();
+            eProvider.Property(c => c.Id).ValueGeneratedNever();
+            eProviderUser.Property(c => c.Id).ValueGeneratedNever();
+            eProviderOrganization.Property(c => c.Id).ValueGeneratedNever();
+            eProviderOrganizationProviderUser.Property(c => c.Id).ValueGeneratedNever();
+            eSend.Property(c => c.Id).ValueGeneratedNever();
+            eTransaction.Property(c => c.Id).ValueGeneratedNever();
+            eUser.Property(c => c.Id).ValueGeneratedNever();
 
-            builder.Entity<Organization>().Ignore(e => e.TwoFactorProviders);
-            builder.Entity<Organization>().Property(e => e.TwoFactorProvidersJson).HasColumnName("TwoFactorProviders");
+            eCollectionCipher.HasKey(cc => new { cc.CollectionId, cc.CipherId });
+            eCollectionUser.HasKey(cu => new { cu.CollectionId, cu.OrganizationUserId });
+            eCollectionGroup.HasKey(cg => new { cg.CollectionId, cg.GroupId });
+            eGrant.HasKey(x => x.Key);
+            eGroupUser.HasKey(gu => new { gu.GroupId, gu.OrganizationUserId });
 
-            builder.Entity<User>().ToTable(nameof(User));
-            builder.Entity<Cipher>().ToTable(nameof(Cipher));
-            builder.Entity<Organization>().ToTable(nameof(Organization));
+
+            if (Database.IsNpgsql()) 
+            {
+                // the postgres provider doesn't currently support database level non-deterministic collations.
+                // see https://www.npgsql.org/efcore/misc/collations-and-case-sensitivity.html#database-collation
+                builder.HasCollation(postgresIndetermanisticCollation, locale: "en-u-ks-primary", provider: "icu", deterministic: false);
+                eUser.Property(e => e.Email).UseCollation(postgresIndetermanisticCollation);
+                eSsoUser.Property(e => e.ExternalId).UseCollation(postgresIndetermanisticCollation);
+                eOrganization.Property(e => e.Identifier).UseCollation(postgresIndetermanisticCollation);
+                //
+            }
+
+            eCipher.ToTable(nameof(Cipher));
+            eCollection.ToTable(nameof(Collection));
+            eCollectionCipher.ToTable(nameof(CollectionCipher));
+            eDevice.ToTable(nameof(Device));
+            eEmergencyAccess.ToTable(nameof(EmergencyAccess));
+            eEvent.ToTable(nameof(Event));
+            eFolder.ToTable(nameof(Folder));
+            eGrant.ToTable(nameof(Grant));
+            eGroup.ToTable(nameof(Group));
+            eGroupUser.ToTable(nameof(GroupUser));
+            eInstallation.ToTable(nameof(Installation));
+            eOrganization.ToTable(nameof(Organization));
+            eOrganizationUser.ToTable(nameof(OrganizationUser));
+            ePolicy.ToTable(nameof(Policy));
+            eProvider.ToTable(nameof(Provider));
+            eProviderUser.ToTable(nameof(ProviderUser));
+            eProviderOrganization.ToTable(nameof(ProviderOrganization));
+            eProviderOrganizationProviderUser.ToTable(nameof(ProviderOrganizationProviderUser));
+            eSend.ToTable(nameof(Send));
+            eSsoConfig.ToTable(nameof(SsoConfig));
+            eSsoUser.ToTable(nameof(SsoUser));
+            eTaxRate.ToTable(nameof(TaxRate));
+            eTransaction.ToTable(nameof(Transaction));
+            eU2f.ToTable(nameof(U2f));
+            eUser.ToTable(nameof(User));
         }
     }
 }
diff --git a/src/Core/Repositories/EntityFramework/DeviceRepository.cs b/src/Core/Repositories/EntityFramework/DeviceRepository.cs
new file mode 100644
index 0000000000..79f6e8c93f
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/DeviceRepository.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Table;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class DeviceRepository : Repository<TableModel.Device, EfModel.Device, Guid>, IDeviceRepository
+    {
+        public DeviceRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Devices)
+        { }
+
+        public async Task ClearPushTokenAsync(Guid id)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = dbContext.Devices.Where(d => d.Id == id);
+                dbContext.AttachRange(query);
+                await query.ForEachAsync(x => x.PushToken = null);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task<Device> GetByIdAsync(Guid id, Guid userId)
+        {
+            var device = await base.GetByIdAsync(id);
+            if (device == null || device.UserId != userId)
+            {
+                return null;
+            }
+
+            return Mapper.Map<TableModel.Device>(device);
+        }
+
+        public async Task<Device> GetByIdentifierAsync(string identifier)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = dbContext.Devices.Where(d => d.Identifier == identifier);
+                var device = await query.FirstOrDefaultAsync();
+                return Mapper.Map<TableModel.Device>(device);
+            }
+        }
+
+        public async Task<Device> GetByIdentifierAsync(string identifier, Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = dbContext.Devices.Where(d => d.Identifier == identifier && d.UserId == userId);
+                var device = await query.FirstOrDefaultAsync();
+                return Mapper.Map<TableModel.Device>(device);
+            }
+        }
+
+        public async Task<ICollection<Device>> GetManyByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = dbContext.Devices.Where(d => d.UserId == userId);
+                var devices = await query.ToListAsync();
+                return Mapper.Map<List<TableModel.Device>>(devices);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/EmergencyAccessRepository.cs b/src/Core/Repositories/EntityFramework/EmergencyAccessRepository.cs
new file mode 100644
index 0000000000..c8c4ecfaa4
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/EmergencyAccessRepository.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Enums;
+using Bit.Core.Models.Data;
+using Bit.Core.Repositories.EntityFramework.Queries;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class EmergencyAccessRepository : Repository<TableModel.EmergencyAccess, EfModel.EmergencyAccess, Guid>, IEmergencyAccessRepository
+    {
+        public EmergencyAccessRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.EmergencyAccesses)
+        { }
+
+        public async Task<int> GetCountByGrantorIdEmailAsync(Guid grantorId, string email, bool onlyRegisteredUsers)
+        {
+            var query = new EmergencyAccessReadCountByGrantorIdEmailQuery(grantorId, email, onlyRegisteredUsers);
+            return await GetCountFromQuery(query);
+        }
+
+        public async Task<EmergencyAccessDetails> GetDetailsByIdGrantorIdAsync(Guid id, Guid grantorId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = new EmergencyAccessDetailsViewQuery();
+                var query = view.Run(dbContext).Where(ea => 
+                    ea.Id == id && 
+                    ea.GrantorId == grantorId
+                );
+                return await query.FirstOrDefaultAsync();
+            }
+        }
+
+        public async Task<ICollection<EmergencyAccessDetails>> GetExpiredRecoveriesAsync()
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = new EmergencyAccessDetailsViewQuery();
+                var query = view.Run(dbContext).Where(ea => 
+                    ea.Status == EmergencyAccessStatusType.RecoveryInitiated
+                );
+                return await query.ToListAsync();
+            }
+        }
+
+        public async Task<ICollection<EmergencyAccessDetails>> GetManyDetailsByGranteeIdAsync(Guid granteeId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = new EmergencyAccessDetailsViewQuery();
+                var query = view.Run(dbContext).Where(ea => 
+                    ea.GranteeId == granteeId
+                );
+                return await query.ToListAsync();
+            }
+        }
+
+        public async Task<ICollection<EmergencyAccessDetails>> GetManyDetailsByGrantorIdAsync(Guid grantorId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = new EmergencyAccessDetailsViewQuery();
+                var query = view.Run(dbContext).Where(ea => 
+                    ea.GrantorId == grantorId
+                );
+                return await query.ToListAsync();
+            }
+        }
+
+        public async Task<ICollection<EmergencyAccessNotify>> GetManyToNotifyAsync()
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = new EmergencyAccessDetailsViewQuery();
+                var query = view.Run(dbContext).Where(ea => 
+                    ea.Status == EmergencyAccessStatusType.RecoveryInitiated
+                );
+                var notifies = await query.Select(ea => new EmergencyAccessNotify 
+                {
+                    Id = ea.Id,
+                    GrantorId = ea.GrantorId,
+                    GranteeId = ea.GranteeId,
+                    Email = ea.Email,
+                    KeyEncrypted = ea.KeyEncrypted,
+                    Type = ea.Type,
+                    Status = ea.Status,
+                    WaitTimeDays = ea.WaitTimeDays,
+                    RecoveryInitiatedDate = ea.RecoveryInitiatedDate,
+                    LastNotificationDate = ea.LastNotificationDate,
+                    CreationDate = ea.CreationDate,
+                    RevisionDate = ea.RevisionDate,
+                    GranteeName = ea.GranteeName,
+                    GranteeEmail = ea.GranteeEmail,
+                    GrantorEmail = ea.GrantorEmail,
+                }).ToListAsync(); 
+                return notifies;
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/EventRepository.cs b/src/Core/Repositories/EntityFramework/EventRepository.cs
new file mode 100644
index 0000000000..bff7843b87
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/EventRepository.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Data;
+using Bit.Core.Models.Table;
+using Bit.Core.Repositories.EntityFramework.Queries;
+using LinqToDB.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class EventRepository : Repository<TableModel.Event, EfModel.Event, Guid>, IEventRepository
+    {
+        public EventRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Events)
+        { }
+
+        public async Task CreateAsync(IEvent e)
+        {
+            if (e is not Event ev)
+            {
+                ev = new Event(e);
+            }
+
+            await base.CreateAsync(ev);
+        }
+
+        public async Task CreateManyAsync(IEnumerable<IEvent> entities)
+        {
+            if (!entities?.Any() ?? true)
+            {
+                return;
+            }
+
+            if (!entities.Skip(1).Any())
+            {
+                await CreateAsync(entities.First());
+                return;
+            }
+
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var tableEvents = entities.Select(e => e as Event ?? new Event(e));
+                var entityEvents = Mapper.Map<List<EfModel.Event>>(tableEvents);
+                await dbContext.BulkCopyAsync(entityEvents);
+            }
+        }
+
+        public async Task<PagedResult<IEvent>> GetManyByCipherAsync(Cipher cipher, DateTime startDate, DateTime endDate, PageOptions pageOptions)
+        {
+            DateTime? beforeDate = null;
+            if (!string.IsNullOrWhiteSpace(pageOptions.ContinuationToken) &&
+                long.TryParse(pageOptions.ContinuationToken, out var binaryDate))
+            {
+                beforeDate = DateTime.SpecifyKind(DateTime.FromBinary(binaryDate), DateTimeKind.Utc);
+            }
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new EventReadPageByCipherIdQuery(cipher, startDate, endDate, beforeDate, pageOptions);
+                var events = await query.Run(dbContext).ToListAsync();
+
+                var result = new PagedResult<IEvent>();
+                if (events.Any() && events.Count >= pageOptions.PageSize)
+                {
+                    result.ContinuationToken = events.Last().Date.ToBinary().ToString();
+                }
+                result.Data.AddRange(events);
+                return result;
+            }
+        }
+
+
+        public async Task<PagedResult<IEvent>> GetManyByOrganizationActingUserAsync(Guid organizationId, Guid actingUserId, DateTime startDate, DateTime endDate, PageOptions pageOptions)
+        {
+            DateTime? beforeDate = null;
+            if (!string.IsNullOrWhiteSpace(pageOptions.ContinuationToken) &&
+                long.TryParse(pageOptions.ContinuationToken, out var binaryDate))
+            {
+                beforeDate = DateTime.SpecifyKind(DateTime.FromBinary(binaryDate), DateTimeKind.Utc);
+            }
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new EventReadPageByOrganizationIdActingUserIdQuery(organizationId, actingUserId,
+                    startDate, endDate, beforeDate, pageOptions);
+                var events = await query.Run(dbContext).ToListAsync();
+
+                var result = new PagedResult<IEvent>();
+                if (events.Any() && events.Count >= pageOptions.PageSize)
+                {
+                    result.ContinuationToken = events.Last().Date.ToBinary().ToString();
+                }
+                result.Data.AddRange(events);
+                return result;
+            }
+        }
+
+        public async Task<PagedResult<IEvent>> GetManyByOrganizationAsync(Guid organizationId, DateTime startDate, DateTime endDate, PageOptions pageOptions)
+        {
+            DateTime? beforeDate = null;
+            if (!string.IsNullOrWhiteSpace(pageOptions.ContinuationToken) &&
+                long.TryParse(pageOptions.ContinuationToken, out var binaryDate))
+            {
+                beforeDate = DateTime.SpecifyKind(DateTime.FromBinary(binaryDate), DateTimeKind.Utc);
+            }
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new EventReadPageByOrganizationIdQuery(organizationId, startDate,
+                    endDate, beforeDate, pageOptions);
+                var events = await query.Run(dbContext).ToListAsync();
+
+                var result = new PagedResult<IEvent>();
+                if (events.Any() && events.Count >= pageOptions.PageSize)
+                {
+                    result.ContinuationToken = events.Last().Date.ToBinary().ToString();
+                }
+                result.Data.AddRange(events);
+                return result;
+            }
+        }
+
+        public async Task<PagedResult<IEvent>> GetManyByUserAsync(Guid userId, DateTime startDate, DateTime endDate, PageOptions pageOptions)
+        {
+            DateTime? beforeDate = null;
+            if (!string.IsNullOrWhiteSpace(pageOptions.ContinuationToken) &&
+                long.TryParse(pageOptions.ContinuationToken, out var binaryDate))
+            {
+                beforeDate = DateTime.SpecifyKind(DateTime.FromBinary(binaryDate), DateTimeKind.Utc);
+            }
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new EventReadPageByUserIdQuery(userId, startDate,
+                    endDate, beforeDate, pageOptions);
+                var events = await query.Run(dbContext).ToListAsync();
+
+                var result = new PagedResult<IEvent>();
+                if (events.Any() && events.Count >= pageOptions.PageSize)
+                {
+                    result.ContinuationToken = events.Last().Date.ToBinary().ToString();
+                }
+                result.Data.AddRange(events);
+                return result;
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/FolderRepository.cs b/src/Core/Repositories/EntityFramework/FolderRepository.cs
new file mode 100644
index 0000000000..823491f351
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/FolderRepository.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Table;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class FolderRepository : Repository<TableModel.Folder, EfModel.Folder, Guid>, IFolderRepository
+    {
+        public FolderRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Folders)
+        { }
+
+        public async Task<Folder> GetByIdAsync(Guid id, Guid userId)
+        {
+            var folder = await base.GetByIdAsync(id);
+            if (folder == null || folder.UserId != userId)
+            {
+                return null;
+            }
+
+            return folder;
+        }
+
+        public async Task<ICollection<Folder>> GetManyByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from f in dbContext.Folders
+                    where f.UserId == userId
+                    select f;
+                var folders = await query.ToListAsync();
+                return Mapper.Map<List<TableModel.Folder>>(folders);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/GrantRepository.cs b/src/Core/Repositories/EntityFramework/GrantRepository.cs
new file mode 100644
index 0000000000..a71aff2272
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/GrantRepository.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Table;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class GrantRepository : BaseEntityFrameworkRepository, IGrantRepository
+    {
+        public GrantRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper)
+        { }
+
+        public async Task DeleteByKeyAsync(string key)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from g in dbContext.Grants
+                    where g.Key == key
+                    select g;
+                dbContext.Remove(query);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task DeleteManyAsync(string subjectId, string sessionId, string clientId, string type)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from g in dbContext.Grants
+                    where g.SubjectId == subjectId &&
+                        g.ClientId == clientId && 
+                        g.SessionId == sessionId &&
+                        g.Type == type
+                    select g;
+                dbContext.Remove(query);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task<Grant> GetByKeyAsync(string key)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from g in dbContext.Grants
+                    where g.Key == key
+                    select g;
+                var grant = await query.FirstOrDefaultAsync();
+                return grant;
+            }
+        }
+
+        public async Task<ICollection<Grant>> GetManyAsync(string subjectId, string sessionId, string clientId, string type)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from g in dbContext.Grants
+                    where g.SubjectId == subjectId &&
+                        g.ClientId == clientId && 
+                        g.SessionId == sessionId &&
+                        g.Type == type
+                    select g;
+                var grants = await query.ToListAsync();
+                return (ICollection<Grant>)grants;
+            }
+        }
+
+        public async Task SaveAsync(Grant obj)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var existingGrant = await (from g in dbContext.Grants
+                    where g.Key == obj.Key
+                    select g).FirstOrDefaultAsync();
+                if (existingGrant != null)
+                {
+                    dbContext.Entry(existingGrant).CurrentValues.SetValues(obj);
+                }
+                else
+                {
+                    var entity = Mapper.Map<EfModel.Grant>(obj);
+                    await dbContext.AddAsync(entity);
+                    await dbContext.SaveChangesAsync();
+                }
+            }
+        }
+    }
+}
+
diff --git a/src/Core/Repositories/EntityFramework/GroupRepository.cs b/src/Core/Repositories/EntityFramework/GroupRepository.cs
new file mode 100644
index 0000000000..863e3ae6e8
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/GroupRepository.cs
@@ -0,0 +1,174 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Data;
+using Bit.Core.Models.Table;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class GroupRepository : Repository<TableModel.Group, EfModel.Group, Guid>, IGroupRepository
+    {
+        public GroupRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Groups)
+        { }
+
+        public async Task CreateAsync(Group obj, IEnumerable<SelectionReadOnly> collections)
+        {
+            var grp = await base.CreateAsync(obj);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var availibleCollections = await (
+                    from c in dbContext.Collections
+                    where c.OrganizationId == grp.OrganizationId
+                    select c).ToListAsync();
+                var filteredCollections = collections.Where(c => availibleCollections.Any(a => c.Id == a.Id));
+                var collectionGroups = filteredCollections.Select(y => new EfModel.CollectionGroup
+                {
+                    CollectionId = y.Id,
+                    GroupId = grp.Id,
+                    ReadOnly = y.ReadOnly,
+                    HidePasswords = y.HidePasswords,
+                });
+                await dbContext.CollectionGroups.AddRangeAsync(collectionGroups);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task DeleteUserAsync(Guid groupId, Guid organizationUserId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from gu in dbContext.GroupUsers
+                    where gu.GroupId == groupId &&
+                        gu.OrganizationUserId == organizationUserId
+                    select gu;
+                dbContext.RemoveRange(await query.ToListAsync());
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task<Tuple<Group, ICollection<SelectionReadOnly>>> GetByIdWithCollectionsAsync(Guid id)
+        {
+            var grp = await base.GetByIdAsync(id);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = await ( 
+                    from cg in dbContext.CollectionGroups
+                    where cg.GroupId == id
+                    select cg).ToListAsync();
+                var collections = query.Select(c => new SelectionReadOnly
+                {
+                    Id = c.CollectionId,
+                    ReadOnly = c.ReadOnly,
+                    HidePasswords = c.HidePasswords,
+                }).ToList(); 
+                return new Tuple<Group, ICollection<SelectionReadOnly>>(
+                    grp, collections);
+            }
+        }
+
+        public async Task<ICollection<Group>> GetManyByOrganizationIdAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var data = await (
+                    from g in dbContext.Groups
+                    where g.OrganizationId == organizationId
+                    select g).ToListAsync();
+                return Mapper.Map<List<TableModel.Group>>(data);
+            }
+        }
+
+        public async Task<ICollection<GroupUser>> GetManyGroupUsersByOrganizationIdAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query =
+                    from gu in dbContext.GroupUsers
+                    join g in dbContext.Groups
+                        on gu.GroupId equals g.Id
+                    where g.OrganizationId == organizationId
+                    select gu;
+                var groupUsers = await query.ToListAsync();
+                return Mapper.Map<List<TableModel.GroupUser>>(groupUsers);
+            }
+        }
+
+        public async Task<ICollection<Guid>> GetManyIdsByUserIdAsync(Guid organizationUserId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query =
+                    from gu in dbContext.GroupUsers
+                    where gu.OrganizationUserId == organizationUserId
+                    select gu;
+                var groupIds = await query.Select(x => x.GroupId).ToListAsync();
+                return groupIds;
+            }
+        }
+
+        public async Task<ICollection<Guid>> GetManyUserIdsByIdAsync(Guid id)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query =
+                    from gu in dbContext.GroupUsers
+                    where gu.GroupId == id
+                    select gu;
+                var groupIds = await query.Select(x => x.OrganizationUserId).ToListAsync();
+                return groupIds;
+            }
+        }
+
+        public async Task ReplaceAsync(Group obj, IEnumerable<SelectionReadOnly> collections)
+        {
+            await base.ReplaceAsync(obj);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                await UserBumpAccountRevisionDateByOrganizationId(obj.OrganizationId);
+            }
+        }
+
+        public async Task UpdateUsersAsync(Guid groupId, IEnumerable<Guid> organizationUserIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var orgId = (await dbContext.Groups.FindAsync(groupId)).OrganizationId;
+                var insert = from ou in dbContext.OrganizationUsers
+                    where organizationUserIds.Contains(ou.Id) &&
+                        ou.OrganizationId == orgId &&
+                        !dbContext.GroupUsers.Any(gu => gu.GroupId == groupId && ou.Id == gu.OrganizationUserId)
+                    select new EfModel.GroupUser
+                    {
+                        GroupId = groupId,
+                        OrganizationUserId = ou.Id,
+                    };
+               await dbContext.AddRangeAsync(insert);
+
+               var delete = from gu in dbContext.GroupUsers
+                    where gu.GroupId == groupId &&
+                    !organizationUserIds.Contains(gu.OrganizationUserId)
+                    select gu;
+               dbContext.RemoveRange(delete);
+               await dbContext.SaveChangesAsync();
+               await UserBumpAccountRevisionDateByOrganizationId(orgId);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/InstallationRepository.cs b/src/Core/Repositories/EntityFramework/InstallationRepository.cs
new file mode 100644
index 0000000000..f28e7cd2be
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/InstallationRepository.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class InstallationRepository : Repository<TableModel.Installation, EfModel.Installation, Guid>, IInstallationRepository
+    {
+        public InstallationRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Installations)
+        { }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/MaintenanceRepository.cs b/src/Core/Repositories/EntityFramework/MaintenanceRepository.cs
new file mode 100644
index 0000000000..9ad8e85144
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/MaintenanceRepository.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Microsoft.Extensions.DependencyInjection;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class MaintenanceRepository : BaseEntityFrameworkRepository, IMaintenanceRepository
+    {
+        public MaintenanceRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper)
+        { }
+
+        public async Task DeleteExpiredGrantsAsync()
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from g in dbContext.Grants
+                            where g.ExpirationDate < DateTime.UtcNow
+                            select g;
+                dbContext.RemoveRange(query);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public Task DisableCipherAutoStatsAsync()
+        {
+            return Task.CompletedTask;
+        }
+
+        public Task RebuildIndexesAsync()
+        {
+            return Task.CompletedTask;
+        }
+
+        public Task UpdateStatisticsAsync()
+        {
+            return Task.CompletedTask;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/OrganizationRepository.cs b/src/Core/Repositories/EntityFramework/OrganizationRepository.cs
index 47bae92fef..2f7c5781d5 100644
--- a/src/Core/Repositories/EntityFramework/OrganizationRepository.cs
+++ b/src/Core/Repositories/EntityFramework/OrganizationRepository.cs
@@ -1,14 +1,14 @@
-using System;
-using System.Threading.Tasks;
-using TableModel = Bit.Core.Models.Table;
+using AutoMapper;
+using Bit.Core.Models.Table;
 using DataModel = Bit.Core.Models.Data;
 using EFModel = Bit.Core.Models.EntityFramework;
-using System.Linq;
-using System.Collections.Generic;
-using AutoMapper;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection;
-using Bit.Core.Models.Table;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System;
+using TableModel = Bit.Core.Models.Table;
 
 namespace Bit.Core.Repositories.EntityFramework
 {
@@ -40,48 +40,35 @@ namespace Bit.Core.Repositories.EntityFramework
         }
 
         public async Task<ICollection<TableModel.Organization>> GetManyByUserIdAsync(Guid userId)
-        {
-            // TODO
-            return await Task.FromResult(null as ICollection<TableModel.Organization>);
-        }
-
-        public async Task<ICollection<TableModel.Organization>> SearchAsync(string name, string userEmail, bool? paid,
-            int skip, int take)
         {
             using (var scope = ServiceScopeFactory.CreateScope())
             {
                 var dbContext = GetDatabaseContext(scope);
-                // TODO: more filters
                 var organizations = await GetDbSet(dbContext)
-                .Where(e => name == null || e.Name.StartsWith(name))
-                .OrderBy(e => e.Name)
-                .Skip(skip).Take(take)
-                .ToListAsync();
+                    .Select(e => e.OrganizationUsers
+                        .Where(ou => ou.UserId == userId)
+                        .Select(ou => ou.Organization))
+                    .ToListAsync();
                 return Mapper.Map<List<TableModel.Organization>>(organizations);
             }
         }
 
-        public async Task UpdateStorageAsync(Guid id)
+        public async Task<ICollection<TableModel.Organization>> SearchAsync(string name, string userEmail,
+            bool? paid, int skip, int take)
         {
             using (var scope = ServiceScopeFactory.CreateScope())
             {
                 var dbContext = GetDatabaseContext(scope);
-                var ciphers = await dbContext.Ciphers
-                    .Where(e => e.UserId == null && e.OrganizationId == id).ToListAsync();
-                var storage = ciphers.Sum(e => e.AttachmentsJson?.RootElement.EnumerateArray()
-                    .Sum(p => p.GetProperty("Size").GetInt64()) ?? 0);
-                var organization = new EFModel.Organization
-                {
-                    Id = id,
-                    RevisionDate = DateTime.UtcNow,
-                    Storage = storage,
-                };
-                var set = GetDbSet(dbContext);
-                set.Attach(organization);
-                var entry = dbContext.Entry(organization);
-                entry.Property(e => e.RevisionDate).IsModified = true;
-                entry.Property(e => e.Storage).IsModified = true;
-                await dbContext.SaveChangesAsync();
+                var organizations = await GetDbSet(dbContext)
+                    .Where(e => name == null || e.Name.Contains(name))
+                    .Where(e => userEmail == null || e.OrganizationUsers.Any(u => u.Email == userEmail))
+                    .Where(e => paid == null || 
+                            (paid == true && !string.IsNullOrWhiteSpace(e.GatewaySubscriptionId)) ||
+                            (paid == false && e.GatewaySubscriptionId == null))
+                    .OrderBy(e => e.CreationDate)
+                    .Skip(skip).Take(take)
+                    .ToListAsync();
+                return Mapper.Map<List<TableModel.Organization>>(organizations);
             }
         }
 
@@ -103,5 +90,10 @@ namespace Bit.Core.Repositories.EntityFramework
                 }).ToListAsync();
             }
         }
+
+        public async Task UpdateStorageAsync(Guid id)
+        {
+            await OrganizationUpdateStorage(id);
+        }
     }
 }
diff --git a/src/Core/Repositories/EntityFramework/OrganizationUserRepository.cs b/src/Core/Repositories/EntityFramework/OrganizationUserRepository.cs
new file mode 100644
index 0000000000..5175cb27eb
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/OrganizationUserRepository.cs
@@ -0,0 +1,393 @@
+using AutoMapper;
+using Bit.Core.Enums;
+using Bit.Core.Models.Data;
+using Bit.Core.Models.Table;
+using Bit.Core.Repositories.EntityFramework.Queries;
+using EfModel = Bit.Core.Models.EntityFramework;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class OrganizationUserRepository : Repository<TableModel.OrganizationUser, EfModel.OrganizationUser, Guid>, IOrganizationUserRepository
+    {
+        public OrganizationUserRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.OrganizationUsers)
+        { }
+
+        public async Task CreateAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections)
+        {
+            var organizationUser = await base.CreateAsync(obj);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var availibleCollections = await (
+                    from c in dbContext.Collections
+                    where c.OrganizationId == organizationUser.OrganizationId
+                    select c).ToListAsync();
+                var filteredCollections = collections.Where(c => availibleCollections.Any(a => c.Id == a.Id));
+                var collectionUsers = filteredCollections.Select(y => new EfModel.CollectionUser
+                {
+                    CollectionId = y.Id,
+                    OrganizationUserId = organizationUser.Id,
+                    ReadOnly = y.ReadOnly,
+                    HidePasswords = y.HidePasswords,
+                });
+                await dbContext.CollectionUsers.AddRangeAsync(collectionUsers);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task CreateManyAsync(IEnumerable<OrganizationUser> organizationUsers)
+        {
+            if (!organizationUsers.Any())
+            {
+                return;
+            }
+
+            foreach (var organizationUser in organizationUsers)
+            {
+                organizationUser.SetNewId();
+            }
+
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entities = Mapper.Map<List<EfModel.OrganizationUser>>(organizationUsers);
+                await dbContext.AddRangeAsync(entities);
+            }
+        }
+
+        public async Task DeleteManyAsync(IEnumerable<Guid> organizationUserIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entities = dbContext.FindAsync<EfModel.OrganizationUser>(organizationUserIds);
+                dbContext.RemoveRange(entities);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task<Tuple<OrganizationUser, ICollection<SelectionReadOnly>>> GetByIdWithCollectionsAsync(Guid id)
+        {
+            var organizationUser = await base.GetByIdAsync(id);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = await (
+                    from ou in dbContext.OrganizationUsers
+                    join cu in dbContext.CollectionUsers
+                        on ou.Id equals cu.OrganizationUserId
+                    where !ou.AccessAll && 
+                        ou.Id == id
+                    select cu).ToListAsync();
+                var collections = query.Select(cu => new SelectionReadOnly
+                {
+                    Id = cu.CollectionId,
+                    ReadOnly = cu.ReadOnly,
+                    HidePasswords = cu.HidePasswords,
+                }); 
+                return new Tuple<OrganizationUser, ICollection<SelectionReadOnly>>(
+                    organizationUser, collections.ToList());
+            }
+        }
+
+        public async Task<OrganizationUser> GetByOrganizationAsync(Guid organizationId, Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entity = await GetDbSet(dbContext)
+                    .FirstOrDefaultAsync(e => e.OrganizationId == organizationId && e.UserId == userId);
+                return entity;
+            }
+        }
+
+        public async Task<OrganizationUser> GetByOrganizationEmailAsync(Guid organizationId, string email)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entity = await GetDbSet(dbContext)
+                    .FirstOrDefaultAsync(ou => ou.OrganizationId == organizationId &&
+                        !string.IsNullOrWhiteSpace(ou.Email) &&
+                        ou.Email == email);
+                return entity;
+            }
+        }
+
+        public async Task<int> GetCountByFreeOrganizationAdminUserAsync(Guid userId)
+        {
+            var query = new OrganizationUserReadCountByFreeOrganizationAdminUserQuery(userId);
+            return await GetCountFromQuery(query);
+        }
+
+        public async Task<int> GetCountByOnlyOwnerAsync(Guid userId)
+        {
+            var query = new OrganizationUserReadCountByOnlyOwnerQuery(userId);
+            return await GetCountFromQuery(query);
+        }
+
+        public async Task<int> GetCountByOrganizationAsync(Guid organizationId, string email, bool onlyRegisteredUsers)
+        {
+            var query = new OrganizationUserReadCountByOrganizationIdEmailQuery(organizationId, email, onlyRegisteredUsers);
+            return await GetCountFromQuery(query);
+        }
+
+        public async Task<int> GetCountByOrganizationIdAsync(Guid organizationId)
+        {
+            var query = new OrganizationUserReadCountByOrganizationIdQuery(organizationId);
+            return await GetCountFromQuery(query);
+        }
+
+        public async Task<OrganizationUserUserDetails> GetDetailsByIdAsync(Guid id)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = new OrganizationUserUserDetailsViewQuery();
+                var entity = await view.Run(dbContext).FirstOrDefaultAsync(ou => ou.Id == id);
+                return entity;
+            }
+        }
+
+        public async Task<Tuple<OrganizationUserUserDetails, ICollection<SelectionReadOnly>>> GetDetailsByIdWithCollectionsAsync(Guid id)
+        {
+            var organizationUserUserDetails = await GetDetailsByIdAsync(id);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from ou in dbContext.OrganizationUsers
+                    join cu in dbContext.CollectionUsers on ou.Id equals cu.OrganizationUserId
+                    where !ou.AccessAll && ou.Id == id
+                    select cu;
+                var collections = await query.Select(cu => new SelectionReadOnly
+                {
+                   Id = cu.CollectionId,
+                   ReadOnly = cu.ReadOnly,
+                   HidePasswords = cu.HidePasswords,
+                }).ToListAsync();
+                return new Tuple<OrganizationUserUserDetails, ICollection<SelectionReadOnly>>(organizationUserUserDetails, collections);
+            }
+        }
+
+        public async Task<OrganizationUserOrganizationDetails> GetDetailsByUserAsync(Guid userId, Guid organizationId, OrganizationUserStatusType? status = null)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = new OrganizationUserOrganizationDetailsViewQuery();
+                var t = await (view.Run(dbContext)).ToArrayAsync();
+                var entity = await view.Run(dbContext)
+                    .FirstOrDefaultAsync(o => o.UserId == userId && 
+                        o.OrganizationId == organizationId && 
+                        (status == null || o.Status == status));
+                return entity;
+            }
+        }
+
+        public async Task<ICollection<OrganizationUser>> GetManyAsync(IEnumerable<Guid> Ids)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from ou in dbContext.OrganizationUsers
+                    where Ids.Contains(ou.Id)
+                    select ou;
+                var data = await query.ToArrayAsync();
+                return data;
+            }
+        }
+
+        public async Task<ICollection<OrganizationUser>> GetManyByManyUsersAsync(IEnumerable<Guid> userIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from ou in dbContext.OrganizationUsers
+                    where userIds.Contains(ou.Id)
+                    select ou;
+                return Mapper.Map<List<TableModel.OrganizationUser>>(await query.ToListAsync());
+            }
+        }
+
+        public async Task<ICollection<OrganizationUser>> GetManyByOrganizationAsync(Guid organizationId, OrganizationUserType? type)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from ou in dbContext.OrganizationUsers
+                    where ou.OrganizationId == organizationId &&
+                        (type == null || ou.Type == type)
+                    select ou;
+                return Mapper.Map<List<TableModel.OrganizationUser>>(await query.ToListAsync());
+            }
+        }
+
+        public async Task<ICollection<OrganizationUser>> GetManyByUserAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from ou in dbContext.OrganizationUsers
+                    where ou.UserId == userId
+                    select ou;
+                return Mapper.Map<List<TableModel.OrganizationUser>>(await query.ToListAsync());
+            }
+        }
+
+        public async Task<ICollection<OrganizationUserUserDetails>> GetManyDetailsByOrganizationAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = new OrganizationUserUserDetailsViewQuery();
+                var query = from ou in view.Run(dbContext)
+                    where ou.OrganizationId == organizationId
+                    select ou;
+                return await query.ToListAsync();
+            }
+        }
+
+        public async Task<ICollection<OrganizationUserOrganizationDetails>> GetManyDetailsByUserAsync(Guid userId,
+                OrganizationUserStatusType? status = null)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = new OrganizationUserOrganizationDetailsViewQuery();
+                var query = from ou in view.Run(dbContext)
+                    where ou.UserId == userId &&
+                    (status == null || ou.Status == status)
+                    select ou;
+                var organizationUsers = await query.ToListAsync();
+                return organizationUsers;
+            }
+        }
+
+        public async Task<IEnumerable<OrganizationUserPublicKey>> GetManyPublicKeysByOrganizationUserAsync(Guid organizationId, IEnumerable<Guid> Ids)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from ou in dbContext.OrganizationUsers
+                    where Ids.Contains(ou.Id) && ou.Status == OrganizationUserStatusType.Accepted
+                    join u in dbContext.Users
+                        on ou.UserId equals u.Id
+                    where ou.OrganizationId == organizationId
+                    select new { ou, u };
+                var data = await query
+                    .Select(x => new OrganizationUserPublicKey() 
+                    {
+                       Id = x.ou.Id,
+                       PublicKey = x.u.PublicKey,
+                    }).ToListAsync();
+                return data;
+            }
+        }
+
+        public async Task ReplaceAsync(OrganizationUser obj, IEnumerable<SelectionReadOnly> collections)
+        {
+            await base.ReplaceAsync(obj);
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+
+                var procedure = new OrganizationUserUpdateWithCollectionsQuery(obj, collections);
+
+                var update = procedure.Update.Run(dbContext);
+                dbContext.UpdateRange(await update.ToListAsync());
+
+                var insert = procedure.Insert.Run(dbContext);
+                await dbContext.AddRangeAsync(await insert.ToListAsync());
+
+                dbContext.RemoveRange(await procedure.Delete.Run(dbContext).ToListAsync()); 
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task ReplaceManyAsync(IEnumerable<OrganizationUser> organizationUsers)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                dbContext.UpdateRange(organizationUsers);
+                await dbContext.SaveChangesAsync();
+                await UserBumpManyAccountRevisionDates(organizationUsers
+                    .Where(ou => ou.UserId.HasValue)
+                    .Select(ou => ou.UserId.Value).ToArray());
+            }
+        }
+
+        public async Task<IEnumerable<string>> SelectKnownEmailsAsync(Guid organizationId, IEnumerable<string> emails, bool onlyRegisteredUsers)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var usersQuery = from ou in dbContext.OrganizationUsers
+                    join u in dbContext.Users
+                        on ou.UserId equals u.Id into u_g
+                    from u in u_g
+                    where ou.OrganizationId == organizationId
+                    select new { ou, u };
+                var ouu = await usersQuery.ToListAsync();
+                var ouEmails = ouu.Select(x => x.ou.Email);
+                var uEmails = ouu.Select(x => x.u.Email);
+                var knownEmails = from e in emails
+                    where (ouEmails.Contains(e) || uEmails.Contains(e)) &&
+                    (!onlyRegisteredUsers && (uEmails.Contains(e) || ouEmails.Contains(e))) ||
+                    (onlyRegisteredUsers && uEmails.Contains(e))
+                    select e;
+                return knownEmails;
+            }
+        }
+
+        public async Task UpdateGroupsAsync(Guid orgUserId, IEnumerable<Guid> groupIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+
+                var procedure = new GroupUserUpdateGroupsQuery(orgUserId, groupIds);
+
+                var insert = procedure.Insert.Run(dbContext);
+                var data = await insert.ToListAsync();
+                await dbContext.AddRangeAsync(data);
+
+                var delete = procedure.Delete.Run(dbContext);
+                var deleteData = await delete.ToListAsync();
+                dbContext.RemoveRange(deleteData); 
+                await UserBumpAccountRevisionDateByOrganizationUserId(orgUserId);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task UpsertManyAsync(IEnumerable<OrganizationUser> organizationUsers)
+        {
+            var createUsers = new List<OrganizationUser>();
+            var replaceUsers = new List<OrganizationUser>();
+            foreach (var organizationUser in organizationUsers)
+            {
+                if (organizationUser.Id.Equals(default))
+                {
+                    createUsers.Add(organizationUser);
+                }
+                else
+                {
+                    replaceUsers.Add(organizationUser);
+                }
+            }
+
+            await CreateManyAsync(createUsers);
+            await ReplaceManyAsync(replaceUsers);
+        }
+
+        Task<ICollection<string>> IOrganizationUserRepository.SelectKnownEmailsAsync(Guid organizationId, IEnumerable<string> emails, bool onlyRegisteredUsers) => throw new NotImplementedException();
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/PolicyRepository.cs b/src/Core/Repositories/EntityFramework/PolicyRepository.cs
new file mode 100644
index 0000000000..8ad345000f
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/PolicyRepository.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Enums;
+using Bit.Core.Models.Table;
+using Bit.Core.Repositories.EntityFramework.Queries;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class PolicyRepository : Repository<TableModel.Policy, EfModel.Policy, Guid>, IPolicyRepository
+    {
+        public PolicyRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Policies)
+        { }
+
+        public async Task<Policy> GetByOrganizationIdTypeAsync(Guid organizationId, PolicyType type)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.Policies
+                    .FirstOrDefaultAsync(p => p.OrganizationId == organizationId && p.Type == type);
+                return Mapper.Map<TableModel.Policy>(results);
+            }
+        }
+
+        public async Task<ICollection<Policy>> GetManyByOrganizationIdAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.Policies
+                    .Where(p => p.OrganizationId == organizationId)
+                    .ToListAsync();
+                return Mapper.Map<List<TableModel.Policy>>(results);
+            }
+        }
+
+        public async Task<ICollection<Policy>> GetManyByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+
+                var query = new PolicyReadByUserIdQuery(userId);
+                var results = await query.Run(dbContext).ToListAsync();
+                return Mapper.Map<List<TableModel.Policy>>(results);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/ProviderOrganizationProviderUserRepository.cs b/src/Core/Repositories/EntityFramework/ProviderOrganizationProviderUserRepository.cs
new file mode 100644
index 0000000000..a468c4e31c
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/ProviderOrganizationProviderUserRepository.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Bit.Core.Models.Table.Provider;
+using Bit.Core.Repositories.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+using EfModel = Bit.Core.Models.EntityFramework;
+using Microsoft.Extensions.DependencyInjection;
+using AutoMapper;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class ProviderOrganizationProviderUserRepository : 
+        Repository<TableModel.Provider.ProviderOrganizationProviderUser, EfModel.Provider.ProviderOrganizationProviderUser, Guid>, IProviderOrganizationProviderUserRepository
+    {
+        public ProviderOrganizationProviderUserRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.ProviderOrganizationProviderUsers)
+        { }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/ProviderOrganizationRepository.cs b/src/Core/Repositories/EntityFramework/ProviderOrganizationRepository.cs
new file mode 100644
index 0000000000..6bce3cc190
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/ProviderOrganizationRepository.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Bit.Core.Models.Table.Provider;
+using Bit.Core.Repositories.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+using EfModel = Bit.Core.Models.EntityFramework;
+using Microsoft.Extensions.DependencyInjection;
+using AutoMapper;
+using Bit.Core.Models.Data;
+using Bit.Core.Repositories.EntityFramework.Queries;
+using Microsoft.EntityFrameworkCore;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class ProviderOrganizationRepository : 
+        Repository<TableModel.Provider.ProviderOrganization, EfModel.Provider.ProviderOrganization, Guid>, IProviderOrganizationRepository
+    {
+        public ProviderOrganizationRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.ProviderOrganizations)
+        { }
+
+        public async Task<ICollection<ProviderOrganizationOrganizationDetails>> GetManyDetailsByProviderAsync(Guid providerId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new ProviderOrganizationOrganizationDetailsReadByProviderIdQuery(providerId);
+                var data = await query.Run(dbContext).ToListAsync();
+                return data;
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/ProviderRepository.cs b/src/Core/Repositories/EntityFramework/ProviderRepository.cs
new file mode 100644
index 0000000000..1cb261ad4c
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/ProviderRepository.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Bit.Core.Models.Table.Provider;
+using Bit.Core.Repositories.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+using EfModel = Bit.Core.Models.EntityFramework;
+using Microsoft.Extensions.DependencyInjection;
+using AutoMapper;
+using Microsoft.EntityFrameworkCore;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class ProviderRepository : Repository<TableModel.Provider.Provider, EfModel.Provider.Provider, Guid>, IProviderRepository
+    {
+
+        public ProviderRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Providers)
+        { }
+
+        public Task<ICollection<ProviderAbility>> GetManyAbilitiesAsync() => throw new NotImplementedException();
+
+        public async Task<ICollection<Provider>> SearchAsync(string name, string userEmail, int skip, int take)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = !string.IsNullOrWhiteSpace(userEmail) ?
+                    (from p in dbContext.Providers
+                    join pu in dbContext.ProviderUsers
+                        on p.Id equals pu.ProviderId
+                    join u in dbContext.Users
+                        on pu.UserId equals u.Id
+                    where (string.IsNullOrWhiteSpace(name) || p.Name.Contains(name)) &&
+                        u.Email == userEmail
+                    orderby p.CreationDate descending
+                    select new { p, pu, u }).Skip(skip).Take(take).Select(x => x.p) :
+                    (from p in dbContext.Providers
+                    where string.IsNullOrWhiteSpace(name) || p.Name.Contains(name)
+                    orderby p.CreationDate descending
+                    select new { p }).Skip(skip).Take(take).Select(x => x.p);
+                return await query.ToArrayAsync();
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/ProviderUserRepository.cs b/src/Core/Repositories/EntityFramework/ProviderUserRepository.cs
new file mode 100644
index 0000000000..67c642b3c0
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/ProviderUserRepository.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Bit.Core.Models.Table.Provider;
+using TableModel = Bit.Core.Models.Table;
+using EfModel = Bit.Core.Models.EntityFramework;
+using Microsoft.Extensions.DependencyInjection;
+using AutoMapper;
+using Bit.Core.Enums.Provider;
+using Microsoft.EntityFrameworkCore;
+using Bit.Core.Models.Data;
+using Bit.Core.Repositories.EntityFramework.Queries;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class ProviderUserRepository : 
+        Repository<TableModel.Provider.ProviderUser, EfModel.Provider.ProviderUser, Guid>, IProviderUserRepository
+    {
+        public ProviderUserRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.ProviderUsers)
+        { }
+
+        public async Task<int> GetCountByProviderAsync(Guid providerId, string email, bool onlyRegisteredUsers)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from pu in dbContext.ProviderUsers
+                    join u in dbContext.Users
+                        on pu.UserId equals u.Id into u_g
+                    from u in u_g.DefaultIfEmpty()
+                    where pu.ProviderId == providerId &&
+                        ((!onlyRegisteredUsers && (pu.Email == email || u.Email == email)) ||
+                        (onlyRegisteredUsers && u.Email == email))
+                    select new { pu, u };
+                return await query.CountAsync();
+            }
+        }
+
+        public async Task<ICollection<ProviderUser>> GetManyAsync(IEnumerable<Guid> ids)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = dbContext.ProviderUsers.Where(item => ids.Contains(item.Id));
+                return await query.ToArrayAsync();
+            }
+        }
+
+        public async Task<ICollection<ProviderUser>> GetManyByProviderAsync(Guid providerId, ProviderUserType? type = null)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = dbContext.ProviderUsers.Where(pu => pu.ProviderId.Equals(providerId) && 
+                    (type != null && pu.Type.Equals(type)));
+                return await query.ToArrayAsync();
+            }
+        }
+
+        public async Task DeleteManyAsync(IEnumerable<Guid> providerUserIds)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                await UserBumpAccountRevisionDateByProviderUserIds(providerUserIds.ToArray());
+                var entities = dbContext.ProviderUsers.Where(pu => providerUserIds.Contains(pu.Id));
+                dbContext.ProviderUsers.RemoveRange(entities);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task<ICollection<ProviderUser>> GetManyByUserAsync(Guid userId) 
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from pu in dbContext.ProviderUsers
+                    where pu.UserId == userId
+                    select pu;
+                return await query.ToArrayAsync();
+            }
+        }
+        public async Task<ProviderUser> GetByProviderUserAsync(Guid providerId, Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = from pu in dbContext.ProviderUsers
+                    where pu.UserId == userId &&
+                        pu.ProviderId == providerId
+                    select pu;
+                return await query.FirstOrDefaultAsync();
+            }
+        }
+        public async Task<ICollection<ProviderUserUserDetails>> GetManyDetailsByProviderAsync(Guid providerId) 
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var view = from pu in dbContext.ProviderUsers
+                    join u in dbContext.Users
+                        on pu.UserId equals u.Id into u_g
+                    from u in u_g.DefaultIfEmpty()
+                    select new {pu, u};
+                var data = await view.Where(e => e.pu.ProviderId == providerId).Select(e => new ProviderUserUserDetails 
+                {
+                    Id = e.pu.Id,
+                    UserId = e.pu.UserId,
+                    ProviderId = e.pu.ProviderId,
+                    Name = e.u.Name,
+                    Email = e.u.Email ?? e.pu.Email,
+                    Status = e.pu.Status,
+                    Type = e.pu.Type,
+                    Permissions = e.pu.Permissions,
+                }).ToArrayAsync();
+                return data;
+            }
+        }
+
+        public async Task<ICollection<ProviderUserProviderDetails>> GetManyDetailsByUserAsync(Guid userId, ProviderUserStatusType? status = null)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new ProviderUserProviderDetailsReadByUserIdStatusQuery(userId, status);
+                var data = await query.Run(dbContext).ToArrayAsync();
+                return data;
+            }
+        }
+
+        public async Task<IEnumerable<ProviderUserPublicKey>> GetManyPublicKeysByProviderUserAsync(Guid providerId, IEnumerable<Guid> Ids) 
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var query = new UserReadPublicKeysByProviderUserIdsQuery(providerId, Ids);
+                var data = await query.Run(dbContext).ToListAsync();
+                return data;
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/CipherDetailsQuery.cs b/src/Core/Repositories/EntityFramework/Queries/CipherDetailsQuery.cs
new file mode 100644
index 0000000000..761dc7471a
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/CipherDetailsQuery.cs
@@ -0,0 +1,40 @@
+using System.Linq;
+using System;
+using System.Collections.Generic;
+using Core.Models.Data;
+using Bit.Core.Utilities;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class CipherDetailsQuery : IQuery<CipherDetails>
+    {
+        private readonly Guid? _userId;
+        private readonly bool _ignoreFolders;
+        public CipherDetailsQuery(Guid? userId, bool ignoreFolders = false)
+        {
+            _userId = userId;
+            _ignoreFolders = ignoreFolders;
+        }
+        public virtual IQueryable<CipherDetails> Run(DatabaseContext dbContext)
+        {
+            var query = from c in dbContext.Ciphers
+                select new CipherDetails 
+                { 
+                    Id = c.Id,
+                    UserId = c.UserId,
+                    OrganizationId = c.OrganizationId,
+                    Type= c.Type,
+                    Data = c.Data,
+                    Attachments = c.Attachments,
+                    CreationDate = c.CreationDate,
+                    RevisionDate = c.RevisionDate,
+                    DeletedDate = c.DeletedDate,
+                    Favorite = _userId.HasValue && c.Favorites != null && c.Favorites.Contains($"\"{_userId}\":true"),
+                    FolderId = (_ignoreFolders || !_userId.HasValue || c.Folders == null || !c.Folders.Contains(_userId.Value.ToString())) ? 
+                        null : 
+                        CoreHelpers.LoadClassFromJsonData<Dictionary<Guid, Guid>>(c.Folders)[_userId.Value],
+                };
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/CipherOrganizationDetailsReadByIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/CipherOrganizationDetailsReadByIdQuery.cs
new file mode 100644
index 0000000000..52566c9e2a
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/CipherOrganizationDetailsReadByIdQuery.cs
@@ -0,0 +1,41 @@
+using System.Linq;
+using System;
+using Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class CipherOrganizationDetailsReadByIdQuery : IQuery<CipherOrganizationDetails>
+    {
+        private readonly Guid _cipherId;
+
+        public CipherOrganizationDetailsReadByIdQuery(Guid cipherId)
+        {
+            _cipherId = cipherId;
+        }
+
+        public virtual IQueryable<CipherOrganizationDetails> Run(DatabaseContext dbContext)
+        {
+            var query = from c in dbContext.Ciphers
+                join o in dbContext.Organizations
+                    on c.OrganizationId equals o.Id into o_g
+                from o in o_g.DefaultIfEmpty()
+                where c.Id == _cipherId
+                select new CipherOrganizationDetails 
+                {  
+                    Id = c.Id,
+                    UserId = c.UserId,
+                    OrganizationId = c.OrganizationId,
+                    Type = c.Type,
+                    Data = c.Data,
+                    Favorites = c.Favorites,
+                    Folders = c.Folders,
+                    Attachments = c.Attachments,
+                    CreationDate = c.CreationDate,
+                    RevisionDate = c.RevisionDate,
+                    DeletedDate = c.DeletedDate, 
+                    OrganizationUseTotp = o.UseTotp,
+                };
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/CipherReadCanEditByIdUserIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/CipherReadCanEditByIdUserIdQuery.cs
new file mode 100644
index 0000000000..5187726b21
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/CipherReadCanEditByIdUserIdQuery.cs
@@ -0,0 +1,58 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+using Bit.Core.Enums;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class CipherReadCanEditByIdUserIdQuery : IQuery<Cipher>
+    {
+        private readonly Guid _userId;
+        private readonly Guid _cipherId;
+
+        public CipherReadCanEditByIdUserIdQuery(Guid userId, Guid cipherId)
+        {
+            _userId = userId;
+            _cipherId = cipherId;
+        }
+
+        public virtual IQueryable<Cipher> Run(DatabaseContext dbContext)
+        {
+            var query = from c in dbContext.Ciphers
+                join o in dbContext.Organizations
+                    on c.OrganizationId equals o.Id into o_g
+                from o in o_g.DefaultIfEmpty()
+                where !c.UserId.HasValue
+                join ou in dbContext.OrganizationUsers
+                    on o.Id equals ou.OrganizationId into ou_g
+                from ou in ou_g.DefaultIfEmpty()
+                where ou.UserId == _userId
+                join cc in dbContext.CollectionCiphers
+                    on c.Id equals cc.CipherId into cc_g
+                from cc in cc_g.DefaultIfEmpty()
+                where !c.UserId.HasValue && !ou.AccessAll
+                join cu in dbContext.CollectionUsers
+                    on cc.CollectionId equals cu.CollectionId into cu_g
+                from cu in cu_g.DefaultIfEmpty()
+                where ou.Id == cu.OrganizationUserId
+                join gu in dbContext.GroupUsers
+                    on ou.Id equals gu.OrganizationUserId into gu_g
+                from gu in gu_g.DefaultIfEmpty()
+                where !c.UserId.HasValue  && cu.CollectionId == null && !ou.AccessAll
+                join g in dbContext.Groups
+                    on gu.GroupId equals g.Id into g_g
+                from g in g_g.DefaultIfEmpty()
+                join cg in dbContext.CollectionGroups
+                    on gu.GroupId equals cg.GroupId into cg_g
+                from cg in cg_g.DefaultIfEmpty()
+                where !g.AccessAll && cg.CollectionId == cc.CollectionId &&
+                (c.Id == _cipherId && 
+                (c.UserId == _userId || 
+                (!c.UserId.HasValue && ou.Status == OrganizationUserStatusType.Confirmed && o.Enabled &&
+                (ou.AccessAll || cu.CollectionId != null || g.AccessAll || cg.CollectionId != null)))) &&
+                (c.UserId.HasValue || ou.AccessAll || !cu.ReadOnly || g.AccessAll || !cg.ReadOnly)
+                select c;
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/CipherUpdateCollectionsQuery.cs b/src/Core/Repositories/EntityFramework/Queries/CipherUpdateCollectionsQuery.cs
new file mode 100644
index 0000000000..8c3fbd5078
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/CipherUpdateCollectionsQuery.cs
@@ -0,0 +1,69 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+using Bit.Core.Enums;
+using System.Collections.Generic;
+using Table = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class CipherUpdateCollectionsQuery : IQuery<CollectionCipher>
+    {
+        private readonly Table.Cipher _cipher;
+        private readonly IEnumerable<Guid> _collectionIds;
+
+        public CipherUpdateCollectionsQuery(Table.Cipher cipher, IEnumerable<Guid> collectionIds)
+        {
+            _cipher = cipher;
+            _collectionIds = collectionIds;
+        }
+
+        public virtual IQueryable<CollectionCipher> Run(DatabaseContext dbContext)
+        {
+            if (!_cipher.OrganizationId.HasValue || !_collectionIds.Any())
+            {
+                return null;
+            }
+
+            var availibleCollections = !_cipher.UserId.HasValue ?
+                from c in dbContext.Collections
+                where c.OrganizationId == _cipher.OrganizationId
+                select c.Id :
+                from c in dbContext.Collections
+                join o in dbContext.Organizations
+                    on c.OrganizationId equals o.Id
+                join ou in dbContext.OrganizationUsers
+                    on o.Id equals ou.OrganizationId
+                where ou.UserId == _cipher.UserId
+                join cu in dbContext.CollectionUsers
+                    on c.Id equals cu.CollectionId into cu_g
+                from cu in cu_g.DefaultIfEmpty()
+                where !ou.AccessAll && cu.OrganizationUserId == ou.Id
+                join gu in dbContext.GroupUsers
+                    on ou.Id equals gu.OrganizationUserId into gu_g
+                from gu in gu_g.DefaultIfEmpty()
+                where cu.CollectionId == null && !ou.AccessAll
+                join g in dbContext.Groups
+                    on gu.GroupId equals g.Id into g_g
+                from g in g_g.DefaultIfEmpty()
+                join cg in dbContext.CollectionGroups
+                    on c.Id equals cg.CollectionId into cg_g
+                from cg in cg_g.DefaultIfEmpty()
+                where !g.AccessAll && gu.GroupId == cg.GroupId &&
+                    o.Id == _cipher.OrganizationId &&
+                    o.Enabled &&
+                    ou.Status == OrganizationUserStatusType.Confirmed &&
+                    (ou.AccessAll || !cu.ReadOnly || g.AccessAll || !cg.ReadOnly)
+                select c.Id;
+
+            if (!availibleCollections.Any())
+            {
+                return null;
+            }
+
+            var query = from c in availibleCollections
+                        select new CollectionCipher { CollectionId = c, CipherId = _cipher.Id };
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/CollectionCipherReadByUserIdCipherIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/CollectionCipherReadByUserIdCipherIdQuery.cs
new file mode 100644
index 0000000000..00608b3fe4
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/CollectionCipherReadByUserIdCipherIdQuery.cs
@@ -0,0 +1,22 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class CollectionCipherReadByUserIdCipherIdQuery : CollectionCipherReadByUserIdQuery
+    {
+        private readonly Guid _cipherId;
+
+        public CollectionCipherReadByUserIdCipherIdQuery(Guid userId, Guid cipherId) : base(userId)
+        {
+            _cipherId = cipherId;
+        }
+
+        public override IQueryable<CollectionCipher> Run(DatabaseContext dbContext)
+        {
+            var query = base.Run(dbContext);
+            return query.Where(x => x.CipherId == _cipherId);
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/CollectionCipherReadByUserIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/CollectionCipherReadByUserIdQuery.cs
new file mode 100644
index 0000000000..2b1d0d0db7
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/CollectionCipherReadByUserIdQuery.cs
@@ -0,0 +1,46 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+using Bit.Core.Enums;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class CollectionCipherReadByUserIdQuery : IQuery<CollectionCipher>
+    {
+        private readonly Guid _userId;
+
+        public CollectionCipherReadByUserIdQuery(Guid userId)
+        {
+            _userId = userId;
+        }
+
+        public virtual IQueryable<CollectionCipher> Run(DatabaseContext dbContext)
+        {
+            var query = from cc in dbContext.CollectionCiphers
+                join c in dbContext.Collections 
+                    on cc.CollectionId equals c.Id
+                join ou in dbContext.OrganizationUsers
+                    on c.OrganizationId equals ou.OrganizationId
+                where ou.UserId == _userId
+                join cu in dbContext.CollectionUsers
+                    on c.Id equals cu.CollectionId into cu_g
+                from cu in cu_g
+                where ou.AccessAll && cu.OrganizationUserId == ou.Id
+                join gu in dbContext.GroupUsers
+                    on ou.Id equals gu.OrganizationUserId into gu_g
+                from gu in gu_g
+                where cu.CollectionId == null && !ou.AccessAll
+                join g in dbContext.Groups
+                    on gu.GroupId equals g.Id into g_g
+                from g in g_g
+                join cg in dbContext.CollectionGroups
+                    on cc.CollectionId equals cg.CollectionId into cg_g
+                from cg in cg_g
+                where g.AccessAll && cg.GroupId == gu.GroupId  &&
+                    ou.Status == OrganizationUserStatusType.Confirmed &&
+                    (ou.AccessAll || cu.CollectionId != null || g.AccessAll || cg.CollectionId != null)
+                select cc;
+                return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/CollectionReadCountByOrganizationIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/CollectionReadCountByOrganizationIdQuery.cs
new file mode 100644
index 0000000000..64f62682f1
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/CollectionReadCountByOrganizationIdQuery.cs
@@ -0,0 +1,24 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class CollectionReadCountByOrganizationIdQuery : IQuery<Collection>
+    {
+        private readonly Guid _organizationId;
+
+        public CollectionReadCountByOrganizationIdQuery(Guid organizationId)
+        {
+            _organizationId = organizationId;
+        }
+
+        public IQueryable<Collection> Run(DatabaseContext dbContext)
+        {
+            var query = from c in dbContext.Collections
+                where c.OrganizationId == _organizationId
+                select c;
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/CollectionUserUpdateUsersQuery.cs b/src/Core/Repositories/EntityFramework/Queries/CollectionUserUpdateUsersQuery.cs
new file mode 100644
index 0000000000..24b4ca9d17
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/CollectionUserUpdateUsersQuery.cs
@@ -0,0 +1,121 @@
+using System.Collections.Generic;
+using System.Linq;
+using EfModel = Bit.Core.Models.EntityFramework;
+using Bit.Core.Models.Data;
+using System;
+using System.Threading.Tasks;
+using Microsoft.EntityFrameworkCore;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class CollectionUserUpdateUsersQuery
+    {
+        public readonly CollectionUserUpdateUsersInsertQuery Insert;
+        public readonly CollectionUserUpdateUsersUpdateQuery Update;
+        public readonly CollectionUserUpdateUsersDeleteQuery Delete;
+
+        public CollectionUserUpdateUsersQuery(Guid collectionId, IEnumerable<SelectionReadOnly> users)
+        {
+            Insert  = new CollectionUserUpdateUsersInsertQuery(collectionId, users);
+            Update = new CollectionUserUpdateUsersUpdateQuery(collectionId, users);
+            Delete = new CollectionUserUpdateUsersDeleteQuery(collectionId, users);
+        }
+    }
+
+    public class CollectionUserUpdateUsersInsertQuery : IQuery<EfModel.OrganizationUser>
+    {
+        private readonly Guid _collectionId;
+        private readonly IEnumerable<SelectionReadOnly> _users;
+
+        public CollectionUserUpdateUsersInsertQuery(Guid collectionId, IEnumerable<SelectionReadOnly> users)
+        {
+            _collectionId = collectionId;
+            _users = users;
+        }
+
+        public IQueryable<EfModel.OrganizationUser> Run(DatabaseContext dbContext)
+        {
+            var orgId = dbContext.Collections.FirstOrDefault(c => c.Id == _collectionId)?.OrganizationId;
+            var organizationUserIds = _users.Select(u => u.Id);
+            var insertQuery = from ou in dbContext.OrganizationUsers
+                where 
+                    organizationUserIds.Contains(ou.Id) &&
+                    ou.OrganizationId == orgId &&
+                    !dbContext.CollectionUsers.Any(
+                        x => x.CollectionId != _collectionId && x.OrganizationUserId == ou.Id)
+                select ou;
+            return insertQuery;
+        }
+
+        public async Task<IEnumerable<EfModel.CollectionUser>> BuildInMemory(DatabaseContext dbContext)
+        {
+            var data = await Run(dbContext).ToListAsync();
+            var collectionUsers = data.Select(x => new EfModel.CollectionUser()
+            { 
+                CollectionId = _collectionId,
+                OrganizationUserId = x.Id,
+                ReadOnly = _users.FirstOrDefault(u => u.Id.Equals(x.Id)).ReadOnly,
+                HidePasswords = _users.FirstOrDefault(u => u.Id.Equals(x.Id)).HidePasswords,
+            });
+            return collectionUsers;
+        }
+    }
+
+    public class CollectionUserUpdateUsersUpdateQuery: IQuery<EfModel.CollectionUser>
+    {
+        private readonly Guid _collectionId;
+        private readonly IEnumerable<SelectionReadOnly> _users;
+
+        public CollectionUserUpdateUsersUpdateQuery(Guid collectionId, IEnumerable<SelectionReadOnly> users)
+        {
+            _collectionId = collectionId;
+            _users = users;
+        }
+
+        public IQueryable<EfModel.CollectionUser> Run(DatabaseContext dbContext)
+        {
+            var orgId = dbContext.Collections.FirstOrDefault(c => c.Id == _collectionId)?.OrganizationId;
+            var ids = _users.Select(x => x.Id);
+            var updateQuery = from target in dbContext.CollectionUsers
+                where target.CollectionId == _collectionId &&
+                    ids.Contains(target.OrganizationUserId)
+                select target;
+            return updateQuery;
+        }
+
+        public async Task<IEnumerable<EfModel.CollectionUser>> BuildInMemory(DatabaseContext dbContext)
+        {
+            var data = await Run(dbContext).ToListAsync();
+            var collectionUsers = data.Select(x => new EfModel.CollectionUser
+            { 
+                CollectionId = _collectionId,
+                OrganizationUserId = x.OrganizationUserId,
+                ReadOnly = _users.FirstOrDefault(u => u.Id.Equals(x.OrganizationUserId)).ReadOnly,
+                HidePasswords = _users.FirstOrDefault(u => u.Id.Equals(x.OrganizationUserId)).HidePasswords,
+            });
+            return collectionUsers;
+        }
+    }
+
+    public class CollectionUserUpdateUsersDeleteQuery: IQuery<EfModel.CollectionUser>
+    {
+        private readonly Guid _collectionId;
+        private readonly IEnumerable<SelectionReadOnly> _users;
+
+        public CollectionUserUpdateUsersDeleteQuery(Guid collectionId, IEnumerable<SelectionReadOnly> users)
+        {
+            _collectionId = collectionId;
+            _users = users;
+        }
+
+        public IQueryable<EfModel.CollectionUser> Run(DatabaseContext dbContext)
+        {
+            var orgId = dbContext.Collections.FirstOrDefault(c => c.Id == _collectionId)?.OrganizationId;
+            var deleteQuery = from cu in dbContext.CollectionUsers
+                where !dbContext.Users.Any(
+                    u => u.Id == cu.OrganizationUserId)
+            select cu;
+            return deleteQuery;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/EmergencyAccessDetailsViewQuery.cs b/src/Core/Repositories/EntityFramework/Queries/EmergencyAccessDetailsViewQuery.cs
new file mode 100644
index 0000000000..f2818b504a
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/EmergencyAccessDetailsViewQuery.cs
@@ -0,0 +1,39 @@
+using System.Linq;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class EmergencyAccessDetailsViewQuery : IQuery<EmergencyAccessDetails>
+    {
+        public IQueryable<EmergencyAccessDetails> Run(DatabaseContext dbContext)
+        {
+            var query = from ea in dbContext.EmergencyAccesses
+                join grantee in dbContext.Users
+                    on ea.GranteeId equals grantee.Id into grantee_g
+                from grantee in grantee_g.DefaultIfEmpty()
+                join grantor in dbContext.Users
+                    on ea.GrantorId equals grantor.Id into grantor_g
+                from grantor in grantor_g.DefaultIfEmpty()
+                select new {ea, grantee, grantor};
+            return query.Select(x => new EmergencyAccessDetails 
+            {
+                Id = x.ea.Id,
+                GrantorId = x.ea.GrantorId,
+                GranteeId = x.ea.GranteeId,
+                Email = x.ea.Email,
+                KeyEncrypted = x.ea.KeyEncrypted,
+                Type = x.ea.Type,
+                Status = x.ea.Status,
+                WaitTimeDays = x.ea.WaitTimeDays,
+                RecoveryInitiatedDate = x.ea.RecoveryInitiatedDate,
+                LastNotificationDate = x.ea.LastNotificationDate,
+                CreationDate = x.ea.CreationDate,
+                RevisionDate = x.ea.RevisionDate,
+                GranteeName = x.grantee.Name,
+                GranteeEmail = x.grantee.Email,
+                GrantorName = x.grantor.Name,
+                GrantorEmail = x.grantor.Email,
+            });
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/EmergencyAccessReadCountByGrantorIdEmailQuery.cs b/src/Core/Repositories/EntityFramework/Queries/EmergencyAccessReadCountByGrantorIdEmailQuery.cs
new file mode 100644
index 0000000000..b1007d56fc
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/EmergencyAccessReadCountByGrantorIdEmailQuery.cs
@@ -0,0 +1,33 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class EmergencyAccessReadCountByGrantorIdEmailQuery : IQuery<EmergencyAccess>
+    {
+        private readonly Guid _grantorId;
+        private readonly string _email;
+        private readonly bool _onlyRegisteredUsers;
+
+        public EmergencyAccessReadCountByGrantorIdEmailQuery(Guid grantorId, string email, bool onlyRegisteredUsers)
+        {
+            _grantorId = grantorId;
+            _email = email;
+            _onlyRegisteredUsers = onlyRegisteredUsers;
+        }
+
+        public IQueryable<EmergencyAccess> Run(DatabaseContext dbContext)
+        {
+            var query = from ea in dbContext.EmergencyAccesses
+                join u in dbContext.Users
+                    on ea.GranteeId equals u.Id into u_g
+                from u in u_g.DefaultIfEmpty()
+                where ea.GrantorId == _grantorId &&
+                    ((!_onlyRegisteredUsers && (ea.Email == _email || u.Email == _email))
+                     || (_onlyRegisteredUsers && u.Email == _email))
+                select ea;
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/EventReadPageByCipherIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/EventReadPageByCipherIdQuery.cs
new file mode 100644
index 0000000000..47d5a02533
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/EventReadPageByCipherIdQuery.cs
@@ -0,0 +1,50 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+using Bit.Core.Models.Data;
+using Table = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class EventReadPageByCipherIdQuery : IQuery<Event>
+    {
+        private readonly Table.Cipher _cipher;
+        private readonly DateTime _startDate;
+        private readonly DateTime _endDate;
+        private readonly DateTime? _beforeDate;
+        private readonly PageOptions _pageOptions;
+
+        public EventReadPageByCipherIdQuery(Table.Cipher cipher, DateTime startDate, DateTime endDate, PageOptions pageOptions)
+        {
+            _cipher = cipher;
+            _startDate = startDate;
+            _endDate = endDate;
+            _beforeDate = null;
+            _pageOptions = pageOptions;
+        }
+
+        public EventReadPageByCipherIdQuery(Table.Cipher cipher, DateTime startDate, DateTime endDate, DateTime? beforeDate, PageOptions pageOptions)
+        {
+            _cipher = cipher;
+            _startDate = startDate;
+            _endDate = endDate;
+            _beforeDate = beforeDate;
+            _pageOptions = pageOptions;
+        }
+
+        public IQueryable<Event> Run(DatabaseContext dbContext)
+        {
+            var q = from e in dbContext.Events
+                where e.Date >= _startDate &&
+                (_beforeDate == null || e.Date < _beforeDate.Value) &&
+                ((!_cipher.OrganizationId.HasValue && !e.OrganizationId.HasValue) ||
+                (_cipher.OrganizationId.HasValue && _cipher.OrganizationId == e.OrganizationId)) &&
+                ((!_cipher.UserId.HasValue && !e.UserId.HasValue) ||
+                    (_cipher.UserId.HasValue && _cipher.UserId == e.UserId)) &&
+                _cipher.Id == e.CipherId
+                orderby e.Date descending
+                select e;
+            return q.Skip(0).Take(_pageOptions.PageSize);
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/EventReadPageByOrganizationIdActingUserIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/EventReadPageByOrganizationIdActingUserIdQuery.cs
new file mode 100644
index 0000000000..207b8435b3
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/EventReadPageByOrganizationIdActingUserIdQuery.cs
@@ -0,0 +1,41 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class EventReadPageByOrganizationIdActingUserIdQuery : IQuery<Event>
+    {
+        private readonly Guid _organizationId;
+        private readonly Guid _actingUserId;
+        private readonly DateTime _startDate;
+        private readonly DateTime _endDate;
+        private readonly DateTime? _beforeDate;
+        private readonly PageOptions _pageOptions;
+
+        public EventReadPageByOrganizationIdActingUserIdQuery(Guid organizationId, Guid actingUserId,
+                DateTime startDate, DateTime endDate, DateTime? beforeDate, PageOptions pageOptions)
+        {
+            _organizationId = organizationId;
+            _actingUserId = actingUserId;
+            _startDate = startDate;
+            _endDate = endDate;
+            _beforeDate = beforeDate;
+            _pageOptions = pageOptions;
+        }
+
+        public IQueryable<Event> Run(DatabaseContext dbContext)
+        {
+            var q = from e in dbContext.Events
+                where e.Date >= _startDate &&
+                (_beforeDate != null || e.Date <= _endDate) &&
+                (_beforeDate == null || e.Date < _beforeDate.Value) &&
+                e.OrganizationId == _organizationId &&
+                e.ActingUserId == _actingUserId
+                orderby e.Date descending
+                select e;
+            return q.Skip(0).Take(_pageOptions.PageSize);
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/EventReadPageByOrganizationIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/EventReadPageByOrganizationIdQuery.cs
new file mode 100644
index 0000000000..95ac7d59e0
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/EventReadPageByOrganizationIdQuery.cs
@@ -0,0 +1,38 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class EventReadPageByOrganizationIdQuery: IQuery<Event>
+    {
+        private readonly Guid _organizationId;
+        private readonly DateTime _startDate;
+        private readonly DateTime _endDate;
+        private readonly DateTime? _beforeDate;
+        private readonly PageOptions _pageOptions;
+
+        public EventReadPageByOrganizationIdQuery(Guid organizationId, DateTime startDate,
+                DateTime endDate, DateTime? beforeDate, PageOptions pageOptions)
+        {
+            _organizationId = organizationId;
+            _startDate = startDate;
+            _endDate = endDate;
+            _beforeDate = beforeDate;
+            _pageOptions = pageOptions;
+        }
+
+        public IQueryable<Event> Run(DatabaseContext dbContext)
+        {
+            var q = from e in dbContext.Events
+                where e.Date >= _startDate &&
+                (_beforeDate != null || e.Date <= _endDate) &&
+                (_beforeDate == null || e.Date < _beforeDate.Value) &&
+                e.OrganizationId == _organizationId
+                orderby e.Date descending
+                select e;
+            return q.Skip(0).Take(_pageOptions.PageSize);
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/EventReadPageByUserIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/EventReadPageByUserIdQuery.cs
new file mode 100644
index 0000000000..d434e10f65
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/EventReadPageByUserIdQuery.cs
@@ -0,0 +1,39 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class EventReadPageByUserIdQuery: IQuery<Event>
+    {
+        private readonly Guid _userId;
+        private readonly DateTime _startDate;
+        private readonly DateTime _endDate;
+        private readonly DateTime? _beforeDate;
+        private readonly PageOptions _pageOptions;
+
+        public EventReadPageByUserIdQuery(Guid userId, DateTime startDate,
+                DateTime endDate, DateTime? beforeDate, PageOptions pageOptions)
+        {
+            _userId = userId;
+            _startDate = startDate;
+            _endDate = endDate;
+            _beforeDate = beforeDate;
+            _pageOptions = pageOptions;
+        }
+
+        public IQueryable<Event> Run(DatabaseContext dbContext)
+        {
+            var q = from e in dbContext.Events
+                where e.Date >= _startDate &&
+                (_beforeDate != null || e.Date <= _endDate) &&
+                (_beforeDate == null || e.Date < _beforeDate.Value) &&
+                !e.OrganizationId.HasValue &&
+                e.ActingUserId == _userId
+                orderby e.Date descending
+                select e;
+            return q.Skip(0).Take(_pageOptions.PageSize);
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/GroupUserUpdateGroupsQuery.cs b/src/Core/Repositories/EntityFramework/Queries/GroupUserUpdateGroupsQuery.cs
new file mode 100644
index 0000000000..6b61533a73
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/GroupUserUpdateGroupsQuery.cs
@@ -0,0 +1,73 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+using Microsoft.EntityFrameworkCore;
+using System.Collections.Generic;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class GroupUserUpdateGroupsQuery
+    {
+        public readonly GroupUserUpdateGroupsInsertQuery Insert;
+        public readonly GroupUserUpdateGroupsDeleteQuery Delete;
+
+        public GroupUserUpdateGroupsQuery(Guid organizationUserId, IEnumerable<Guid> groupIds)
+        {
+            Insert  = new GroupUserUpdateGroupsInsertQuery(organizationUserId, groupIds);
+            Delete = new GroupUserUpdateGroupsDeleteQuery(organizationUserId, groupIds);
+        }
+    }
+
+    public class GroupUserUpdateGroupsInsertQuery : IQuery<GroupUser>
+    {
+        private readonly Guid _organizationUserId;
+        private readonly IEnumerable<Guid> _groupIds;
+
+        public GroupUserUpdateGroupsInsertQuery(Guid organizationUserId, IEnumerable<Guid> collections)
+        {
+            _organizationUserId = organizationUserId;
+            _groupIds = collections;
+        }
+
+        public IQueryable<GroupUser> Run(DatabaseContext dbContext)
+        {
+            var orgUser = from ou in dbContext.OrganizationUsers
+                where ou.Id == _organizationUserId
+                select ou;
+            var groupIdEntities = dbContext.Groups.Where(x => _groupIds.Contains(x.Id));
+            var query = from g in dbContext.Groups
+                join ou in orgUser
+                    on g.OrganizationId equals ou.OrganizationId
+                join gie in groupIdEntities
+                    on g.Id equals gie.Id
+                where !dbContext.GroupUsers.Any(gu => _groupIds.Contains(gu.GroupId) && gu.OrganizationUserId == _organizationUserId)
+                select g;
+            return query.Select(x => new GroupUser 
+            {
+                GroupId = x.Id,
+                OrganizationUserId = _organizationUserId,
+            });
+        }
+    }
+
+    public class GroupUserUpdateGroupsDeleteQuery : IQuery<GroupUser>
+    {
+        private readonly Guid _organizationUserId;
+        private readonly IEnumerable<Guid> _groupIds;
+
+        public GroupUserUpdateGroupsDeleteQuery(Guid organizationUserId, IEnumerable<Guid> groupIds)
+        {
+            _organizationUserId = organizationUserId;
+            _groupIds = groupIds;
+        }
+
+        public IQueryable<GroupUser> Run(DatabaseContext dbContext)
+        {
+            var deleteQuery = from gu in dbContext.GroupUsers
+                where gu.OrganizationUserId == _organizationUserId &&
+                    !_groupIds.Any(x => gu.GroupId == x)
+                select gu;
+            return deleteQuery;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/IQuery.cs b/src/Core/Repositories/EntityFramework/Queries/IQuery.cs
new file mode 100644
index 0000000000..de6c129030
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/IQuery.cs
@@ -0,0 +1,9 @@
+using System.Linq;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public interface IQuery<TOut>
+    {
+        IQueryable<TOut> Run(DatabaseContext dbContext);
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/OrganizationUserOrganizationDetailsViewQuery.cs b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserOrganizationDetailsViewQuery.cs
new file mode 100644
index 0000000000..dd3e53d01c
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserOrganizationDetailsViewQuery.cs
@@ -0,0 +1,48 @@
+using System.Collections.Generic;
+using System.Linq;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class OrganizationUserOrganizationDetailsViewQuery : IQuery<OrganizationUserOrganizationDetails>
+    {
+        public IQueryable<OrganizationUserOrganizationDetails> Run(DatabaseContext dbContext)
+        {
+            var query = from ou in dbContext.OrganizationUsers
+                join o in dbContext.Organizations on ou.OrganizationId equals o.Id
+                join su in dbContext.SsoUsers on ou.UserId equals su.UserId into su_g
+                from su in su_g.DefaultIfEmpty()
+                where ((su == null || !su.OrganizationId.HasValue) || su.OrganizationId == ou.OrganizationId)
+                select new { ou, o, su };
+            return query.Select(x => new OrganizationUserOrganizationDetails 
+            {
+                OrganizationId = x.ou.OrganizationId,
+                UserId = x.ou.UserId,
+                Name = x.o.Name,
+                Enabled = x.o.Enabled,
+                UsePolicies = x.o.UsePolicies,
+                UseSso = x.o.UseSso,
+                UseGroups = x.o.UseGroups,
+                UseDirectory = x.o.UseDirectory,
+                UseEvents = x.o.UseEvents,
+                UseTotp = x.o.UseTotp,
+                Use2fa = x.o.Use2fa,
+                UseApi = x.o.UseApi,
+                SelfHost = x.o.SelfHost,
+                UsersGetPremium = x.o.UsersGetPremium,
+                Seats = x.o.Seats,
+                MaxCollections = x.o.MaxCollections,
+                MaxStorageGb = x.o.MaxStorageGb,
+                Identifier = x.o.Identifier,
+                Key = x.ou.Key,
+                ResetPasswordKey = x.ou.ResetPasswordKey,
+                Status = x.ou.Status,
+                Type = x.ou.Type,
+                SsoExternalId = x.su.ExternalId,
+                Permissions = x.ou.Permissions,
+                PublicKey = x.o.PublicKey,
+                PrivateKey = x.o.PrivateKey,
+            });
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByFreeOrganizationAdminUserQuery.cs b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByFreeOrganizationAdminUserQuery.cs
new file mode 100644
index 0000000000..c2f0c32e1f
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByFreeOrganizationAdminUserQuery.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using System.Linq;
+using Bit.Core.Enums;
+using Bit.Core.Models.EntityFramework;
+using System;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class OrganizationUserReadCountByFreeOrganizationAdminUserQuery : IQuery<OrganizationUser>
+    {
+        private readonly Guid _userId;
+
+        public OrganizationUserReadCountByFreeOrganizationAdminUserQuery(Guid userId)
+        {
+            _userId = userId;
+        }
+
+        public IQueryable<OrganizationUser> Run(DatabaseContext dbContext)
+        {
+            var query = from ou in dbContext.OrganizationUsers
+                join o in dbContext.Organizations
+                    on ou.OrganizationId equals o.Id
+                where ou.UserId == _userId &&
+                    (ou.Type == OrganizationUserType.Owner || ou.Type == OrganizationUserType.Admin) &&
+                    o.PlanType == PlanType.Free &&
+                    ou.Status == OrganizationUserStatusType.Confirmed
+                select ou;
+                                
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByOnlyOwnerQuery.cs b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByOnlyOwnerQuery.cs
new file mode 100644
index 0000000000..ed36db2c79
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByOnlyOwnerQuery.cs
@@ -0,0 +1,39 @@
+using System.Collections.Generic;
+using System.Linq;
+using Bit.Core.Enums;
+using Bit.Core.Models.EntityFramework;
+using System;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class OrganizationUserReadCountByOnlyOwnerQuery : IQuery<OrganizationUser>
+    {
+        private readonly Guid _userId;
+
+        public OrganizationUserReadCountByOnlyOwnerQuery(Guid userId)
+        {
+            _userId = userId;
+        }
+
+        public IQueryable<OrganizationUser> Run(DatabaseContext dbContext)
+        {
+            var owners = from ou in dbContext.OrganizationUsers
+                where ou.Type == OrganizationUserType.Owner &&
+                ou.Status == OrganizationUserStatusType.Confirmed
+                group ou by ou.OrganizationId into g
+                select new 
+                { 
+                    OrgUser = g.Select(x => new {x.UserId, x.Id}).FirstOrDefault(), ConfirmedOwnerCount = g.Count() 
+                };
+                    
+            var query = from owner in owners
+                join ou in dbContext.OrganizationUsers
+                    on owner.OrgUser.Id equals ou.Id
+                where owner.OrgUser.UserId == _userId &&
+                    owner.ConfirmedOwnerCount == 1
+                select ou;
+                                
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByOrganizationIdEmailQuery.cs b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByOrganizationIdEmailQuery.cs
new file mode 100644
index 0000000000..17da7814e9
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByOrganizationIdEmailQuery.cs
@@ -0,0 +1,33 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class OrganizationUserReadCountByOrganizationIdEmailQuery : IQuery<OrganizationUser>
+    {
+        private readonly Guid _organizationId;
+        private readonly string _email;
+        private readonly bool _onlyUsers;
+
+        public OrganizationUserReadCountByOrganizationIdEmailQuery(Guid organizationId, string email, bool onlyUsers)
+        {
+            _organizationId = organizationId;
+            _email = email;
+            _onlyUsers = onlyUsers;
+        }
+
+        public IQueryable<OrganizationUser> Run(DatabaseContext dbContext)
+        {
+            var query = from ou in dbContext.OrganizationUsers
+                join u in dbContext.Users
+                    on ou.UserId equals u.Id into u_g
+                from u in u_g.DefaultIfEmpty()
+                where ou.OrganizationId == _organizationId &&
+                    ((!_onlyUsers && (ou.Email == _email || u.Email == _email))
+                     || (_onlyUsers && u.Email == _email))
+                select ou;
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByOrganizationIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByOrganizationIdQuery.cs
new file mode 100644
index 0000000000..3a47772376
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserReadCountByOrganizationIdQuery.cs
@@ -0,0 +1,24 @@
+using System.Linq;
+using Bit.Core.Models.EntityFramework;
+using System;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class OrganizationUserReadCountByOrganizationIdQuery : IQuery<OrganizationUser>
+    {
+        private readonly Guid _organizationId;
+
+        public OrganizationUserReadCountByOrganizationIdQuery(Guid organizationId)
+        {
+            _organizationId = organizationId;
+        }
+
+        public IQueryable<OrganizationUser> Run(DatabaseContext dbContext)
+        {
+            var query = from ou in dbContext.OrganizationUsers
+                where ou.OrganizationId == _organizationId
+                select ou;
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/OrganizationUserUpdateWithCollectionsQuery.cs b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserUpdateWithCollectionsQuery.cs
new file mode 100644
index 0000000000..de2e519c54
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserUpdateWithCollectionsQuery.cs
@@ -0,0 +1,110 @@
+using Bit.Core.Models.Data;
+using Bit.Core.Models.EntityFramework;
+using Microsoft.EntityFrameworkCore;
+using System.Collections.Generic;
+using System.Linq;
+using System;
+using Table = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class OrganizationUserUpdateWithCollectionsQuery
+    {
+        public OrganizationUserUpdateWithCollectionsInsertQuery Insert { get; set; }
+        public OrganizationUserUpdateWithCollectionsUpdateQuery Update { get; set; }
+        public OrganizationUserUpdateWithCollectionsDeleteQuery Delete { get; set; }
+
+        public OrganizationUserUpdateWithCollectionsQuery(Table.OrganizationUser organizationUser,
+                IEnumerable<SelectionReadOnly> collections)
+        {
+            Insert  = new OrganizationUserUpdateWithCollectionsInsertQuery(organizationUser, collections);
+            Update = new OrganizationUserUpdateWithCollectionsUpdateQuery(organizationUser, collections);
+            Delete = new OrganizationUserUpdateWithCollectionsDeleteQuery(organizationUser, collections);
+        }
+    }
+
+    public class OrganizationUserUpdateWithCollectionsInsertQuery : IQuery<CollectionUser>
+    {
+        private readonly Table.OrganizationUser _organizationUser;
+        private readonly IEnumerable<SelectionReadOnly> _collections;
+
+        public OrganizationUserUpdateWithCollectionsInsertQuery(Table.OrganizationUser organizationUser, IEnumerable<SelectionReadOnly> collections)
+        {
+            _organizationUser = organizationUser;
+            _collections = collections;
+        }
+
+        public IQueryable<CollectionUser> Run(DatabaseContext dbContext)
+        {
+            var collectionIds = _collections.Select(c => c.Id).ToArray();
+            var t = (from cu in dbContext.CollectionUsers
+                where collectionIds.Contains(cu.CollectionId) &&
+                    cu.OrganizationUserId == _organizationUser.Id
+                select cu).AsEnumerable();
+            var insertQuery = (from c in dbContext.Collections
+                where collectionIds.Contains(c.Id) &&
+                    c.OrganizationId == _organizationUser.OrganizationId &&
+                    !t.Any()
+                select c).AsEnumerable();
+            return insertQuery.Select(x => new CollectionUser
+            { 
+                CollectionId = x.Id,
+                OrganizationUserId = _organizationUser.Id,
+                ReadOnly = _collections.FirstOrDefault(c => c.Id == x.Id).ReadOnly,
+                HidePasswords = _collections.FirstOrDefault(c => c.Id == x.Id).HidePasswords,
+            }).AsQueryable();
+        }
+    }
+
+    public class OrganizationUserUpdateWithCollectionsUpdateQuery: IQuery<CollectionUser>
+    {
+        private readonly Table.OrganizationUser _organizationUser;
+        private readonly IEnumerable<SelectionReadOnly> _collections;
+
+        public OrganizationUserUpdateWithCollectionsUpdateQuery(Table.OrganizationUser organizationUser, IEnumerable<SelectionReadOnly> collections)
+        {
+            _organizationUser = organizationUser;
+            _collections = collections;
+        }
+
+        public IQueryable<CollectionUser> Run(DatabaseContext dbContext)
+        {
+            var collectionIds = _collections.Select(c => c.Id).ToArray();
+            var updateQuery = (from target in dbContext.CollectionUsers
+                where collectionIds.Contains(target.CollectionId) &&
+                target.OrganizationUserId == _organizationUser.Id
+                select new { target }).AsEnumerable();
+            updateQuery = updateQuery.Where(cu => 
+                cu.target.ReadOnly == _collections.FirstOrDefault(u => u.Id == cu.target.CollectionId).ReadOnly &&
+                cu.target.HidePasswords == _collections.FirstOrDefault(u => u.Id == cu.target.CollectionId).HidePasswords);
+            return updateQuery.Select(x => new CollectionUser
+            { 
+                CollectionId = x.target.CollectionId,
+                OrganizationUserId = _organizationUser.Id,
+                ReadOnly = x.target.ReadOnly,
+                HidePasswords = x.target.HidePasswords,
+            }).AsQueryable();
+        }
+    }
+
+    public class OrganizationUserUpdateWithCollectionsDeleteQuery: IQuery<CollectionUser>
+    {
+        private readonly Table.OrganizationUser _organizationUser;
+        private readonly IEnumerable<SelectionReadOnly> _collections;
+
+        public OrganizationUserUpdateWithCollectionsDeleteQuery(Table.OrganizationUser organizationUser, IEnumerable<SelectionReadOnly> collections)
+        {
+            _organizationUser = organizationUser;
+            _collections = collections;
+        }
+
+        public IQueryable<CollectionUser> Run(DatabaseContext dbContext)
+        {
+            var deleteQuery = from cu in dbContext.CollectionUsers
+                where !_collections.Any(
+                    c => c.Id == cu.CollectionId)
+                select cu;
+            return deleteQuery;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/OrganizationUserUserViewQuery.cs b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserUserViewQuery.cs
new file mode 100644
index 0000000000..861a334a88
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/OrganizationUserUserViewQuery.cs
@@ -0,0 +1,35 @@
+using System.Linq;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class OrganizationUserUserDetailsViewQuery : IQuery<OrganizationUserUserDetails>
+    {
+        public IQueryable<OrganizationUserUserDetails> Run(DatabaseContext dbContext)
+        {
+            var query = from ou in dbContext.OrganizationUsers
+                join u in dbContext.Users on ou.UserId equals u.Id into u_g
+                from u in u_g.DefaultIfEmpty()
+                join su in dbContext.SsoUsers on u.Id equals su.UserId into su_g
+                from su in su_g.DefaultIfEmpty()
+                select new { ou, u, su };
+            return query.Select(x => new OrganizationUserUserDetails 
+            {
+                Id = x.ou.Id,
+                OrganizationId = x.ou.OrganizationId,
+                UserId = x.ou.UserId,
+                Name = x.u.Name,
+                Email = x.u.Email ?? x.ou.Email,
+                TwoFactorProviders = x.u.TwoFactorProviders,
+                Premium = x.u.Premium,
+                Status = x.ou.Status,
+                Type = x.ou.Type,
+                AccessAll = x.ou.AccessAll,
+                ExternalId = x.ou.ExternalId,
+                SsoExternalId = x.su.ExternalId,
+                Permissions = x.ou.Permissions,
+                ResetPasswordKey = x.ou.ResetPasswordKey,
+            });
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/PolicyReadByUserIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/PolicyReadByUserIdQuery.cs
new file mode 100644
index 0000000000..09532e1015
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/PolicyReadByUserIdQuery.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using System.Linq;
+using Bit.Core.Enums;
+using Bit.Core.Models.EntityFramework;
+using System;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class PolicyReadByUserIdQuery : IQuery<Policy>
+    {
+        private readonly Guid _userId;
+
+        public PolicyReadByUserIdQuery(Guid userId)
+        {
+            _userId = userId;
+        }
+
+        public IQueryable<Policy> Run(DatabaseContext dbContext)
+        {
+            var query = from p in dbContext.Policies
+                join ou in dbContext.OrganizationUsers
+                    on p.OrganizationId equals ou.OrganizationId
+                join o in dbContext.Organizations
+                    on ou.OrganizationId equals o.Id
+                where ou.UserId == _userId &&
+                    ou.Status == OrganizationUserStatusType.Confirmed &&
+                    o.Enabled == true
+                select p;
+                                
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/ProviderOrganizationOrganizationDetailsReadByProviderIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/ProviderOrganizationOrganizationDetailsReadByProviderIdQuery.cs
new file mode 100644
index 0000000000..3919fae591
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/ProviderOrganizationOrganizationDetailsReadByProviderIdQuery.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Linq;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class ProviderOrganizationOrganizationDetailsReadByProviderIdQuery : IQuery<ProviderOrganizationOrganizationDetails>
+    {
+        private readonly Guid _providerId;
+        public ProviderOrganizationOrganizationDetailsReadByProviderIdQuery(Guid providerId)
+        {
+            _providerId = providerId;
+        }
+
+        public IQueryable<ProviderOrganizationOrganizationDetails> Run(DatabaseContext dbContext)
+        {
+            var query = from po in dbContext.ProviderOrganizations
+                join o in dbContext.Organizations
+                    on po.OrganizationId equals o.Id
+                where po.ProviderId == _providerId
+                select new { po, o };
+            return query.Select(x => new ProviderOrganizationOrganizationDetails() 
+            {
+                Id = x.po.Id,
+                ProviderId = x.po.ProviderId,
+                OrganizationId  = x.po.OrganizationId,
+                OrganizationName = x.o.Name,
+                Key = x.po.Key,
+                Settings = x.po.Settings,
+                CreationDate = x.po.CreationDate,
+                RevisionDate = x.po.RevisionDate,
+            });
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/ProviderUserProviderDetailsReadByUserIdStatusQuery.cs b/src/Core/Repositories/EntityFramework/Queries/ProviderUserProviderDetailsReadByUserIdStatusQuery.cs
new file mode 100644
index 0000000000..5188033191
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/ProviderUserProviderDetailsReadByUserIdStatusQuery.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Linq;
+using Bit.Core.Enums.Provider;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class ProviderUserProviderDetailsReadByUserIdStatusQuery : IQuery<ProviderUserProviderDetails>
+    {
+        private readonly Guid _userId;
+        private readonly ProviderUserStatusType? _status;
+        public ProviderUserProviderDetailsReadByUserIdStatusQuery(Guid userId, ProviderUserStatusType? status)
+        {
+            _userId = userId;
+            _status = status;
+        }
+
+        public IQueryable<ProviderUserProviderDetails> Run(DatabaseContext dbContext)
+        {
+            var query = from pu in dbContext.ProviderUsers
+                join p in dbContext.Providers
+                    on pu.ProviderId equals p.Id into p_g
+                from p in p_g.DefaultIfEmpty()
+                where pu.UserId == _userId && (_status == null || pu.Status == _status)
+                select new { pu, p };
+            return query.Select(x => new ProviderUserProviderDetails() 
+            {
+                UserId = x.pu.UserId,
+                ProviderId = x.pu.ProviderId,
+                Name =  x.p.Name,
+                Key = x.pu.Key,
+                Status = x.pu.Status,
+                Type = x.pu.Type,
+                Enabled = x.p.Enabled,
+                Permissions = x.pu.Permissions,
+            });
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/UserBumpAccountRevisionDateByCipherIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/UserBumpAccountRevisionDateByCipherIdQuery.cs
new file mode 100644
index 0000000000..38bc0cf507
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/UserBumpAccountRevisionDateByCipherIdQuery.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using System.Linq;
+using Bit.Core.Enums;
+using Bit.Core.Models.EntityFramework;
+using Table = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class UserBumpAccountRevisionDateByCipherIdQuery : IQuery<User>
+    {
+        private readonly Table.Cipher _cipher;
+
+        public UserBumpAccountRevisionDateByCipherIdQuery(Table.Cipher cipher)
+        {
+            _cipher = cipher;
+        }
+
+        public IQueryable<User> Run(DatabaseContext dbContext)
+        {
+            var query = from u in dbContext.Users
+                join ou in dbContext.OrganizationUsers
+                    on u.Id equals ou.UserId
+                join collectionCipher in dbContext.CollectionCiphers
+                    on _cipher.Id equals collectionCipher.CipherId into cc_g
+                from cc in cc_g.DefaultIfEmpty()
+                join collectionUser in dbContext.CollectionUsers
+                    on cc.CollectionId equals collectionUser.CollectionId into cu_g
+                from cu in cu_g.DefaultIfEmpty()
+                where ou.AccessAll && 
+                        cu.OrganizationUserId == ou.Id
+                join groupUser in dbContext.GroupUsers
+                    on ou.Id equals groupUser.OrganizationUserId into gu_g
+                from gu in gu_g.DefaultIfEmpty()
+                where cu.CollectionId == null &&
+                        !ou.AccessAll
+                join grp in dbContext.Groups
+                    on gu.GroupId equals grp.Id into g_g
+                from g in g_g.DefaultIfEmpty()
+                join collectionGroup in dbContext.CollectionGroups
+                    on cc.CollectionId equals collectionGroup.CollectionId into cg_g
+                from cg in cg_g.DefaultIfEmpty()
+                where !g.AccessAll &&
+                        cg.GroupId == gu.GroupId
+                where ou.OrganizationId == _cipher.OrganizationId &&
+                        ou.Status == OrganizationUserStatusType.Confirmed &&
+                        (cu.CollectionId != null ||
+                        cg.CollectionId != null ||
+                        ou.AccessAll ||
+                        g.AccessAll)
+                select u;
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/UserBumpAccountRevisionDateByOrganizationIdQuery.cs b/src/Core/Repositories/EntityFramework/Queries/UserBumpAccountRevisionDateByOrganizationIdQuery.cs
new file mode 100644
index 0000000000..4145d27195
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/UserBumpAccountRevisionDateByOrganizationIdQuery.cs
@@ -0,0 +1,30 @@
+using System.Collections.Generic;
+using System.Linq;
+using Bit.Core.Enums;
+using System;
+using Bit.Core.Models.EntityFramework;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class UserBumpAccountRevisionDateByOrganizationIdQuery : IQuery<User>
+    {
+        private readonly Guid _organizationId;
+
+        public UserBumpAccountRevisionDateByOrganizationIdQuery(Guid organizationId)
+        {
+            _organizationId = organizationId;
+        }
+
+        public IQueryable<User> Run(DatabaseContext dbContext)
+        {
+            var query = from u in dbContext.Users
+                join ou in dbContext.OrganizationUsers
+                    on u.Id equals ou.UserId
+                where ou.OrganizationId == _organizationId &&
+                    ou.Status == OrganizationUserStatusType.Confirmed
+                select u;
+                        
+            return query;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/UserCipherDetailsQuery.cs b/src/Core/Repositories/EntityFramework/Queries/UserCipherDetailsQuery.cs
new file mode 100644
index 0000000000..8254b091ce
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/UserCipherDetailsQuery.cs
@@ -0,0 +1,76 @@
+using System.Linq;
+using System;
+using Bit.Core.Enums;
+using System.Collections.Generic;
+using Core.Models.Data;
+using Bit.Core.Utilities;
+using Newtonsoft.Json.Linq;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class UserCipherDetailsQuery : IQuery<CipherDetails>
+    {
+        private readonly Guid? _userId; 
+        public UserCipherDetailsQuery(Guid? userId)
+        {
+            _userId = userId;
+        }
+        public virtual IQueryable<CipherDetails> Run(DatabaseContext dbContext)
+        {
+            var query = from c in dbContext.Ciphers
+                join ou in dbContext.OrganizationUsers
+                    on c.OrganizationId equals ou.OrganizationId
+                where ou.UserId == _userId &&
+                    ou.Status == OrganizationUserStatusType.Confirmed
+                join o in dbContext.Organizations 
+                    on c.OrganizationId equals o.Id
+                where o.Id == ou.OrganizationId && o.Enabled
+                join cc in dbContext.CollectionCiphers
+                    on c.Id equals cc.CipherId into cc_g
+                from cc in cc_g.DefaultIfEmpty()
+                where ou.AccessAll
+                join cu in dbContext.CollectionUsers
+                    on cc.CollectionId equals cu.CollectionId into cu_g
+                from cu in cu_g.DefaultIfEmpty()
+                where cu.OrganizationUserId == ou.Id
+                join gu in dbContext.GroupUsers
+                    on ou.Id equals gu.OrganizationUserId into gu_g
+                from gu in gu_g.DefaultIfEmpty()
+                where cu.CollectionId == null && !ou.AccessAll
+                join g in dbContext.Groups
+                    on gu.GroupId equals g.Id into g_g
+                from g in g_g.DefaultIfEmpty()
+                join cg in dbContext.CollectionGroups
+                    on cc.CollectionId equals cg.CollectionId into cg_g
+                from cg in cg_g.DefaultIfEmpty()
+                where !g.AccessAll && cg.GroupId == gu.GroupId &&
+                ou.AccessAll || cu.CollectionId != null || g.AccessAll || cg.CollectionId != null
+                select new {c, ou, o, cc, cu, gu, g, cg}.c;
+
+            var query2 = from c in dbContext.Ciphers
+                where c.UserId == _userId
+                select c;
+
+            var union = query.Union(query2).Select(c => new CipherDetails
+            {
+                Id = c.Id,
+                UserId = c.UserId,
+                OrganizationId = c.OrganizationId,
+                Type= c.Type,
+                Data = c.Data,
+                Attachments = c.Attachments,
+                CreationDate = c.CreationDate,
+                RevisionDate = c.RevisionDate,
+                DeletedDate = c.DeletedDate,
+                Favorite = _userId.HasValue && c.Favorites != null && c.Favorites.Contains($"\"{_userId}\":true"),
+                FolderId = _userId.HasValue && !string.IsNullOrWhiteSpace(c.Folders) ? 
+                    Guid.Parse(JObject.Parse(c.Folders)[_userId.Value.ToString()].Value<string>()) : 
+                    null,
+                Edit = true,
+                ViewPassword = true,
+                OrganizationUseTotp = false,
+            });
+            return union;
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/UserCollectionDetailsQuery.cs b/src/Core/Repositories/EntityFramework/Queries/UserCollectionDetailsQuery.cs
new file mode 100644
index 0000000000..9c56239d22
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/UserCollectionDetailsQuery.cs
@@ -0,0 +1,56 @@
+using System.Linq;
+using System;
+using Bit.Core.Enums;
+using System.Collections.Generic;
+using Bit.Core.Models.Data;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class UserCollectionDetailsQuery : IQuery<CollectionDetails>
+    {
+        private readonly Guid? _userId; 
+        public UserCollectionDetailsQuery(Guid? userId)
+        {
+            _userId = userId;
+        }
+        public virtual IQueryable<CollectionDetails> Run(DatabaseContext dbContext)
+        {
+            var query = from c in dbContext.Collections
+                join ou in dbContext.OrganizationUsers
+                    on c.OrganizationId equals ou.OrganizationId
+                join o in dbContext.Organizations
+                    on c.OrganizationId equals o.Id
+                join cu in dbContext.CollectionUsers
+                    on c.Id equals cu.CollectionId into cu_g
+                from cu in cu_g.DefaultIfEmpty()
+                where ou.AccessAll && cu.OrganizationUserId == ou.Id
+                join gu in dbContext.GroupUsers
+                    on ou.Id equals gu.OrganizationUserId into gu_g
+                from gu in gu_g.DefaultIfEmpty()
+                where cu.CollectionId == null && !ou.AccessAll
+                join g in dbContext.Groups
+                    on gu.GroupId equals g.Id into g_g
+                from g in g_g.DefaultIfEmpty()
+                join cg in dbContext.CollectionGroups
+                    on gu.GroupId equals cg.GroupId into cg_g
+                from cg in cg_g.DefaultIfEmpty()
+                where !g.AccessAll && cg.CollectionId == c.Id &&
+                    ou.UserId == _userId &&
+                    ou.Status == OrganizationUserStatusType.Confirmed &&
+                    o.Enabled &&
+                    (ou.AccessAll || cu.CollectionId != null || g.AccessAll || cg.CollectionId != null)
+                select new { c, ou, o, cu, gu, g, cg };
+            return query.Select(x => new CollectionDetails 
+            {
+                Id = x.c.Id,
+                OrganizationId = x.c.OrganizationId,
+                Name = x.c.Name,
+                ExternalId = x.c.ExternalId,
+                CreationDate = x.c.CreationDate,
+                RevisionDate = x.c.RevisionDate,
+                ReadOnly = !x.ou.AccessAll || !x.g.AccessAll || (x.cu.ReadOnly || x.cg.ReadOnly),
+                HidePasswords = !x.ou.AccessAll || !x.g.AccessAll || (x.cu.HidePasswords || x.cg.HidePasswords),
+            });
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Queries/UserReadPublicKeysByProviderUserIdsQuery.cs b/src/Core/Repositories/EntityFramework/Queries/UserReadPublicKeysByProviderUserIdsQuery.cs
new file mode 100644
index 0000000000..d3b629f6dc
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/Queries/UserReadPublicKeysByProviderUserIdsQuery.cs
@@ -0,0 +1,38 @@
+using System.Linq;
+using System;
+using System.Collections.Generic;
+using Core.Models.Data;
+using Bit.Core.Utilities;
+using Bit.Core.Models.Data;
+using Bit.Core.Enums.Provider;
+
+namespace Bit.Core.Repositories.EntityFramework.Queries
+{
+    public class UserReadPublicKeysByProviderUserIdsQuery : IQuery<ProviderUserPublicKey>
+    {
+        private readonly Guid _providerId;
+        private readonly IEnumerable<Guid> _ids;
+
+        public UserReadPublicKeysByProviderUserIdsQuery(Guid providerId, IEnumerable<Guid> Ids)
+        {
+            _providerId = providerId;
+            _ids = Ids;
+        }
+
+        public virtual IQueryable<ProviderUserPublicKey> Run(DatabaseContext dbContext)
+        {
+            var query = from pu in dbContext.ProviderUsers
+                join u in dbContext.Users
+                    on pu.UserId equals u.Id
+                where _ids.Contains(pu.Id) &&
+                    pu.Status == ProviderUserStatusType.Accepted &&
+                    pu.ProviderId == _providerId
+                select new { pu, u };
+            return query.Select(x => new ProviderUserPublicKey
+            {
+                Id = x.pu.Id,
+                PublicKey = x.u.PublicKey,
+            });
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/Repository.cs b/src/Core/Repositories/EntityFramework/Repository.cs
index b8158065b8..4f29ed621d 100644
--- a/src/Core/Repositories/EntityFramework/Repository.cs
+++ b/src/Core/Repositories/EntityFramework/Repository.cs
@@ -4,6 +4,9 @@ using Bit.Core.Models.Table;
 using AutoMapper;
 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection;
+using System.Collections.Generic;
+using System.Linq;
+using Bit.Core.Repositories.EntityFramework.Queries;
 
 namespace Bit.Core.Repositories.EntityFramework
 {
@@ -26,19 +29,21 @@ namespace Bit.Core.Repositories.EntityFramework
             {
                 var dbContext = GetDatabaseContext(scope);
                 var entity = await GetDbSet(dbContext).FindAsync(id);
-                return entity as T;
+                return Mapper.Map<T>(entity);
             }
         }
 
-        public virtual async Task CreateAsync(T obj)
+        public virtual async Task<T> CreateAsync(T obj)
         {
             using (var scope = ServiceScopeFactory.CreateScope())
             {
                 var dbContext = GetDatabaseContext(scope);
+                obj.SetNewId();
                 var entity = Mapper.Map<TEntity>(obj);
-                dbContext.Add(entity);
+                await dbContext.AddAsync(entity);
                 await dbContext.SaveChangesAsync();
                 obj.Id = entity.Id;
+                return obj;
             }
         }
 
@@ -59,7 +64,7 @@ namespace Bit.Core.Repositories.EntityFramework
 
         public virtual async Task UpsertAsync(T obj)
         {
-            if (obj.Id.Equals(default(T)))
+            if (obj.Id.Equals(default(TId)))
             {
                 await CreateAsync(obj);
             }
@@ -75,9 +80,46 @@ namespace Bit.Core.Repositories.EntityFramework
             {
                 var dbContext = GetDatabaseContext(scope);
                 var entity = Mapper.Map<TEntity>(obj);
-                dbContext.Entry(entity).State = EntityState.Deleted;
+                dbContext.Remove(entity);
                 await dbContext.SaveChangesAsync();
             }
         }
+
+        public virtual async Task RefreshDb()
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var context = GetDatabaseContext(scope);
+                await context.Database.EnsureDeletedAsync();
+                await context.Database.EnsureCreatedAsync();
+            }
+        }
+
+        public virtual async Task<List<T>> CreateMany(List<T> objs)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var entities = new List<TEntity>();
+                foreach (var o in objs)
+                {
+                    o.SetNewId();
+                    var entity = Mapper.Map<TEntity>(o);
+                    entities.Add(entity);
+                }
+                var dbContext = GetDatabaseContext(scope);
+                await GetDbSet(dbContext).AddRangeAsync(entities);
+                await dbContext.SaveChangesAsync();
+                return objs;
+            }
+        }
+
+        public IQueryable<Tout> Run<Tout>(IQuery<Tout> query)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                return query.Run(dbContext);
+            }
+        }
     }
 }
diff --git a/src/Core/Repositories/EntityFramework/SendRepository.cs b/src/Core/Repositories/EntityFramework/SendRepository.cs
new file mode 100644
index 0000000000..151c4e67a1
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/SendRepository.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Table;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class SendRepository : Repository<TableModel.Send, EfModel.Send, Guid>, ISendRepository
+    {
+        public SendRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Sends)
+        { }
+
+        public override async Task<Send> CreateAsync(Send send)
+        {
+           send = await base.CreateAsync(send);
+           if (send.UserId.HasValue)
+           {
+                await UserUpdateStorage(send.UserId.Value);
+                await UserBumpAccountRevisionDate(send.UserId.Value);
+           }
+           return send;
+        }
+
+        public async Task<ICollection<Send>> GetManyByDeletionDateAsync(DateTime deletionDateBefore)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.Sends.Where(s => s.DeletionDate < deletionDateBefore).ToListAsync();
+                return Mapper.Map<List<TableModel.Send>>(results);
+            }
+        }
+
+        public async Task<ICollection<Send>> GetManyByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.Sends.Where(s => s.UserId == userId).ToListAsync();
+                return Mapper.Map<List<TableModel.Send>>(results);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/SsoConfigRepository.cs b/src/Core/Repositories/EntityFramework/SsoConfigRepository.cs
new file mode 100644
index 0000000000..e96bb6485f
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/SsoConfigRepository.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Table;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class SsoConfigRepository : Repository<TableModel.SsoConfig, EfModel.SsoConfig, long>, ISsoConfigRepository
+    {
+        public SsoConfigRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.SsoConfigs)
+        { }
+
+        public async Task<SsoConfig> GetByOrganizationIdAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var ssoConfig = await GetDbSet(dbContext).SingleOrDefaultAsync(sc => sc.OrganizationId == organizationId);
+                return Mapper.Map<TableModel.SsoConfig>(ssoConfig);
+            }
+        }
+
+        public async Task<SsoConfig> GetByIdentifierAsync(string identifier)
+        {
+
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var ssoConfig = await GetDbSet(dbContext).SingleOrDefaultAsync(sc => sc.Organization.Identifier == identifier);
+                return Mapper.Map<TableModel.SsoConfig>(ssoConfig);
+            }
+        }
+
+        public async Task<ICollection<SsoConfig>> GetManyByRevisionNotBeforeDate(DateTime? notBefore)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var ssoConfigs = await GetDbSet(dbContext).Where(sc => sc.Enabled && sc.RevisionDate >= notBefore).ToListAsync();
+                return Mapper.Map<List<TableModel.SsoConfig>>(ssoConfigs);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/SsoUserRepository.cs b/src/Core/Repositories/EntityFramework/SsoUserRepository.cs
new file mode 100644
index 0000000000..6eacfa0afc
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/SsoUserRepository.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Threading.Tasks;
+using AutoMapper;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class SsoUserRepository : Repository<TableModel.SsoUser, EfModel.SsoUser, long>, ISsoUserRepository
+    {
+        public SsoUserRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.SsoUsers)
+        { }
+
+        public async Task DeleteAsync(Guid userId, Guid? organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entity = await GetDbSet(dbContext).SingleOrDefaultAsync(su => su.UserId == userId && su.OrganizationId == organizationId);
+                dbContext.Entry(entity).State = EntityState.Deleted;
+                await dbContext.SaveChangesAsync();
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/TaxRateRepository.cs b/src/Core/Repositories/EntityFramework/TaxRateRepository.cs
new file mode 100644
index 0000000000..f2180002c2
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/TaxRateRepository.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Table;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class TaxRateRepository : Repository<TableModel.TaxRate, EfModel.TaxRate, string>, ITaxRateRepository
+    {
+        public TaxRateRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.TaxRates)
+        { }
+
+        public async Task ArchiveAsync(TaxRate model)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var entity = await dbContext.FindAsync<TaxRate>(model);
+                entity.Active = false;
+                await dbContext.SaveChangesAsync();
+            }
+        }
+
+        public async Task<ICollection<TaxRate>> GetAllActiveAsync()
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.TaxRates
+                    .Where(t => t.Active)
+                    .ToListAsync();
+                return Mapper.Map<List<TableModel.TaxRate>>(results);
+            }
+        }
+
+        public async Task<ICollection<TaxRate>> GetByLocationAsync(TaxRate taxRate)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.TaxRates
+                    .Where(t => t.Active &&
+                        t.Country == taxRate.Country &&
+                        t.PostalCode == taxRate.PostalCode)
+                    .ToListAsync();
+                return Mapper.Map<List<TableModel.TaxRate>>(results);
+            }
+        }
+
+        public async Task<ICollection<TaxRate>> SearchAsync(int skip, int count)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.TaxRates
+                    .Skip(skip)
+                    .Take(count)
+                    .Where(t => t.Active)
+                    .OrderBy(t => t.Country).ThenByDescending(t => t.PostalCode)
+                    .ToListAsync();
+                return Mapper.Map<List<TableModel.TaxRate>>(results);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/TransactionRepository.cs b/src/Core/Repositories/EntityFramework/TransactionRepository.cs
new file mode 100644
index 0000000000..07ceebe0f4
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/TransactionRepository.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Enums;
+using Bit.Core.Models.Table;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class TransactionRepository : Repository<TableModel.Transaction, EfModel.Transaction, Guid>, ITransactionRepository
+    {
+        public TransactionRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.Transactions)
+        { }
+
+        public async Task<Transaction> GetByGatewayIdAsync(GatewayType gatewayType, string gatewayId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.Transactions
+                    .FirstOrDefaultAsync(t => (t.GatewayId == gatewayId && t.Gateway == gatewayType));
+                return Mapper.Map<TableModel.Transaction>(results);
+            }
+        }
+
+        public async Task<ICollection<Transaction>> GetManyByOrganizationIdAsync(Guid organizationId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.Transactions
+                    .Where(t => (t.OrganizationId == organizationId && !t.UserId.HasValue))
+                    .ToListAsync();
+                return Mapper.Map<List<TableModel.Transaction>>(results);
+            }
+        }
+
+        public async Task<ICollection<Transaction>> GetManyByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.Transactions
+                    .Where(t => (t.UserId == userId))
+                    .ToListAsync();
+                return Mapper.Map<List<TableModel.Transaction>>(results);
+            }
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/U2fRepository.cs b/src/Core/Repositories/EntityFramework/U2fRepository.cs
new file mode 100644
index 0000000000..1afe000e0a
--- /dev/null
+++ b/src/Core/Repositories/EntityFramework/U2fRepository.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using AutoMapper;
+using Bit.Core.Models.Table;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.DependencyInjection;
+using DataModel = Bit.Core.Models.Data;
+using EfModel = Bit.Core.Models.EntityFramework;
+using TableModel = Bit.Core.Models.Table;
+
+namespace Bit.Core.Repositories.EntityFramework
+{
+    public class U2fRepository : Repository<TableModel.U2f, EfModel.U2f, int>, IU2fRepository
+    {
+        public U2fRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper)
+            : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.U2fs)
+        { }
+
+        public async Task<ICollection<U2f>> GetManyByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var results = await dbContext.U2fs.Where(u => u.UserId == userId).ToListAsync();
+                return (ICollection<U2f>)results;
+            }
+        }
+
+        public async Task DeleteManyByUserIdAsync(Guid userId)
+        {
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var u2fs = dbContext.U2fs.Where(u => u.UserId == userId);
+                dbContext.RemoveRange(u2fs);
+                await dbContext.SaveChangesAsync();
+            }
+        }
+        
+        public override Task ReplaceAsync(U2f obj)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override Task UpsertAsync(U2f obj)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override Task DeleteAsync(U2f obj)
+        {
+            throw new NotSupportedException();
+        }
+    }
+}
diff --git a/src/Core/Repositories/EntityFramework/UserRepository.cs b/src/Core/Repositories/EntityFramework/UserRepository.cs
index 75e3a22f5b..38c432131d 100644
--- a/src/Core/Repositories/EntityFramework/UserRepository.cs
+++ b/src/Core/Repositories/EntityFramework/UserRepository.cs
@@ -9,6 +9,7 @@ using System.Collections.Generic;
 using System.Linq;
 using Microsoft.Extensions.DependencyInjection;
 using Bit.Core.Models.Table;
+using System.Text.Json;
 
 namespace Bit.Core.Repositories.EntityFramework
 {
@@ -23,7 +24,8 @@ namespace Bit.Core.Repositories.EntityFramework
             using (var scope = ServiceScopeFactory.CreateScope())
             {
                 var dbContext = GetDatabaseContext(scope);
-                return await GetDbSet(dbContext).FirstOrDefaultAsync(e => e.Email == email);
+                var entity = await GetDbSet(dbContext).FirstOrDefaultAsync(e => e.Email == email);
+                return Mapper.Map<TableModel.User>(entity);
             }
         }
 
@@ -46,11 +48,23 @@ namespace Bit.Core.Repositories.EntityFramework
             using (var scope = ServiceScopeFactory.CreateScope())
             {
                 var dbContext = GetDatabaseContext(scope);
-                var users = await GetDbSet(dbContext)
-                    .Where(e => email == null || e.Email.StartsWith(email))
-                    .OrderBy(e => e.Email)
-                    .Skip(skip).Take(take)
-                    .ToListAsync();
+                List<EFModel.User> users;
+                if (dbContext.Database.IsNpgsql())
+                {
+                    users = await GetDbSet(dbContext)
+                        .Where(e => e.Email == null || 
+                            EF.Functions.ILike(EF.Functions.Collate(e.Email, "default"), "a%"))
+                        .OrderBy(e => e.Email)
+                        .Skip(skip).Take(take)
+                        .ToListAsync();
+                }
+                else {
+                    users = await GetDbSet(dbContext)
+                        .Where(e => email == null || e.Email.StartsWith(email))
+                        .OrderBy(e => e.Email)
+                        .Skip(skip).Take(take)
+                        .ToListAsync();
+                }
                 return Mapper.Map<List<TableModel.User>>(users);
             }
         }
@@ -86,25 +100,7 @@ namespace Bit.Core.Repositories.EntityFramework
 
         public async Task UpdateStorageAsync(Guid id)
         {
-            using (var scope = ServiceScopeFactory.CreateScope())
-            {
-                var dbContext = GetDatabaseContext(scope);
-                var ciphers = await dbContext.Ciphers.Where(e => e.UserId == id).ToListAsync();
-                var storage = ciphers.Sum(e => e.AttachmentsJson?.RootElement.EnumerateArray()
-                    .Sum(p => p.GetProperty("Size").GetInt64()) ?? 0);
-                var user = new EFModel.User
-                {
-                    Id = id,
-                    RevisionDate = DateTime.UtcNow,
-                    Storage = storage,
-                };
-                var set = GetDbSet(dbContext);
-                set.Attach(user);
-                var entry = dbContext.Entry(user);
-                entry.Property(e => e.RevisionDate).IsModified = true;
-                entry.Property(e => e.Storage).IsModified = true;
-                await dbContext.SaveChangesAsync();
-            }
+            await base.UserUpdateStorage(id);
         }
 
         public async Task UpdateRenewalReminderDateAsync(Guid id, DateTime renewalReminderDate)
@@ -115,7 +111,7 @@ namespace Bit.Core.Repositories.EntityFramework
                 var user = new EFModel.User
                 {
                     Id = id,
-                    RenewalReminderDate = renewalReminderDate
+                    RenewalReminderDate = renewalReminderDate,
                 };
                 var set = GetDbSet(dbContext);
                 set.Attach(user);
@@ -124,14 +120,32 @@ namespace Bit.Core.Repositories.EntityFramework
             }
         }
 
-        public Task<User> GetBySsoUserAsync(string externalId, Guid? organizationId)
+        public async Task<User> GetBySsoUserAsync(string externalId, Guid? organizationId)
         {
-            throw new NotImplementedException();
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var ssoUser = await dbContext.SsoUsers.SingleOrDefaultAsync(e =>
+                    e.OrganizationId == organizationId && e.ExternalId == externalId);
+                
+                if (ssoUser == null)
+                {
+                    return null;
+                }
+
+                var entity = await dbContext.Users.SingleOrDefaultAsync(e => e.Id == ssoUser.UserId);
+                return Mapper.Map<TableModel.User>(entity);
+            }
         }
 
-        public Task<IEnumerable<User>> GetManyAsync(IEnumerable<Guid> ids)
+        public async Task<IEnumerable<User>> GetManyAsync(IEnumerable<Guid> ids)
         {
-            throw new NotImplementedException();
+            using (var scope = ServiceScopeFactory.CreateScope())
+            {
+                var dbContext = GetDatabaseContext(scope);
+                var users = dbContext.Users.Where(x => ids.Contains(x.Id));
+                return await users.ToListAsync();
+            }
         }
     }
 }
diff --git a/src/Core/Repositories/IProviderOrganizationProviderUserRepository.cs b/src/Core/Repositories/IProviderOrganizationProviderUserRepository.cs
index 64d54d11ea..8a4f05245d 100644
--- a/src/Core/Repositories/IProviderOrganizationProviderUserRepository.cs
+++ b/src/Core/Repositories/IProviderOrganizationProviderUserRepository.cs
@@ -3,7 +3,7 @@ using Bit.Core.Models.Table.Provider;
 
 namespace Bit.Core.Repositories
 {
-    public interface IProviderOrganizationProviderUserRepository : IRepository<Provider, Guid>
+    public interface IProviderOrganizationProviderUserRepository : IRepository<ProviderOrganizationProviderUser, Guid>
     {
     }
 }
diff --git a/src/Core/Repositories/IRepository.cs b/src/Core/Repositories/IRepository.cs
index bbb4e81af1..9402e22e18 100644
--- a/src/Core/Repositories/IRepository.cs
+++ b/src/Core/Repositories/IRepository.cs
@@ -7,7 +7,7 @@ namespace Bit.Core.Repositories
     public interface IRepository<T, TId> where TId : IEquatable<TId> where T : class, ITableObject<TId>
     {
         Task<T> GetByIdAsync(TId id);
-        Task CreateAsync(T obj);
+        Task<T> CreateAsync(T obj);
         Task ReplaceAsync(T obj);
         Task UpsertAsync(T obj);
         Task DeleteAsync(T obj);
diff --git a/src/Core/Repositories/PostgreSql/BasePostgreSqlRepository.cs b/src/Core/Repositories/PostgreSql/BasePostgreSqlRepository.cs
deleted file mode 100644
index 956d6fb977..0000000000
--- a/src/Core/Repositories/PostgreSql/BasePostgreSqlRepository.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using System.Text.RegularExpressions;
-using Dapper;
-
-namespace Bit.Core.Repositories.PostgreSql
-{
-    public abstract class BasePostgreSqlRepository : BaseRepository
-    {
-        static BasePostgreSqlRepository()
-        {
-            // Support snake case property names
-            DefaultTypeMap.MatchNamesWithUnderscores = true;
-        }
-
-        public BasePostgreSqlRepository(string connectionString, string readOnlyConnectionString)
-            : base(connectionString, readOnlyConnectionString)
-        { }
-
-        protected static string SnakeCase(string input)
-        {
-            if (string.IsNullOrWhiteSpace(input))
-            {
-                return input;
-            }
-            var startUnderscores = Regex.Match(input, @"^_+");
-            return startUnderscores + Regex.Replace(input, @"([a-z0-9])([A-Z])", "$1_$2").ToLowerInvariant();
-        }
-
-        protected static DynamicParameters ToParam<T>(T obj)
-        {
-            var dp = new DynamicParameters();
-            var properties = typeof(T).GetProperties();
-            foreach (var property in properties)
-            {
-                dp.Add($"_{SnakeCase(property.Name)}", property.GetValue(obj));
-            }
-            return dp;
-        }
-    }
-}
diff --git a/src/Core/Repositories/PostgreSql/Repository.cs b/src/Core/Repositories/PostgreSql/Repository.cs
deleted file mode 100644
index 1c9053c114..0000000000
--- a/src/Core/Repositories/PostgreSql/Repository.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-using System;
-using System.Data;
-using System.Linq;
-using System.Threading.Tasks;
-using Dapper;
-using Bit.Core.Models.Table;
-using Npgsql;
-
-namespace Bit.Core.Repositories.PostgreSql
-{
-    public abstract class Repository<T, TId> : BasePostgreSqlRepository, IRepository<T, TId>
-        where TId : IEquatable<TId>
-        where T : class, ITableObject<TId>
-    {
-        public Repository(string connectionString, string readOnlyConnectionString, string table = null)
-            : base(connectionString, readOnlyConnectionString)
-        {
-            if (!string.IsNullOrWhiteSpace(table))
-            {
-                Table = table;
-            }
-            else
-            {
-                Table = SnakeCase(typeof(T).Name).ToLowerInvariant();
-            }
-        }
-
-        protected string Table { get; private set; }
-
-        public virtual async Task<T> GetByIdAsync(TId id)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                var results = await connection.QueryAsync<T>(
-                    $"{Table}_read_by_id",
-                    ToParam(new { Id = id }),
-                    commandType: CommandType.StoredProcedure);
-
-                return results.SingleOrDefault();
-            }
-        }
-
-        public virtual async Task CreateAsync(T obj)
-        {
-            obj.SetNewId();
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                var results = await connection.ExecuteAsync(
-                    $"{Table}_create",
-                    ToParam(obj),
-                    commandType: CommandType.StoredProcedure);
-            }
-        }
-
-        public virtual async Task ReplaceAsync(T obj)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                var results = await connection.ExecuteAsync(
-                    $"{Table}_update",
-                    ToParam(obj),
-                    commandType: CommandType.StoredProcedure);
-            }
-        }
-
-        public virtual async Task UpsertAsync(T obj)
-        {
-            if (obj.Id.Equals(default(TId)))
-            {
-                await CreateAsync(obj);
-            }
-            else
-            {
-                await ReplaceAsync(obj);
-            }
-        }
-
-        public virtual async Task DeleteAsync(T obj)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                await connection.ExecuteAsync(
-                    $"{Table}_delete_by_id",
-                    ToParam(new { Id = obj.Id }),
-                    commandType: CommandType.StoredProcedure);
-            }
-        }
-    }
-}
diff --git a/src/Core/Repositories/PostgreSql/UserRepository.cs b/src/Core/Repositories/PostgreSql/UserRepository.cs
deleted file mode 100644
index a5ab31c4f0..0000000000
--- a/src/Core/Repositories/PostgreSql/UserRepository.cs
+++ /dev/null
@@ -1,170 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Data;
-using System.Linq;
-using System.Threading.Tasks;
-using Bit.Core.Models.Data;
-using Bit.Core.Models.Table;
-using Bit.Core.Settings;
-using Dapper;
-using Npgsql;
-
-namespace Bit.Core.Repositories.PostgreSql
-{
-    public class UserRepository : Repository<User, Guid>, IUserRepository
-    {
-        public UserRepository(GlobalSettings globalSettings)
-            : this(globalSettings.PostgreSql.ConnectionString, globalSettings.PostgreSql.ReadOnlyConnectionString)
-        { }
-
-        public UserRepository(string connectionString, string readOnlyConnectionString)
-            : base(connectionString, readOnlyConnectionString)
-        { }
-
-        public override async Task<User> GetByIdAsync(Guid id)
-        {
-            return await base.GetByIdAsync(id);
-        }
-
-        public async Task<User> GetByEmailAsync(string email)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                var results = await connection.QueryAsync<User>(
-                    "user_read_by_email",
-                    ToParam(new { Email = email }),
-                    commandType: CommandType.StoredProcedure);
-
-                return results.SingleOrDefault();
-            }
-        }
-
-        public async Task<UserKdfInformation> GetKdfInformationByEmailAsync(string email)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                var results = await connection.QueryAsync<UserKdfInformation>(
-                    "user_read_kdf_by_email",
-                    ToParam(new { Email = email }),
-                    commandType: CommandType.StoredProcedure);
-
-                return results.SingleOrDefault();
-            }
-        }
-
-        public async Task<ICollection<User>> SearchAsync(string email, int skip, int take)
-        {
-            using (var connection = new NpgsqlConnection(ReadOnlyConnectionString))
-            {
-                var results = await connection.QueryAsync<User>(
-                    "user_search",
-                    ToParam(new { Email = email, Skip = skip, Take = take }),
-                    commandType: CommandType.StoredProcedure,
-                    commandTimeout: 120);
-
-                return results.ToList();
-            }
-        }
-
-        public async Task<ICollection<User>> GetManyByPremiumAsync(bool premium)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                var results = await connection.QueryAsync<User>(
-                    "user_read_by_premium",
-                    ToParam(new { Premium = premium }),
-                    commandType: CommandType.StoredProcedure);
-
-                return results.ToList();
-            }
-        }
-
-        public async Task<ICollection<User>> GetManyByPremiumRenewalAsync()
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                var results = await connection.QueryAsync<User>(
-                    "user_read_by_premium_renewal",
-                    commandType: CommandType.StoredProcedure);
-
-                return results.ToList();
-            }
-        }
-
-        public async Task<string> GetPublicKeyAsync(Guid id)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                var results = await connection.QueryAsync<string>(
-                    "user_read_public_key_by_id",
-                    ToParam(new { Id = id }),
-                    commandType: CommandType.StoredProcedure);
-
-                return results.SingleOrDefault();
-            }
-        }
-
-        public async Task<DateTime> GetAccountRevisionDateAsync(Guid id)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                var results = await connection.QueryAsync<DateTime>(
-                    "user_read_account_revision_date_by_id",
-                    ToParam(new { Id = id }),
-                    commandType: CommandType.StoredProcedure);
-
-                return results.SingleOrDefault();
-            }
-        }
-
-        public override async Task ReplaceAsync(User user)
-        {
-            await base.ReplaceAsync(user);
-        }
-
-        public override async Task DeleteAsync(User user)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                await connection.ExecuteAsync(
-                    $"user_delete_by_id",
-                    ToParam(new { Id = user.Id }),
-                    commandType: CommandType.StoredProcedure,
-                    commandTimeout: 180);
-            }
-        }
-
-        public async Task UpdateStorageAsync(Guid id)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                await connection.ExecuteAsync(
-                    "user_update_storage",
-                    ToParam(new { Id = id }),
-                    commandType: CommandType.StoredProcedure,
-                    commandTimeout: 180);
-            }
-        }
-
-        public async Task UpdateRenewalReminderDateAsync(Guid id, DateTime renewalReminderDate)
-        {
-            using (var connection = new NpgsqlConnection(ConnectionString))
-            {
-                await connection.ExecuteAsync(
-                    "user_update_renewal_reminder_date",
-                    ToParam(new { Id = id, RenewalReminderDate = renewalReminderDate }),
-                    commandType: CommandType.StoredProcedure);
-            }
-        }
-
-        public Task<User> GetBySsoUserAsync(string externalId, Guid? organizationId)
-        {
-            throw new NotImplementedException();
-        }
-        
-        public Task<IEnumerable<User>> GetManyAsync(IEnumerable<Guid> ids)
-        {
-            throw new NotImplementedException();
-        }
-    }
-}
diff --git a/src/Core/Repositories/SqlServer/GroupRepository.cs b/src/Core/Repositories/SqlServer/GroupRepository.cs
index 7d128c88a3..a41777057e 100644
--- a/src/Core/Repositories/SqlServer/GroupRepository.cs
+++ b/src/Core/Repositories/SqlServer/GroupRepository.cs
@@ -141,10 +141,5 @@ namespace Bit.Core.Repositories.SqlServer
                     commandType: CommandType.StoredProcedure);
             }
         }
-
-        public class GroupWithCollections : Group
-        {
-            public DataTable Collections { get; set; }
-        }
     }
 }
diff --git a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs
index c204a5c5f1..3fb672708f 100644
--- a/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs
+++ b/src/Core/Repositories/SqlServer/OrganizationUserRepository.cs
@@ -271,11 +271,6 @@ namespace Bit.Core.Repositories.SqlServer
             }
         }
 
-        public class OrganizationUserWithCollections : OrganizationUser
-        {
-            public DataTable Collections { get; set; }
-        }
-
         public async Task<ICollection<OrganizationUser>> GetManyByManyUsersAsync(IEnumerable<Guid> userIds)
         {
             using (var connection = new SqlConnection(ConnectionString))
diff --git a/src/Core/Repositories/SqlServer/ProviderOrganizationProviderUserRepository.cs b/src/Core/Repositories/SqlServer/ProviderOrganizationProviderUserRepository.cs
index 8a71203b93..8cac8b3658 100644
--- a/src/Core/Repositories/SqlServer/ProviderOrganizationProviderUserRepository.cs
+++ b/src/Core/Repositories/SqlServer/ProviderOrganizationProviderUserRepository.cs
@@ -4,7 +4,7 @@ using Bit.Core.Settings;
 
 namespace Bit.Core.Repositories.SqlServer
 {
-    public class ProviderOrganizationProviderUserRepository : Repository<Provider, Guid>, IProviderOrganizationProviderUserRepository
+    public class ProviderOrganizationProviderUserRepository : Repository<ProviderOrganizationProviderUser, Guid>, IProviderOrganizationProviderUserRepository
     {
         public ProviderOrganizationProviderUserRepository(GlobalSettings globalSettings)
             : this(globalSettings.SqlServer.ConnectionString, globalSettings.SqlServer.ReadOnlyConnectionString)
diff --git a/src/Core/Repositories/SqlServer/Repository.cs b/src/Core/Repositories/SqlServer/Repository.cs
index 838fd70cb9..2d6714651a 100644
--- a/src/Core/Repositories/SqlServer/Repository.cs
+++ b/src/Core/Repositories/SqlServer/Repository.cs
@@ -43,16 +43,21 @@ namespace Bit.Core.Repositories.SqlServer
             }
         }
 
-        public virtual async Task CreateAsync(T obj)
+        public virtual async Task<T> CreateAsync(T obj)
         {
             obj.SetNewId();
             using (var connection = new SqlConnection(ConnectionString))
             {
+                var parameters = new DynamicParameters();
+                parameters.AddDynamicParams(obj);
+                parameters.Add("Id", obj.Id, direction: ParameterDirection.InputOutput);
                 var results = await connection.ExecuteAsync(
                     $"[{Schema}].[{Table}_Create]",
-                    obj,
+                    parameters,
                     commandType: CommandType.StoredProcedure);
+                obj.Id = parameters.Get<TId>(nameof(obj.Id));
             }
+            return obj;
         }
 
         public virtual async Task ReplaceAsync(T obj)
diff --git a/src/Core/Repositories/SqlServer/U2fRepository.cs b/src/Core/Repositories/SqlServer/U2fRepository.cs
index 591a299137..55335bcc84 100644
--- a/src/Core/Repositories/SqlServer/U2fRepository.cs
+++ b/src/Core/Repositories/SqlServer/U2fRepository.cs
@@ -44,11 +44,6 @@ namespace Bit.Core.Repositories.SqlServer
             }
         }
 
-        public override Task<U2f> GetByIdAsync(int id)
-        {
-            throw new NotSupportedException();
-        }
-
         public override Task ReplaceAsync(U2f obj)
         {
             throw new NotSupportedException();
diff --git a/src/Core/Services/Implementations/I18nViewLocalizer.cs b/src/Core/Services/Implementations/I18nViewLocalizer.cs
index b094351144..7164275016 100644
--- a/src/Core/Services/Implementations/I18nViewLocalizer.cs
+++ b/src/Core/Services/Implementations/I18nViewLocalizer.cs
@@ -30,8 +30,5 @@ namespace Bit.Core.Services
         public LocalizedString GetString(string name) => _stringLocalizer[name];
         public LocalizedString GetString(string name, params object[] arguments) =>
             _stringLocalizer[name, arguments];
-
-        [Obsolete("This method is obsolete. Use `CurrentCulture` and `CurrentUICulture` instead.")]
-        public IHtmlLocalizer WithCulture(CultureInfo culture) => _htmlLocalizer.WithCulture(culture);
     }
 }
diff --git a/src/Core/Settings/GlobalSettings.cs b/src/Core/Settings/GlobalSettings.cs
index 717cc1fdb3..95ca661ebf 100644
--- a/src/Core/Settings/GlobalSettings.cs
+++ b/src/Core/Settings/GlobalSettings.cs
@@ -43,8 +43,11 @@ namespace Bit.Core.Settings
         public virtual CaptchaSettings Captcha { get; set; } = new CaptchaSettings();
         public virtual InstallationSettings Installation { get; set; } = new InstallationSettings();
         public virtual BaseServiceUriSettings BaseServiceUri { get; set; }
+        public virtual string DatabaseProvider { get; set; }
         public virtual SqlSettings SqlServer { get; set; } = new SqlSettings();
         public virtual SqlSettings PostgreSql { get; set; } = new SqlSettings();
+        public virtual SqlSettings MySql { get; set; } = new SqlSettings();
+        public virtual SqlSettings Sqlite { get; set; } = new SqlSettings();
         public virtual MailSettings Mail { get; set; } = new MailSettings();
         public virtual ConnectionStringSettings Storage { get; set; } = new ConnectionStringSettings();
         public virtual ConnectionStringSettings Events { get; set; } = new ConnectionStringSettings();
diff --git a/src/Core/Utilities/ServiceCollectionExtensions.cs b/src/Core/Utilities/ServiceCollectionExtensions.cs
index c5b9bd717d..1590be802f 100644
--- a/src/Core/Utilities/ServiceCollectionExtensions.cs
+++ b/src/Core/Utilities/ServiceCollectionExtensions.cs
@@ -18,6 +18,7 @@ using Bit.Core.Utilities;
 using IdentityModel;
 using IdentityServer4.AccessTokenValidation;
 using IdentityServer4.Configuration;
+using LinqToDB.EntityFrameworkCore;
 using Microsoft.AspNetCore.Authentication.Cookies;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Builder;
@@ -46,56 +47,108 @@ namespace Bit.Core.Utilities
     {
         public static void AddSqlServerRepositories(this IServiceCollection services, GlobalSettings globalSettings)
         {
-            var usePostgreSql = CoreHelpers.SettingHasValue(globalSettings.PostgreSql?.ConnectionString);
-            var useEf = usePostgreSql;
+            var selectedDatabaseProvider = globalSettings.DatabaseProvider;
+            var provider = SupportedDatabaseProviders.SqlServer;
+            var connectionString = string.Empty;
+            if (!string.IsNullOrWhiteSpace(selectedDatabaseProvider))
+            {
+                switch (selectedDatabaseProvider.ToLowerInvariant())
+                {
+                    case "postgres":
+                    case "postgresql":
+                        provider = SupportedDatabaseProviders.Postgres;
+                        connectionString = globalSettings.PostgreSql.ConnectionString;
+                        break;
+                    case "mysql":
+                    case "mariadb":
+                        provider = SupportedDatabaseProviders.MySql;
+                        connectionString = globalSettings.MySql.ConnectionString;
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+            var useEf = (provider != SupportedDatabaseProviders.SqlServer);
 
             if (useEf)
             {
+                if (string.IsNullOrWhiteSpace(connectionString))
+                {
+                    throw new Exception($"Database provider type {provider} was selected but no connection string was found.");
+                }
+                LinqToDBForEFTools.Initialize();
                 services.AddAutoMapper(typeof(EntityFrameworkRepos.UserRepository));
                 services.AddDbContext<EntityFrameworkRepos.DatabaseContext>(options =>
                 {
-                    if (usePostgreSql)
+                    if (provider == SupportedDatabaseProviders.Postgres)
                     {
-                        options.UseNpgsql(globalSettings.PostgreSql.ConnectionString);
+                        options.UseNpgsql(connectionString);
+                    } 
+                    else if (provider == SupportedDatabaseProviders.MySql)
+                    {
+                        options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
                     }
                 });
+                services.AddSingleton<ICipherRepository, EntityFrameworkRepos.CipherRepository>();
+                services.AddSingleton<ICollectionCipherRepository, EntityFrameworkRepos.CollectionCipherRepository>();
+                services.AddSingleton<ICollectionRepository, EntityFrameworkRepos.CollectionRepository>();
+                services.AddSingleton<IDeviceRepository, EntityFrameworkRepos.DeviceRepository>();
+                services.AddSingleton<IEmergencyAccessRepository, EntityFrameworkRepos.EmergencyAccessRepository>();
+                services.AddSingleton<IFolderRepository, EntityFrameworkRepos.FolderRepository>();
+                services.AddSingleton<IGrantRepository, EntityFrameworkRepos.GrantRepository>();
+                services.AddSingleton<IGroupRepository, EntityFrameworkRepos.GroupRepository>();
+                services.AddSingleton<IInstallationRepository, EntityFrameworkRepos.InstallationRepository>();
+                services.AddSingleton<IMaintenanceRepository, EntityFrameworkRepos.MaintenanceRepository>();
+                services.AddSingleton<IOrganizationRepository, EntityFrameworkRepos.OrganizationRepository>();
+                services.AddSingleton<IOrganizationUserRepository, EntityFrameworkRepos.OrganizationUserRepository>();
+                services.AddSingleton<IPolicyRepository, EntityFrameworkRepos.PolicyRepository>();
+                services.AddSingleton<ISendRepository, EntityFrameworkRepos.SendRepository>();
+                services.AddSingleton<ISsoConfigRepository, EntityFrameworkRepos.SsoConfigRepository>();
+                services.AddSingleton<ISsoUserRepository, EntityFrameworkRepos.SsoUserRepository>();
+                services.AddSingleton<ITaxRateRepository, EntityFrameworkRepos.TaxRateRepository>();
+                services.AddSingleton<ITransactionRepository, EntityFrameworkRepos.TransactionRepository>();
+                services.AddSingleton<IU2fRepository, EntityFrameworkRepos.U2fRepository>();
                 services.AddSingleton<IUserRepository, EntityFrameworkRepos.UserRepository>();
-                //services.AddSingleton<ICipherRepository, EntityFrameworkRepos.CipherRepository>();
-                //services.AddSingleton<IOrganizationRepository, EntityFrameworkRepos.OrganizationRepository>();
+                services.AddSingleton<IProviderRepository, EntityFrameworkRepos.ProviderRepository>();
+                services.AddSingleton<IProviderUserRepository, EntityFrameworkRepos.ProviderUserRepository>();
+                services.AddSingleton<IProviderOrganizationRepository, EntityFrameworkRepos.ProviderOrganizationRepository>();
+                services.AddSingleton<IProviderOrganizationProviderUserRepository, EntityFrameworkRepos.ProviderOrganizationProviderUserRepository>();
             }
             else
             {
-                services.AddSingleton<IUserRepository, SqlServerRepos.UserRepository>();
                 services.AddSingleton<ICipherRepository, SqlServerRepos.CipherRepository>();
-                services.AddSingleton<IDeviceRepository, SqlServerRepos.DeviceRepository>();
-                services.AddSingleton<IGrantRepository, SqlServerRepos.GrantRepository>();
-                services.AddSingleton<IOrganizationRepository, SqlServerRepos.OrganizationRepository>();
-                services.AddSingleton<IOrganizationUserRepository, SqlServerRepos.OrganizationUserRepository>();
-                services.AddSingleton<ICollectionRepository, SqlServerRepos.CollectionRepository>();
-                services.AddSingleton<IFolderRepository, SqlServerRepos.FolderRepository>();
                 services.AddSingleton<ICollectionCipherRepository, SqlServerRepos.CollectionCipherRepository>();
+                services.AddSingleton<ICollectionRepository, SqlServerRepos.CollectionRepository>();
+                services.AddSingleton<IDeviceRepository, SqlServerRepos.DeviceRepository>();
+                services.AddSingleton<IEmergencyAccessRepository, SqlServerRepos.EmergencyAccessRepository>();
+                services.AddSingleton<IFolderRepository, SqlServerRepos.FolderRepository>();
+                services.AddSingleton<IGrantRepository, SqlServerRepos.GrantRepository>();
                 services.AddSingleton<IGroupRepository, SqlServerRepos.GroupRepository>();
-                services.AddSingleton<IU2fRepository, SqlServerRepos.U2fRepository>();
                 services.AddSingleton<IInstallationRepository, SqlServerRepos.InstallationRepository>();
                 services.AddSingleton<IMaintenanceRepository, SqlServerRepos.MaintenanceRepository>();
-                services.AddSingleton<ITransactionRepository, SqlServerRepos.TransactionRepository>();
+                services.AddSingleton<IOrganizationRepository, SqlServerRepos.OrganizationRepository>();
+                services.AddSingleton<IOrganizationUserRepository, SqlServerRepos.OrganizationUserRepository>();
                 services.AddSingleton<IPolicyRepository, SqlServerRepos.PolicyRepository>();
+                services.AddSingleton<ISendRepository, SqlServerRepos.SendRepository>();
                 services.AddSingleton<ISsoConfigRepository, SqlServerRepos.SsoConfigRepository>();
                 services.AddSingleton<ISsoUserRepository, SqlServerRepos.SsoUserRepository>();
-                services.AddSingleton<ISendRepository, SqlServerRepos.SendRepository>();
                 services.AddSingleton<ITaxRateRepository, SqlServerRepos.TaxRateRepository>();
                 services.AddSingleton<IEmergencyAccessRepository, SqlServerRepos.EmergencyAccessRepository>();
                 services.AddSingleton<IProviderRepository, SqlServerRepos.ProviderRepository>();
                 services.AddSingleton<IProviderUserRepository, SqlServerRepos.ProviderUserRepository>();
                 services.AddSingleton<IProviderOrganizationRepository, SqlServerRepos.ProviderOrganizationRepository>();
                 services.AddSingleton<IProviderOrganizationProviderUserRepository, SqlServerRepos.ProviderOrganizationProviderUserRepository>();
+                services.AddSingleton<ITransactionRepository, SqlServerRepos.TransactionRepository>();
+                services.AddSingleton<IU2fRepository, SqlServerRepos.U2fRepository>();
+                services.AddSingleton<IUserRepository, SqlServerRepos.UserRepository>();
             }
 
             if (globalSettings.SelfHosted)
             {
                 if (useEf)
                 {
-                    // TODO
+                    services.AddSingleton<IEventRepository, EntityFrameworkRepos.EventRepository>();
                 }
                 else
                 {
diff --git a/src/Events/Dockerfile b/src/Events/Dockerfile
index e361700faa..8668004ffb 100644
--- a/src/Events/Dockerfile
+++ b/src/Events/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden"
 
diff --git a/src/Icons/Dockerfile b/src/Icons/Dockerfile
index 97d1eb764d..104b9e9880 100644
--- a/src/Icons/Dockerfile
+++ b/src/Icons/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden"
 
diff --git a/src/Identity/Dockerfile b/src/Identity/Dockerfile
index 9ef1c0cc5d..2985d60f4d 100644
--- a/src/Identity/Dockerfile
+++ b/src/Identity/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden"
 
diff --git a/src/Notifications/Dockerfile b/src/Notifications/Dockerfile
index e361700faa..8668004ffb 100644
--- a/src/Notifications/Dockerfile
+++ b/src/Notifications/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden"
 
diff --git a/src/Notifications/Notifications.csproj b/src/Notifications/Notifications.csproj
index 831f03e899..959401ea5f 100644
--- a/src/Notifications/Notifications.csproj
+++ b/src/Notifications/Notifications.csproj
@@ -5,8 +5,8 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.1.6" />
-    <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="3.1.6" />
+    <PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="5.0.2" />
+    <PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="5.0.2" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/src/Notifications/Startup.cs b/src/Notifications/Startup.cs
index 4ce00909de..e6d82617ea 100644
--- a/src/Notifications/Startup.cs
+++ b/src/Notifications/Startup.cs
@@ -52,10 +52,8 @@ namespace Bit.Notifications
             // SignalR
             var signalRServerBuilder = services.AddSignalR().AddMessagePackProtocol(options =>
             {
-                options.FormatterResolvers = new List<MessagePack.IFormatterResolver>()
-                {
-                    MessagePack.Resolvers.ContractlessStandardResolver.Instance
-                };
+                options.SerializerOptions = MessagePack.MessagePackSerializerOptions.Standard
+                    .WithResolver(MessagePack.Resolvers.ContractlessStandardResolver.Instance);
             });
             if (CoreHelpers.SettingHasValue(globalSettings.Notifications?.RedisConnectionString))
             {
diff --git a/src/Sql/dbo/Stored Procedures/Cipher_Create.sql b/src/Sql/dbo/Stored Procedures/Cipher_Create.sql
index ae8910842c..8bf7ce3a77 100644
--- a/src/Sql/dbo/Stored Procedures/Cipher_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Cipher_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Cipher_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @UserId UNIQUEIDENTIFIER,
     @OrganizationId UNIQUEIDENTIFIER,
     @Type TINYINT,
@@ -54,4 +54,4 @@ BEGIN
     BEGIN
         EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
     END
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/Cipher_DeleteAttachment.sql b/src/Sql/dbo/Stored Procedures/Cipher_DeleteAttachment.sql
index 380045e87a..5983f557c2 100644
--- a/src/Sql/dbo/Stored Procedures/Cipher_DeleteAttachment.sql	
+++ b/src/Sql/dbo/Stored Procedures/Cipher_DeleteAttachment.sql	
@@ -35,4 +35,4 @@ BEGIN
         EXEC [dbo].[User_UpdateStorage] @UserId
         EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
     END
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/CollectionCipher_Create.sql b/src/Sql/dbo/Stored Procedures/CollectionCipher_Create.sql
index 52ae9b0f2a..54b7695266 100644
--- a/src/Sql/dbo/Stored Procedures/CollectionCipher_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/CollectionCipher_Create.sql	
@@ -21,4 +21,4 @@ BEGIN
     BEGIN
         EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @CollectionId, @OrganizationId
     END
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/Collection_Create.sql b/src/Sql/dbo/Stored Procedures/Collection_Create.sql
index c9e2f11853..2e442c6a28 100644
--- a/src/Sql/dbo/Stored Procedures/Collection_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Collection_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Collection_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @OrganizationId UNIQUEIDENTIFIER,
     @Name VARCHAR(MAX),
     @ExternalId NVARCHAR(300),
@@ -29,4 +29,4 @@ BEGIN
     )
 
     EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/Device_Create.sql b/src/Sql/dbo/Stored Procedures/Device_Create.sql
index cad719d7af..e40460ad7d 100644
--- a/src/Sql/dbo/Stored Procedures/Device_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Device_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Device_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @UserId UNIQUEIDENTIFIER,
     @Name NVARCHAR(50),
     @Type TINYINT,
@@ -33,4 +33,4 @@ BEGIN
         @CreationDate,
         @RevisionDate
     )
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/EmergencyAccess_Create.sql b/src/Sql/dbo/Stored Procedures/EmergencyAccess_Create.sql
index b949b7bf7f..211fb7ca1a 100644
--- a/src/Sql/dbo/Stored Procedures/EmergencyAccess_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/EmergencyAccess_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[EmergencyAccess_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @GrantorId UNIQUEIDENTIFIER,
     @GranteeId UNIQUEIDENTIFIER,
     @Email NVARCHAR(256),
@@ -45,4 +45,4 @@ BEGIN
         @CreationDate,
         @RevisionDate
     )
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/EmergencyAccess_ReadToNotify.sql b/src/Sql/dbo/Stored Procedures/EmergencyAccess_ReadToNotify.sql
index 320773c95e..e81b0ee5f7 100644
--- a/src/Sql/dbo/Stored Procedures/EmergencyAccess_ReadToNotify.sql	
+++ b/src/Sql/dbo/Stored Procedures/EmergencyAccess_ReadToNotify.sql	
@@ -20,4 +20,4 @@ BEGIN
         DATEADD(DAY, EA.[WaitTimeDays] - 1, EA.[RecoveryInitiatedDate]) <= GETUTCDATE()
     AND
         DATEADD(DAY, 1, EA.[LastNotificationDate]) <= GETUTCDATE()
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/Event_ReadyById.sql b/src/Sql/dbo/Stored Procedures/Event_ReadyById.sql
new file mode 100644
index 0000000000..71e3b28660
--- /dev/null
+++ b/src/Sql/dbo/Stored Procedures/Event_ReadyById.sql	
@@ -0,0 +1,13 @@
+CREATE PROCEDURE [dbo].[Event_ReadById]
+    @Id UNIQUEIDENTIFIER
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    SELECT
+        *
+    FROM
+        [dbo].[Event]
+    WHERE
+        [Id] = @Id
+END
diff --git a/src/Sql/dbo/Stored Procedures/Folder_Create.sql b/src/Sql/dbo/Stored Procedures/Folder_Create.sql
index 7b38c7283c..41bd2a4621 100644
--- a/src/Sql/dbo/Stored Procedures/Folder_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Folder_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Folder_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @UserId UNIQUEIDENTIFIER,
     @Name VARCHAR(MAX),
     @CreationDate DATETIME2(7),
@@ -26,4 +26,4 @@ BEGIN
     )
 
     EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/Group_Create.sql b/src/Sql/dbo/Stored Procedures/Group_Create.sql
index f47df20897..893cd57e38 100644
--- a/src/Sql/dbo/Stored Procedures/Group_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Group_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Group_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @OrganizationId UNIQUEIDENTIFIER,
     @Name NVARCHAR(100),
     @AccessAll BIT,
@@ -30,4 +30,4 @@ BEGIN
         @CreationDate,
         @RevisionDate
     )
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/Installation_Create.sql b/src/Sql/dbo/Stored Procedures/Installation_Create.sql
index 121ed30b2c..8c91a5b81a 100644
--- a/src/Sql/dbo/Stored Procedures/Installation_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Installation_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Installation_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @Email NVARCHAR(256),
     @Key VARCHAR(150),
     @Enabled BIT,
@@ -24,4 +24,4 @@ BEGIN
         @Enabled,
         @CreationDate
     )
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_Create.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_Create.sql
index dd7c738e12..9dacb45f91 100644
--- a/src/Sql/dbo/Stored Procedures/OrganizationUser_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[OrganizationUser_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @OrganizationId UNIQUEIDENTIFIER,
     @UserId UNIQUEIDENTIFIER,
     @Email NVARCHAR(256),
diff --git a/src/Sql/dbo/Stored Procedures/Organization_Create.sql b/src/Sql/dbo/Stored Procedures/Organization_Create.sql
index cea32a9cef..7082edd4ed 100644
--- a/src/Sql/dbo/Stored Procedures/Organization_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Organization_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Organization_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @Identifier NVARCHAR(50),
     @Name NVARCHAR(50),
     @BusinessName NVARCHAR(50),
diff --git a/src/Sql/dbo/Stored Procedures/Policy_Create.sql b/src/Sql/dbo/Stored Procedures/Policy_Create.sql
index c2aea915f4..44934b0500 100644
--- a/src/Sql/dbo/Stored Procedures/Policy_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Policy_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Policy_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @OrganizationId UNIQUEIDENTIFIER,
     @Type TINYINT,
     @Data NVARCHAR(MAX),
@@ -32,4 +32,4 @@ BEGIN
     )
 
     EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/Send_Create.sql b/src/Sql/dbo/Stored Procedures/Send_Create.sql
index 037b069f17..0cfe60b44f 100644
--- a/src/Sql/dbo/Stored Procedures/Send_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Send_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Send_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @UserId UNIQUEIDENTIFIER,
     @OrganizationId UNIQUEIDENTIFIER,
     @Type TINYINT,
diff --git a/src/Sql/dbo/Stored Procedures/SsoConfig_DeleteById.sql b/src/Sql/dbo/Stored Procedures/SsoConfig_DeleteById.sql
new file mode 100644
index 0000000000..e6343dfe08
--- /dev/null
+++ b/src/Sql/dbo/Stored Procedures/SsoConfig_DeleteById.sql	
@@ -0,0 +1,12 @@
+CREATE PROCEDURE [dbo].[SsoConfig_DeleteById]
+    @Id BIGINT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    DELETE
+    FROM
+        [dbo].[SsoConfig]
+    WHERE
+        [Id] = @Id
+END
\ No newline at end of file
diff --git a/src/Sql/dbo/Stored Procedures/SsoConfig_ReadById.sql b/src/Sql/dbo/Stored Procedures/SsoConfig_ReadById.sql
new file mode 100644
index 0000000000..fbca19bf15
--- /dev/null
+++ b/src/Sql/dbo/Stored Procedures/SsoConfig_ReadById.sql	
@@ -0,0 +1,13 @@
+CREATE PROCEDURE [dbo].[SsoUser_ReadById]
+    @Id BIGINT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    SELECT
+        *
+    FROM
+        [dbo].[SsoUserView]
+    WHERE
+        [Id] = @Id
+END
\ No newline at end of file
diff --git a/src/Sql/dbo/Stored Procedures/SsoUser_DeleteById.sql b/src/Sql/dbo/Stored Procedures/SsoUser_DeleteById.sql
new file mode 100644
index 0000000000..046f717e12
--- /dev/null
+++ b/src/Sql/dbo/Stored Procedures/SsoUser_DeleteById.sql	
@@ -0,0 +1,12 @@
+CREATE PROCEDURE [dbo].[SsoUser_DeleteById]
+    @Id BIGINT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    DELETE
+    FROM
+        [dbo].[SsoUser]
+    WHERE
+        [Id] = @Id
+END
diff --git a/src/Sql/dbo/Stored Procedures/TaxRate_Create.sql b/src/Sql/dbo/Stored Procedures/TaxRate_Create.sql
index 5dc6a186b0..be88fe60b3 100644
--- a/src/Sql/dbo/Stored Procedures/TaxRate_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/TaxRate_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[TaxRate_Create]
-    @Id VARCHAR(40),
+    @Id VARCHAR(40) OUTPUT,
     @Country VARCHAR(50),
     @State VARCHAR(2),
     @PostalCode VARCHAR(10),
diff --git a/src/Sql/dbo/Stored Procedures/Transaction_Create.sql b/src/Sql/dbo/Stored Procedures/Transaction_Create.sql
index 0f9efba271..a46d9195da 100644
--- a/src/Sql/dbo/Stored Procedures/Transaction_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/Transaction_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[Transaction_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @UserId UNIQUEIDENTIFIER,
     @OrganizationId UNIQUEIDENTIFIER,
     @Type TINYINT,
@@ -45,4 +45,4 @@ BEGIN
         @GatewayId,
         @CreationDate
     )
-END
\ No newline at end of file
+END
diff --git a/src/Sql/dbo/Stored Procedures/U2f_Create.sql b/src/Sql/dbo/Stored Procedures/U2f_Create.sql
index c7b85b3569..b495f2652e 100644
--- a/src/Sql/dbo/Stored Procedures/U2f_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/U2f_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[U2f_Create]
-    @Id INT,
+    @Id INT OUTPUT,
     @UserId UNIQUEIDENTIFIER,
     @KeyHandle VARCHAR(200),
     @Challenge VARCHAR(200),
@@ -28,4 +28,6 @@ BEGIN
         @Version,
         @CreationDate
     )
-END
\ No newline at end of file
+
+    SET @Id = (SELECT SCOPE_IDENTITY())
+END
diff --git a/src/Sql/dbo/Stored Procedures/User_Create.sql b/src/Sql/dbo/Stored Procedures/User_Create.sql
index cdb8bda180..a28e146170 100644
--- a/src/Sql/dbo/Stored Procedures/User_Create.sql	
+++ b/src/Sql/dbo/Stored Procedures/User_Create.sql	
@@ -1,5 +1,5 @@
 CREATE PROCEDURE [dbo].[User_Create]
-    @Id UNIQUEIDENTIFIER,
+    @Id UNIQUEIDENTIFIER OUTPUT,
     @Name NVARCHAR(50),
     @Email NVARCHAR(256),
     @EmailVerified BIT,
diff --git a/src/Sql/dbo/Views/SsoUserView.sql b/src/Sql/dbo/Views/SsoUserView.sql
new file mode 100644
index 0000000000..bd29b1b55c
--- /dev/null
+++ b/src/Sql/dbo/Views/SsoUserView.sql
@@ -0,0 +1,6 @@
+CREATE VIEW [dbo].[SsoUserView]
+AS
+SELECT
+    *
+FROM
+    [dbo].[SsoUser]
diff --git a/test/Core.Test/AutoFixture/Attributes/CiSkippedTheory.cs b/test/Core.Test/AutoFixture/Attributes/CiSkippedTheory.cs
new file mode 100644
index 0000000000..446ee3197b
--- /dev/null
+++ b/test/Core.Test/AutoFixture/Attributes/CiSkippedTheory.cs
@@ -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";
+            }
+        }
+    }
+}
diff --git a/test/Core.Test/AutoFixture/CipherFixtures.cs b/test/Core.Test/AutoFixture/CipherFixtures.cs
index 410f6e11fb..30d21f132a 100644
--- a/test/Core.Test/AutoFixture/CipherFixtures.cs
+++ b/test/Core.Test/AutoFixture/CipherFixtures.cs
@@ -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)
+        { }
+    }
 }
diff --git a/test/Core.Test/AutoFixture/CollectionCipherFixtures.cs b/test/Core.Test/AutoFixture/CollectionCipherFixtures.cs
new file mode 100644
index 0000000000..54bc7524cf
--- /dev/null
+++ b/test/Core.Test/AutoFixture/CollectionCipherFixtures.cs
@@ -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)
+        { }
+    }
+}
diff --git a/test/Core.Test/AutoFixture/CollectionFixtures.cs b/test/Core.Test/AutoFixture/CollectionFixtures.cs
index 22acefef4d..adad029d86 100644
--- a/test/Core.Test/AutoFixture/CollectionFixtures.cs
+++ b/test/Core.Test/AutoFixture/CollectionFixtures.cs
@@ -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())
+        { }
+    }
+}
diff --git a/test/Core.Test/AutoFixture/DeviceFixtures.cs b/test/Core.Test/AutoFixture/DeviceFixtures.cs
new file mode 100644
index 0000000000..17472c5fb7
--- /dev/null
+++ b/test/Core.Test/AutoFixture/DeviceFixtures.cs
@@ -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)
+        { }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/EmergencyAccessFixtures.cs b/test/Core.Test/AutoFixture/EmergencyAccessFixtures.cs
new file mode 100644
index 0000000000..cdf240803c
--- /dev/null
+++ b/test/Core.Test/AutoFixture/EmergencyAccessFixtures.cs
@@ -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)
+        { }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/EntityFrameworkRepositoryFixtures.cs b/test/Core.Test/AutoFixture/EntityFrameworkRepositoryFixtures.cs
new file mode 100644
index 0000000000..fdc5e79fe5
--- /dev/null
+++ b/test/Core.Test/AutoFixture/EntityFrameworkRepositoryFixtures.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/AutoFixture/EventFixtures.cs b/test/Core.Test/AutoFixture/EventFixtures.cs
new file mode 100644
index 0000000000..b903b2639f
--- /dev/null
+++ b/test/Core.Test/AutoFixture/EventFixtures.cs
@@ -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)
+        { }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/FolderFixtures.cs b/test/Core.Test/AutoFixture/FolderFixtures.cs
new file mode 100644
index 0000000000..9449ae71c3
--- /dev/null
+++ b/test/Core.Test/AutoFixture/FolderFixtures.cs
@@ -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)
+        { }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/GlobalSettingsFixtures.cs b/test/Core.Test/AutoFixture/GlobalSettingsFixtures.cs
index 55f482126a..9eea0b063c 100644
--- a/test/Core.Test/AutoFixture/GlobalSettingsFixtures.cs
+++ b/test/Core.Test/AutoFixture/GlobalSettingsFixtures.cs
@@ -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)
diff --git a/test/Core.Test/AutoFixture/GrantFixtures.cs b/test/Core.Test/AutoFixture/GrantFixtures.cs
new file mode 100644
index 0000000000..a0142a29ad
--- /dev/null
+++ b/test/Core.Test/AutoFixture/GrantFixtures.cs
@@ -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)
+        { }
+    }
+}
diff --git a/test/Core.Test/AutoFixture/GroupFixtures.cs b/test/Core.Test/AutoFixture/GroupFixtures.cs
index cb780761f0..77190ce7b4 100644
--- a/test/Core.Test/AutoFixture/GroupFixtures.cs
+++ b/test/Core.Test/AutoFixture/GroupFixtures.cs
@@ -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)
         { }
     }
 }
diff --git a/test/Core.Test/AutoFixture/GroupUserFixtures.cs b/test/Core.Test/AutoFixture/GroupUserFixtures.cs
new file mode 100644
index 0000000000..1ee09445e5
--- /dev/null
+++ b/test/Core.Test/AutoFixture/GroupUserFixtures.cs
@@ -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)
+        { }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/InstallationFixtures.cs b/test/Core.Test/AutoFixture/InstallationFixtures.cs
new file mode 100644
index 0000000000..8e1aa74eee
--- /dev/null
+++ b/test/Core.Test/AutoFixture/InstallationFixtures.cs
@@ -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)
+        { }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/OrganizationFixtures.cs b/test/Core.Test/AutoFixture/OrganizationFixtures.cs
index 5fd953270a..36f61e4d1c 100644
--- a/test/Core.Test/AutoFixture/OrganizationFixtures.cs
+++ b/test/Core.Test/AutoFixture/OrganizationFixtures.cs
@@ -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)
+        { }
+    }
 }
diff --git a/test/Core.Test/AutoFixture/OrganizationUserFixtures.cs b/test/Core.Test/AutoFixture/OrganizationUserFixtures.cs
index 96c4f95afa..f5e5256dd0 100644
--- a/test/Core.Test/AutoFixture/OrganizationUserFixtures.cs
+++ b/test/Core.Test/AutoFixture/OrganizationUserFixtures.cs
@@ -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)
+        { }
+    }
 }
diff --git a/test/Core.Test/AutoFixture/PolicyFixtures.cs b/test/Core.Test/AutoFixture/PolicyFixtures.cs
index ad79ff1cfe..f53cd271cb 100644
--- a/test/Core.Test/AutoFixture/PolicyFixtures.cs
+++ b/test/Core.Test/AutoFixture/PolicyFixtures.cs
@@ -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)
+        { }
+    }
 }
diff --git a/test/Core.Test/AutoFixture/Relays/MaxLengthStringRelay.cs b/test/Core.Test/AutoFixture/Relays/MaxLengthStringRelay.cs
new file mode 100644
index 0000000000..38e3a1a9c5
--- /dev/null
+++ b/test/Core.Test/AutoFixture/Relays/MaxLengthStringRelay.cs
@@ -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));
+        }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/SendFixtures.cs b/test/Core.Test/AutoFixture/SendFixtures.cs
index 5847684013..1588837c6e 100644
--- a/test/Core.Test/AutoFixture/SendFixtures.cs
+++ b/test/Core.Test/AutoFixture/SendFixtures.cs
@@ -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,
+            })
+        { }
+    }
 }
diff --git a/test/Core.Test/AutoFixture/SsoConfigFixtures.cs b/test/Core.Test/AutoFixture/SsoConfigFixtures.cs
new file mode 100644
index 0000000000..c41f31be40
--- /dev/null
+++ b/test/Core.Test/AutoFixture/SsoConfigFixtures.cs
@@ -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)
+        { }
+    }
+}
diff --git a/test/Core.Test/AutoFixture/SsoUserFixtures.cs b/test/Core.Test/AutoFixture/SsoUserFixtures.cs
new file mode 100644
index 0000000000..bb756a73bc
--- /dev/null
+++ b/test/Core.Test/AutoFixture/SsoUserFixtures.cs
@@ -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)
+        { }
+    }
+}
diff --git a/test/Core.Test/AutoFixture/SutProvider.cs b/test/Core.Test/AutoFixture/SutProvider.cs
index a3cfc210d7..e8b475d248 100644
--- a/test/Core.Test/AutoFixture/SutProvider.cs
+++ b/test/Core.Test/AutoFixture/SutProvider.cs
@@ -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
 {
diff --git a/test/Core.Test/AutoFixture/TaxRateFixtures.cs b/test/Core.Test/AutoFixture/TaxRateFixtures.cs
new file mode 100644
index 0000000000..b0a94eacce
--- /dev/null
+++ b/test/Core.Test/AutoFixture/TaxRateFixtures.cs
@@ -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)
+        { }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/TransactionFixutres.cs b/test/Core.Test/AutoFixture/TransactionFixutres.cs
new file mode 100644
index 0000000000..e2660c8c7a
--- /dev/null
+++ b/test/Core.Test/AutoFixture/TransactionFixutres.cs
@@ -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,
+            })
+        { }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/U2fFixtures.cs b/test/Core.Test/AutoFixture/U2fFixtures.cs
new file mode 100644
index 0000000000..d813fd20ea
--- /dev/null
+++ b/test/Core.Test/AutoFixture/U2fFixtures.cs
@@ -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)
+        { }
+    }
+}
+
diff --git a/test/Core.Test/AutoFixture/UserFixtures.cs b/test/Core.Test/AutoFixture/UserFixtures.cs
new file mode 100644
index 0000000000..1ef978fb07
--- /dev/null
+++ b/test/Core.Test/AutoFixture/UserFixtures.cs
@@ -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)
+        { }
+    }
+}
diff --git a/test/Core.Test/Core.Test.csproj b/test/Core.Test/Core.Test.csproj
index 9ed29918d5..fe0812b797 100644
--- a/test/Core.Test/Core.Test.csproj
+++ b/test/Core.Test/Core.Test.csproj
@@ -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>
diff --git a/test/Core.Test/Helpers/Factories.cs b/test/Core.Test/Helpers/Factories.cs
new file mode 100644
index 0000000000..61469a543a
--- /dev/null
+++ b/test/Core.Test/Helpers/Factories.cs
@@ -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);
+            }
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/CipherRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/CipherRepositoryTests.cs
new file mode 100644
index 0000000000..8613949953
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/CipherRepositoryTests.cs
@@ -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);
+            }
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/CollectionRepository.cs b/test/Core.Test/Repositories/EntityFramework/CollectionRepository.cs
new file mode 100644
index 0000000000..b29d265af7
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/CollectionRepository.cs
@@ -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());
+        }        
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/DeviceRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/DeviceRepositoryTests.cs
new file mode 100644
index 0000000000..33d3bf66a4
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/DeviceRepositoryTests.cs
@@ -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());
+        }
+        
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EmergencyAccessRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/EmergencyAccessRepositoryTests.cs
new file mode 100644
index 0000000000..aaf00bbfdd
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EmergencyAccessRepositoryTests.cs
@@ -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());
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/CipherCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/CipherCompare.cs
new file mode 100644
index 0000000000..979ea7e7b5
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/CipherCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/CollectionCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/CollectionCompare.cs
new file mode 100644
index 0000000000..99aaa4e6b1
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/CollectionCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/DeviceCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/DeviceCompare.cs
new file mode 100644
index 0000000000..ae4defa0ff
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/DeviceCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/EmergencyAccessCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/EmergencyAccessCompare.cs
new file mode 100644
index 0000000000..2564f418ca
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/EmergencyAccessCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/EventCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/EventCompare.cs
new file mode 100644
index 0000000000..ea278388c4
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/EventCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/FolderCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/FolderCompare.cs
new file mode 100644
index 0000000000..1f0a832e60
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/FolderCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/GrantCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/GrantCompare.cs
new file mode 100644
index 0000000000..09d8f01817
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/GrantCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/GroupCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/GroupCompare.cs
new file mode 100644
index 0000000000..1b06b3fbfb
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/GroupCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/InstallationCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/InstallationCompare.cs
new file mode 100644
index 0000000000..380a348e7e
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/InstallationCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/OrganizationCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/OrganizationCompare.cs
new file mode 100644
index 0000000000..d8f51febf1
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/OrganizationCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/OrganizationUserCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/OrganizationUserCompare.cs
new file mode 100644
index 0000000000..7bad311228
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/OrganizationUserCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/PolicyCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/PolicyCompare.cs
new file mode 100644
index 0000000000..f17d63b8b5
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/PolicyCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/SendCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/SendCompare.cs
new file mode 100644
index 0000000000..9a590c5483
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/SendCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/SsoConfigCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/SsoConfigCompare.cs
new file mode 100644
index 0000000000..fbffd9cb0a
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/SsoConfigCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/SsoUserCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/SsoUserCompare.cs
new file mode 100644
index 0000000000..7b6dabd8b4
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/SsoUserCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/TaxRateCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/TaxRateCompare.cs
new file mode 100644
index 0000000000..88127de4dd
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/TaxRateCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/TransactionCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/TransactionCompare.cs
new file mode 100644
index 0000000000..fbf0d981bc
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/TransactionCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/U2fCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/U2fCompare.cs
new file mode 100644
index 0000000000..3cf4d154b0
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/U2fCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/UserCompare.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/UserCompare.cs
new file mode 100644
index 0000000000..552dfc7d8f
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/UserCompare.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/EqualityComparers/UserKdfInformation.cs b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/UserKdfInformation.cs
new file mode 100644
index 0000000000..d69c767137
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/EqualityComparers/UserKdfInformation.cs
@@ -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();
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/FolderRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/FolderRepositoryTests.cs
new file mode 100644
index 0000000000..717b422863
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/FolderRepositoryTests.cs
@@ -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());
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/InstallationRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/InstallationRepositoryTests.cs
new file mode 100644
index 0000000000..70f70f3254
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/InstallationRepositoryTests.cs
@@ -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());
+        }        
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/OrganizationRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/OrganizationRepositoryTests.cs
new file mode 100644
index 0000000000..7f6a2a19f2
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/OrganizationRepositoryTests.cs
@@ -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)));
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/OrganizationUserRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/OrganizationUserRepositoryTests.cs
new file mode 100644
index 0000000000..0d6b44bb2e
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/OrganizationUserRepositoryTests.cs
@@ -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);
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/PolicyRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/PolicyRepositoryTests.cs
new file mode 100644
index 0000000000..b6fe5b83b5
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/PolicyRepositoryTests.cs
@@ -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());
+        }        
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/SendRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/SendRepositoryTests.cs
new file mode 100644
index 0000000000..5f3e9fec61
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/SendRepositoryTests.cs
@@ -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());
+       } 
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/SsoConfigRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/SsoConfigRepositoryTests.cs
new file mode 100644
index 0000000000..584ac56b67
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/SsoConfigRepositoryTests.cs
@@ -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));
+            }
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/SsoUserRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/SsoUserRepositoryTests.cs
new file mode 100644
index 0000000000..3e772ab5e9
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/SsoUserRepositoryTests.cs
@@ -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);
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/TaxRateRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/TaxRateRepositoryTests.cs
new file mode 100644
index 0000000000..594c6e2dcb
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/TaxRateRepositoryTests.cs
@@ -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());
+        }        
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/TransactionRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/TransactionRepositoryTests.cs
new file mode 100644
index 0000000000..43458eac59
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/TransactionRepositoryTests.cs
@@ -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());
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/U2fRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/U2fRepositoryTests.cs
new file mode 100644
index 0000000000..906438827d
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/U2fRepositoryTests.cs
@@ -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());
+        }
+    }
+}
diff --git a/test/Core.Test/Repositories/EntityFramework/UserRepositoryTests.cs b/test/Core.Test/Repositories/EntityFramework/UserRepositoryTests.cs
new file mode 100644
index 0000000000..8b4623f527
--- /dev/null
+++ b/test/Core.Test/Repositories/EntityFramework/UserRepositoryTests.cs
@@ -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());
+        }
+    }
+}
diff --git a/test/Core.Test/Services/CollectionServiceTests.cs b/test/Core.Test/Services/CollectionServiceTests.cs
index d41dcb030f..b1748e8587 100644
--- a/test/Core.Test/Services/CollectionServiceTests.cs
+++ b/test/Core.Test/Services/CollectionServiceTests.cs
@@ -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;
 
diff --git a/test/Core.Test/Services/GroupServiceTests.cs b/test/Core.Test/Services/GroupServiceTests.cs
index 3cb14f85a1..3b8467ce37 100644
--- a/test/Core.Test/Services/GroupServiceTests.cs
+++ b/test/Core.Test/Services/GroupServiceTests.cs
@@ -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;
 
diff --git a/test/Core.Test/Services/OrganizationServiceTests.cs b/test/Core.Test/Services/OrganizationServiceTests.cs
index 93afbc5651..033202202b 100644
--- a/test/Core.Test/Services/OrganizationServiceTests.cs
+++ b/test/Core.Test/Services/OrganizationServiceTests.cs
@@ -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
 {
diff --git a/test/Core.Test/Services/PolicyServiceTests.cs b/test/Core.Test/Services/PolicyServiceTests.cs
index ae04805b34..b344e1877c 100644
--- a/test/Core.Test/Services/PolicyServiceTests.cs
+++ b/test/Core.Test/Services/PolicyServiceTests.cs
@@ -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
 
diff --git a/util/Migrator/DbScripts/2021-07-08_00_EntityFrameworkSupport.sql b/util/Migrator/DbScripts/2021-07-08_00_EntityFrameworkSupport.sql
new file mode 100644
index 0000000000..570a8c44a6
--- /dev/null
+++ b/util/Migrator/DbScripts/2021-07-08_00_EntityFrameworkSupport.sql
@@ -0,0 +1,1047 @@
+-- Tech debt: creates a few views and procedures that we implement as base repository methods but that would throw exceptions on use for not existing in the DB
+IF EXISTS(SELECT * FROM sys.views WHERE [Name] = 'SsoUserView')
+BEGIN
+    DROP VIEW [dbo].[SsoUserView];
+END
+GO
+
+CREATE VIEW [dbo].[SsoUserView]
+AS
+SELECT
+    *
+FROM
+    [dbo].[SsoUser]
+GO
+
+IF OBJECT_ID('[dbo].[SsoConfig_ReadById]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[SsoConfig_ReadById]
+END
+GO
+
+CREATE PROCEDURE [dbo].[SsoConfig_ReadById]
+    @Id BIGINT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    SELECT
+        *
+    FROM
+        [dbo].[SsoConfigView]
+    WHERE
+        [Id] = @Id
+END
+GO
+
+IF OBJECT_ID('[dbo].[SsoUser_DeleteById]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[SsoUser_DeleteById]
+END
+GO
+
+CREATE PROCEDURE [dbo].[SsoUser_DeleteById]
+    @Id BIGINT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    DELETE
+    FROM
+        [dbo].[SsoUser]
+    WHERE
+        [Id] = @Id
+END
+GO
+
+IF OBJECT_ID('[dbo].[SsoConfig_DeleteById]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[SsoConfig_DeleteById]
+END
+GO
+CREATE PROCEDURE [dbo].[SsoConfig_DeleteById]
+    @Id BIGINT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    DELETE
+    FROM
+        [dbo].[SsoConfig]
+    WHERE
+        [Id] = @Id
+END
+GO
+
+IF OBJECT_ID('[dbo].[Event_ReadById]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Event_ReadById]
+END
+GO
+CREATE PROCEDURE [dbo].[Event_ReadById]
+    @Id UNIQUEIDENTIFIER
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    SELECT
+        *
+    FROM
+        [dbo].[Event]
+    WHERE
+        [Id] = @Id
+END
+GO
+
+IF OBJECT_ID('[dbo].[U2f_ReadById]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[U2f_ReadById]
+END
+GO
+CREATE PROCEDURE [dbo].[U2f_ReadById]
+    @Id BIGINT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    SELECT
+        *
+    FROM
+        [dbo].[U2f]
+    WHERE
+        [Id] = @Id
+END
+GO
+-- Refactor: Set all the base Create procs to output the ID for testing
+IF OBJECT_ID('[dbo].[Organization_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Organization_Create]
+END
+GO
+
+CREATE PROCEDURE [dbo].[Organization_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @Identifier NVARCHAR(50),
+    @Name NVARCHAR(50),
+    @BusinessName NVARCHAR(50),
+    @BusinessAddress1 NVARCHAR(50),
+    @BusinessAddress2 NVARCHAR(50),
+    @BusinessAddress3 NVARCHAR(50),
+    @BusinessCountry VARCHAR(2),
+    @BusinessTaxNumber NVARCHAR(30),
+    @BillingEmail NVARCHAR(256),
+    @Plan NVARCHAR(50),
+    @PlanType TINYINT,
+    @Seats INT,
+    @MaxCollections SMALLINT,
+    @UsePolicies BIT,
+    @UseSso BIT,
+    @UseGroups BIT,
+    @UseDirectory BIT,
+    @UseEvents BIT,
+    @UseTotp BIT,
+    @Use2fa BIT,
+    @UseApi BIT,
+    @UseResetPassword BIT,
+    @SelfHost BIT,
+    @UsersGetPremium BIT,
+    @Storage BIGINT,
+    @MaxStorageGb SMALLINT,
+    @Gateway TINYINT,
+    @GatewayCustomerId VARCHAR(50),
+    @GatewaySubscriptionId VARCHAR(50),
+    @ReferenceData VARCHAR(MAX),
+    @Enabled BIT,
+    @LicenseKey VARCHAR(100),
+    @ApiKey VARCHAR(30),
+    @PublicKey VARCHAR(MAX),
+    @PrivateKey VARCHAR(MAX),
+    @TwoFactorProviders NVARCHAR(MAX),
+    @ExpirationDate DATETIME2(7),
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Organization]
+    (
+        [Id],
+        [Identifier],
+        [Name],
+        [BusinessName],
+        [BusinessAddress1],
+        [BusinessAddress2],
+        [BusinessAddress3],
+        [BusinessCountry],
+        [BusinessTaxNumber],
+        [BillingEmail],
+        [Plan],
+        [PlanType],
+        [Seats],
+        [MaxCollections],
+        [UsePolicies],
+        [UseSso],
+        [UseGroups],
+        [UseDirectory],
+        [UseEvents],
+        [UseTotp],
+        [Use2fa],
+        [UseApi],
+        [UseResetPassword],
+        [SelfHost],
+        [UsersGetPremium],
+        [Storage],
+        [MaxStorageGb],
+        [Gateway],
+        [GatewayCustomerId],
+        [GatewaySubscriptionId],
+        [ReferenceData],
+        [Enabled],
+        [LicenseKey],
+        [ApiKey],
+        [PublicKey],
+        [PrivateKey],
+        [TwoFactorProviders],
+        [ExpirationDate],
+        [CreationDate],
+        [RevisionDate]
+    )
+    VALUES
+    (
+        @Id,
+        @Identifier,
+        @Name,
+        @BusinessName,
+        @BusinessAddress1,
+        @BusinessAddress2,
+        @BusinessAddress3,
+        @BusinessCountry,
+        @BusinessTaxNumber,
+        @BillingEmail,
+        @Plan,
+        @PlanType,
+        @Seats,
+        @MaxCollections,
+        @UsePolicies,
+        @UseSso,
+        @UseGroups,
+        @UseDirectory,
+        @UseEvents,
+        @UseTotp,
+        @Use2fa,
+        @UseApi,
+        @UseResetPassword,
+        @SelfHost,
+        @UsersGetPremium,
+        @Storage,
+        @MaxStorageGb,
+        @Gateway,
+        @GatewayCustomerId,
+        @GatewaySubscriptionId,
+        @ReferenceData,
+        @Enabled,
+        @LicenseKey,
+        @ApiKey,
+        @PublicKey,
+        @PrivateKey,
+        @TwoFactorProviders,
+        @ExpirationDate,
+        @CreationDate,
+        @RevisionDate
+    )
+END
+GO 
+
+IF OBJECT_ID('[dbo].[User_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[User_Create]
+END
+GO
+
+CREATE PROCEDURE [dbo].[User_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @Name NVARCHAR(50),
+    @Email NVARCHAR(256),
+    @EmailVerified BIT,
+    @MasterPassword NVARCHAR(300),
+    @MasterPasswordHint NVARCHAR(50),
+    @Culture NVARCHAR(10),
+    @SecurityStamp NVARCHAR(50),
+    @TwoFactorProviders NVARCHAR(MAX),
+    @TwoFactorRecoveryCode NVARCHAR(32),
+    @EquivalentDomains NVARCHAR(MAX),
+    @ExcludedGlobalEquivalentDomains NVARCHAR(MAX),
+    @AccountRevisionDate DATETIME2(7),
+    @Key NVARCHAR(MAX),
+    @PublicKey NVARCHAR(MAX),
+    @PrivateKey NVARCHAR(MAX),
+    @Premium BIT,
+    @PremiumExpirationDate DATETIME2(7),
+    @RenewalReminderDate DATETIME2(7),
+    @Storage BIGINT,
+    @MaxStorageGb SMALLINT,
+    @Gateway TINYINT,
+    @GatewayCustomerId VARCHAR(50),
+    @GatewaySubscriptionId VARCHAR(50),
+    @ReferenceData VARCHAR(MAX),
+    @LicenseKey VARCHAR(100),
+    @Kdf TINYINT,
+    @KdfIterations INT,
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7),
+    @ApiKey VARCHAR(30)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[User]
+    (
+        [Id],
+        [Name],
+        [Email],
+        [EmailVerified],
+        [MasterPassword],
+        [MasterPasswordHint],
+        [Culture],
+        [SecurityStamp],
+        [TwoFactorProviders],
+        [TwoFactorRecoveryCode],
+        [EquivalentDomains],
+        [ExcludedGlobalEquivalentDomains],
+        [AccountRevisionDate],
+        [Key],
+        [PublicKey],
+        [PrivateKey],
+        [Premium],
+        [PremiumExpirationDate],
+        [RenewalReminderDate],
+        [Storage],
+        [MaxStorageGb],
+        [Gateway],
+        [GatewayCustomerId],
+        [GatewaySubscriptionId],
+        [ReferenceData],
+        [LicenseKey],
+        [Kdf],
+        [KdfIterations],
+        [CreationDate],
+        [RevisionDate],
+        [ApiKey]
+    )
+    VALUES
+    (
+        @Id,
+        @Name,
+        @Email,
+        @EmailVerified,
+        @MasterPassword,
+        @MasterPasswordHint,
+        @Culture,
+        @SecurityStamp,
+        @TwoFactorProviders,
+        @TwoFactorRecoveryCode,
+        @EquivalentDomains,
+        @ExcludedGlobalEquivalentDomains,
+        @AccountRevisionDate,
+        @Key,
+        @PublicKey,
+        @PrivateKey,
+        @Premium,
+        @PremiumExpirationDate,
+        @RenewalReminderDate,
+        @Storage,
+        @MaxStorageGb,
+        @Gateway,
+        @GatewayCustomerId,
+        @GatewaySubscriptionId,
+        @ReferenceData,
+        @LicenseKey,
+        @Kdf,
+        @KdfIterations,
+        @CreationDate,
+        @RevisionDate,
+        @ApiKey
+    )
+END
+GO
+
+IF OBJECT_ID('[dbo].[OrganizationUser_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[OrganizationUser_Create]
+END
+GO
+
+CREATE PROCEDURE [dbo].[OrganizationUser_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @OrganizationId UNIQUEIDENTIFIER,
+    @UserId UNIQUEIDENTIFIER,
+    @Email NVARCHAR(256),
+    @Key VARCHAR(MAX),
+    @Status TINYINT,
+    @Type TINYINT,
+    @AccessAll BIT,
+    @ExternalId NVARCHAR(300),
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7),
+    @Permissions NVARCHAR(MAX),
+    @ResetPasswordKey VARCHAR(MAX)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[OrganizationUser]
+    (
+        [Id],
+        [OrganizationId],
+        [UserId],
+        [Email],
+        [Key],
+        [Status],
+        [Type],
+        [AccessAll],
+        [ExternalId],
+        [CreationDate],
+        [RevisionDate],
+        [Permissions],
+        [ResetPasswordKey]
+    )
+    VALUES
+    (
+        @Id,
+        @OrganizationId,
+        @UserId,
+        @Email,
+        @Key,
+        @Status,
+        @Type,
+        @AccessAll,
+        @ExternalId,
+        @CreationDate,
+        @RevisionDate,
+        @Permissions,
+        @ResetPasswordKey
+    )
+END
+GO
+
+IF OBJECT_ID('[dbo].[Cipher_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Cipher_Create]
+END
+GO
+
+CREATE PROCEDURE [dbo].[Cipher_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @UserId UNIQUEIDENTIFIER,
+    @OrganizationId UNIQUEIDENTIFIER,
+    @Type TINYINT,
+    @Data NVARCHAR(MAX),
+    @Favorites NVARCHAR(MAX),
+    @Folders NVARCHAR(MAX),
+    @Attachments NVARCHAR(MAX),
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7),
+    @DeletedDate DATETIME2(7),
+    @Reprompt TINYINT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Cipher]
+    (
+        [Id],
+        [UserId],
+        [OrganizationId],
+        [Type],
+        [Data],
+        [Favorites],
+        [Folders],
+        [Attachments],
+        [CreationDate],
+        [RevisionDate],
+        [DeletedDate],
+        [Reprompt]
+    )
+    VALUES
+    (
+        @Id,
+        CASE WHEN @OrganizationId IS NULL THEN @UserId ELSE NULL END,
+        @OrganizationId,
+        @Type,
+        @Data,
+        @Favorites,
+        @Folders,
+        @Attachments,
+        @CreationDate,
+        @RevisionDate,
+        @DeletedDate,
+        @Reprompt
+    )
+
+    IF @OrganizationId IS NOT NULL
+    BEGIN
+        EXEC [dbo].[User_BumpAccountRevisionDateByCipherId] @Id, @OrganizationId
+    END
+    ELSE IF @UserId IS NOT NULL
+    BEGIN
+        EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
+    END
+END
+GO
+
+IF OBJECT_ID('[dbo].[Device_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Device_Create]
+END
+GO
+CREATE PROCEDURE [dbo].[Device_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @UserId UNIQUEIDENTIFIER,
+    @Name NVARCHAR(50),
+    @Type TINYINT,
+    @Identifier NVARCHAR(50),
+    @PushToken NVARCHAR(255),
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Device]
+    (
+        [Id],
+        [UserId],
+        [Name],
+        [Type],
+        [Identifier],
+        [PushToken],
+        [CreationDate],
+        [RevisionDate]
+    )
+    VALUES
+    (
+        @Id,
+        @UserId,
+        @Name,
+        @Type,
+        @Identifier,
+        @PushToken,
+        @CreationDate,
+        @RevisionDate
+    )
+END
+GO
+
+IF OBJECT_ID('[dbo].[Collection_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Collection_Create]
+END
+GO
+CREATE PROCEDURE [dbo].[Collection_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @OrganizationId UNIQUEIDENTIFIER,
+    @Name VARCHAR(MAX),
+    @ExternalId NVARCHAR(300),
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Collection]
+    (
+        [Id],
+        [OrganizationId],
+        [Name],
+        [ExternalId],
+        [CreationDate],
+        [RevisionDate]
+    )
+    VALUES
+    (
+        @Id,
+        @OrganizationId,
+        @Name,
+        @ExternalId,
+        @CreationDate,
+        @RevisionDate
+    )
+
+    EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId
+END
+GO
+
+IF OBJECT_ID('[dbo].[EmergencyAccess_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[EmergencyAccess_Create]
+END
+GO
+CREATE PROCEDURE [dbo].[EmergencyAccess_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @GrantorId UNIQUEIDENTIFIER,
+    @GranteeId UNIQUEIDENTIFIER,
+    @Email NVARCHAR(256),
+    @KeyEncrypted VARCHAR(MAX),
+    @Type TINYINT,
+    @Status TINYINT,
+    @WaitTimeDays SMALLINT,
+    @RecoveryInitiatedDate DATETIME2(7),
+    @LastNotificationDate DATETIME2(7),
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[EmergencyAccess]
+    (
+        [Id],
+        [GrantorId],
+        [GranteeId],
+        [Email],
+        [KeyEncrypted],
+        [Type],
+        [Status],
+        [WaitTimeDays],
+        [RecoveryInitiatedDate],
+        [LastNotificationDate],
+        [CreationDate],
+        [RevisionDate]
+    )
+    VALUES
+    (
+        @Id,
+        @GrantorId,
+        @GranteeId,
+        @Email,
+        @KeyEncrypted,
+        @Type,
+        @Status,
+        @WaitTimeDays,
+        @RecoveryInitiatedDate,
+        @LastNotificationDate,
+        @CreationDate,
+        @RevisionDate
+    )
+END
+GO
+
+IF OBJECT_ID('[dbo].[Event_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Event_Create]
+END
+GO
+CREATE PROCEDURE [dbo].[Event_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @Type INT,
+    @UserId UNIQUEIDENTIFIER,
+    @OrganizationId UNIQUEIDENTIFIER,
+    @CipherId UNIQUEIDENTIFIER,
+    @CollectionId UNIQUEIDENTIFIER,
+    @PolicyId UNIQUEIDENTIFIER,
+    @GroupId UNIQUEIDENTIFIER,
+    @OrganizationUserId UNIQUEIDENTIFIER,
+    @ActingUserId UNIQUEIDENTIFIER,
+    @DeviceType SMALLINT,
+    @IpAddress VARCHAR(50),
+    @Date DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Event]
+    (
+        [Id],
+        [Type],
+        [UserId],
+        [OrganizationId],
+        [CipherId],
+        [CollectionId],
+        [PolicyId],
+        [GroupId],
+        [OrganizationUserId],
+        [ActingUserId],
+        [DeviceType],
+        [IpAddress],
+        [Date]
+    )
+    VALUES
+    (
+        @Id,
+        @Type,
+        @UserId,
+        @OrganizationId,
+        @CipherId,
+        @CollectionId,
+        @PolicyId,
+        @GroupId,
+        @OrganizationUserId,
+        @ActingUserId,
+        @DeviceType,
+        @IpAddress,
+        @Date
+    )
+END
+GO
+
+IF OBJECT_ID('[dbo].[Folder_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Folder_Create]
+END
+GO
+
+CREATE PROCEDURE [dbo].[Folder_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @UserId UNIQUEIDENTIFIER,
+    @Name VARCHAR(MAX),
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Folder]
+    (
+        [Id],
+        [UserId],
+        [Name],
+        [CreationDate],
+        [RevisionDate]
+    )
+    VALUES
+    (
+        @Id,
+        @UserId,
+        @Name,
+        @CreationDate,
+        @RevisionDate
+    )
+
+    EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
+END
+GO
+IF OBJECT_ID('[dbo].[Group_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Group_Create]
+END
+GO
+CREATE PROCEDURE [dbo].[Group_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @OrganizationId UNIQUEIDENTIFIER,
+    @Name NVARCHAR(100),
+    @AccessAll BIT,
+    @ExternalId NVARCHAR(300),
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Group]
+    (
+        [Id],
+        [OrganizationId],
+        [Name],
+        [AccessAll],
+        [ExternalId],
+        [CreationDate],
+        [RevisionDate]
+    )
+    VALUES
+    (
+        @Id,
+        @OrganizationId,
+        @Name,
+        @AccessAll,
+        @ExternalId,
+        @CreationDate,
+        @RevisionDate
+    )
+END
+GO
+IF OBJECT_ID('[dbo].[Installation_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Installation_Create]
+END
+GO
+CREATE PROCEDURE [dbo].[Installation_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @Email NVARCHAR(256),
+    @Key VARCHAR(150),
+    @Enabled BIT,
+    @CreationDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Installation]
+    (
+        [Id],
+        [Email],
+        [Key],
+        [Enabled],
+        [CreationDate]
+    )
+    VALUES
+    (
+        @Id,
+        @Email,
+        @Key,
+        @Enabled,
+        @CreationDate
+    )
+END
+GO
+IF OBJECT_ID('[dbo].[Policy_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Policy_Create]
+END
+GO
+CREATE PROCEDURE [dbo].[Policy_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @OrganizationId UNIQUEIDENTIFIER,
+    @Type TINYINT,
+    @Data NVARCHAR(MAX),
+    @Enabled BIT,
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Policy]
+    (
+        [Id],
+        [OrganizationId],
+        [Type],
+        [Data],
+        [Enabled],
+        [CreationDate],
+        [RevisionDate]
+    )
+    VALUES
+    (
+        @Id,
+        @OrganizationId,
+        @Type,
+        @Data,
+        @Enabled,
+        @CreationDate,
+        @RevisionDate
+    )
+
+    EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId
+END
+GO
+
+IF OBJECT_ID('[dbo].[Send_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Send_Create]
+END
+GO
+
+CREATE PROCEDURE [dbo].[Send_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @UserId UNIQUEIDENTIFIER,
+    @OrganizationId UNIQUEIDENTIFIER,
+    @Type TINYINT,
+    @Data VARCHAR(MAX),
+    @Key VARCHAR(MAX),
+    @Password NVARCHAR(300),
+    @MaxAccessCount INT,
+    @AccessCount INT,
+    @CreationDate DATETIME2(7),
+    @RevisionDate DATETIME2(7),
+    @ExpirationDate DATETIME2(7),
+    @DeletionDate DATETIME2(7),
+    @Disabled BIT,
+    @HideEmail BIT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Send]
+    (
+        [Id],
+        [UserId],
+        [OrganizationId],
+        [Type],
+        [Data],
+        [Key],
+        [Password],
+        [MaxAccessCount],
+        [AccessCount],
+        [CreationDate],
+        [RevisionDate],
+        [ExpirationDate],
+        [DeletionDate],
+        [Disabled],
+        [HideEmail]
+    )
+    VALUES
+    (
+        @Id,
+        @UserId,
+        @OrganizationId,
+        @Type,
+        @Data,
+        @Key,
+        @Password,
+        @MaxAccessCount,
+        @AccessCount,
+        @CreationDate,
+        @RevisionDate,
+        @ExpirationDate,
+        @DeletionDate,
+        @Disabled,
+        @HideEmail
+    )
+
+    IF @UserId IS NOT NULL
+    BEGIN
+        IF @Type = 1 --File
+        BEGIN
+            EXEC [dbo].[User_UpdateStorage] @UserId
+        END
+        EXEC [dbo].[User_BumpAccountRevisionDate] @UserId
+    END
+    -- TODO: OrganizationId bump?
+END
+GO
+
+IF OBJECT_ID('[dbo].[TaxRate_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[TaxRate_Create]
+END
+GO
+
+
+CREATE PROCEDURE [dbo].[TaxRate_Create]
+    @Id VARCHAR(40) OUTPUT,
+    @Country VARCHAR(50),
+    @State VARCHAR(2),
+    @PostalCode VARCHAR(10),
+    @Rate DECIMAL(5,2),
+    @Active BIT
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[TaxRate]
+    (
+        [Id],
+        [Country],
+        [State],
+        [PostalCode],
+        [Rate],
+        [Active]
+    )
+    VALUES
+    (
+        @Id,
+        @Country,
+        @State,
+        @PostalCode,
+        @Rate,
+        1
+    )
+END
+GO
+
+IF OBJECT_ID('[dbo].[Transaction_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[Transaction_Create]
+END
+GO
+
+CREATE PROCEDURE [dbo].[Transaction_Create]
+    @Id UNIQUEIDENTIFIER OUTPUT,
+    @UserId UNIQUEIDENTIFIER,
+    @OrganizationId UNIQUEIDENTIFIER,
+    @Type TINYINT,
+    @Amount MONEY,
+    @Refunded BIT,
+    @RefundedAmount MONEY,
+    @Details NVARCHAR(100),
+    @PaymentMethodType TINYINT,
+    @Gateway TINYINT,
+    @GatewayId VARCHAR(50),
+    @CreationDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[Transaction]
+    (
+        [Id],
+        [UserId],
+        [OrganizationId],
+        [Type],
+        [Amount],
+        [Refunded],
+        [RefundedAmount],
+        [Details],
+        [PaymentMethodType],
+        [Gateway],
+        [GatewayId],
+        [CreationDate]
+    )
+    VALUES
+    (
+        @Id,
+        @UserId,
+        @OrganizationId,
+        @Type,
+        @Amount,
+        @Refunded,
+        @RefundedAmount,
+        @Details,
+        @PaymentMethodType,
+        @Gateway,
+        @GatewayId,
+        @CreationDate
+    )
+END
+GO
+
+IF OBJECT_ID('[dbo].[U2f_Create]') IS NOT NULL
+BEGIN
+    DROP PROCEDURE [dbo].[U2f_Create]
+END
+GO
+
+CREATE PROCEDURE [dbo].[U2f_Create]
+    @Id INT OUTPUT,
+    @UserId UNIQUEIDENTIFIER,
+    @KeyHandle VARCHAR(200),
+    @Challenge VARCHAR(200),
+    @AppId VARCHAR(50),
+    @Version VARCHAR(20),
+    @CreationDate DATETIME2(7)
+AS
+BEGIN
+    SET NOCOUNT ON
+
+    INSERT INTO [dbo].[U2f]
+    (
+        [UserId],
+        [KeyHandle],
+        [Challenge],
+        [AppId],
+        [Version],
+        [CreationDate]
+    )
+    VALUES
+    (
+        @UserId,
+        @KeyHandle,
+        @Challenge,
+        @AppId,
+        @Version,
+        @CreationDate
+    )
+
+    SET @Id = (SELECT scope_identity())
+END
+GO
diff --git a/util/Migrator/Migrator.csproj b/util/Migrator/Migrator.csproj
index 2c994fe5f4..2623e74c38 100644
--- a/util/Migrator/Migrator.csproj
+++ b/util/Migrator/Migrator.csproj
@@ -6,7 +6,7 @@
 
   <ItemGroup>
     <PackageReference Include="dbup-sqlserver" Version="4.4.0" />
-    <PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.6" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
   </ItemGroup>
 
   <ItemGroup>
diff --git a/util/Migrator/MySql/Init.sql b/util/Migrator/MySql/Init.sql
new file mode 100644
index 0000000000..3c902002c0
--- /dev/null
+++ b/util/Migrator/MySql/Init.sql
@@ -0,0 +1,1028 @@
+ALTER DATABASE CHARACTER SET utf8mb4;
+CREATE TABLE IF NOT EXISTS `__EFMigrationsHistory` (
+    `MigrationId` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
+    `ProductVersion` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
+    CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`)
+) CHARACTER SET utf8mb4;
+
+START TRANSACTION;
+
+CREATE TABLE `Event` (
+    `Id` uuid NOT NULL,
+    `Date` timestamp without time zone NOT NULL,
+    `Type` integer NOT NULL,
+    `UserId` uuid NULL,
+    `OrganizationId` uuid NULL,
+    `CipherId` uuid NULL,
+    `CollectionId` uuid NULL,
+    `PolicyId` uuid NULL,
+    `GroupId` uuid NULL,
+    `OrganizationUserId` uuid NULL,
+    `DeviceType` smallint NULL,
+    `IpAddress` character varying(50) NULL,
+    `ActingUserId` uuid NULL,
+    CONSTRAINT `PK_Event` PRIMARY KEY (`Id`)
+);
+
+CREATE TABLE `Grant` (
+    `Key` character varying(200) NOT NULL,
+    `Type` character varying(50) NULL,
+    `SubjectId` character varying(200) NULL,
+    `SessionId` character varying(100) NULL,
+    `ClientId` character varying(200) NULL,
+    `Description` character varying(200) NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `ExpirationDate` timestamp without time zone NULL,
+    `ConsumedDate` timestamp without time zone NULL,
+    `Data` text NULL,
+    CONSTRAINT `PK_Grant` PRIMARY KEY (`Key`)
+);
+
+CREATE TABLE `Installation` (
+    `Id` uuid NOT NULL,
+    `Email` character varying(256) NULL,
+    `Key` character varying(150) NULL,
+    `Enabled` boolean NOT NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_Installation` PRIMARY KEY (`Id`)
+);
+
+CREATE TABLE `Organization` (
+    `Id` uuid NOT NULL,
+    `Identifier` character varying(50) COLLATE postgresIndetermanisticCollation NULL,
+    `Name` character varying(50) NULL,
+    `BusinessName` character varying(50) NULL,
+    `BusinessAddress1` character varying(50) NULL,
+    `BusinessAddress2` character varying(50) NULL,
+    `BusinessAddress3` character varying(50) NULL,
+    `BusinessCountry` character varying(2) NULL,
+    `BusinessTaxNumber` character varying(30) NULL,
+    `BillingEmail` character varying(256) NULL,
+    `Plan` character varying(50) NULL,
+    `PlanType` smallint NOT NULL,
+    `Seats` integer NULL,
+    `MaxCollections` smallint NULL,
+    `UsePolicies` boolean NOT NULL,
+    `UseSso` boolean NOT NULL,
+    `UseGroups` boolean NOT NULL,
+    `UseDirectory` boolean NOT NULL,
+    `UseEvents` boolean NOT NULL,
+    `UseTotp` boolean NOT NULL,
+    `Use2fa` boolean NOT NULL,
+    `UseApi` boolean NOT NULL,
+    `UseResetPassword` boolean NOT NULL,
+    `SelfHost` boolean NOT NULL,
+    `UsersGetPremium` boolean NOT NULL,
+    `Storage` bigint NULL,
+    `MaxStorageGb` smallint NULL,
+    `Gateway` smallint NULL,
+    `GatewayCustomerId` character varying(50) NULL,
+    `GatewaySubscriptionId` character varying(50) NULL,
+    `ReferenceData` text NULL,
+    `Enabled` boolean NOT NULL,
+    `LicenseKey` character varying(100) NULL,
+    `ApiKey` character varying(30) NULL,
+    `PublicKey` text NULL,
+    `PrivateKey` text NULL,
+    `TwoFactorProviders` text NULL,
+    `ExpirationDate` timestamp without time zone NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_Organization` PRIMARY KEY (`Id`)
+);
+
+CREATE TABLE `Provider` (
+    `Id` uuid NOT NULL,
+    `Name` text NULL,
+    `BusinessName` text NULL,
+    `BusinessAddress1` text NULL,
+    `BusinessAddress2` text NULL,
+    `BusinessAddress3` text NULL,
+    `BusinessCountry` text NULL,
+    `BusinessTaxNumber` text NULL,
+    `BillingEmail` text NULL,
+    `Status` smallint NOT NULL,
+    `Enabled` boolean NOT NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_Provider` PRIMARY KEY (`Id`)
+);
+
+CREATE TABLE `TaxRate` (
+    `Id` character varying(40) NOT NULL,
+    `Country` character varying(50) NULL,
+    `State` character varying(2) NULL,
+    `PostalCode` character varying(10) NULL,
+    `Rate` numeric NOT NULL,
+    `Active` boolean NOT NULL,
+    CONSTRAINT `PK_TaxRate` PRIMARY KEY (`Id`)
+);
+
+CREATE TABLE `User` (
+    `Id` uuid NOT NULL,
+    `Name` character varying(50) NULL,
+    `Email` character varying(256) COLLATE postgresIndetermanisticCollation NOT NULL,
+    `EmailVerified` boolean NOT NULL,
+    `MasterPassword` character varying(300) NULL,
+    `MasterPasswordHint` character varying(50) NULL,
+    `Culture` character varying(10) NULL,
+    `SecurityStamp` character varying(50) NOT NULL,
+    `TwoFactorProviders` text NULL,
+    `TwoFactorRecoveryCode` character varying(32) NULL,
+    `EquivalentDomains` text NULL,
+    `ExcludedGlobalEquivalentDomains` text NULL,
+    `AccountRevisionDate` timestamp without time zone NOT NULL,
+    `Key` text NULL,
+    `PublicKey` text NULL,
+    `PrivateKey` text NULL,
+    `Premium` boolean NOT NULL,
+    `PremiumExpirationDate` timestamp without time zone NULL,
+    `RenewalReminderDate` timestamp without time zone NULL,
+    `Storage` bigint NULL,
+    `MaxStorageGb` smallint NULL,
+    `Gateway` smallint NULL,
+    `GatewayCustomerId` character varying(50) NULL,
+    `GatewaySubscriptionId` character varying(50) NULL,
+    `ReferenceData` text NULL,
+    `LicenseKey` character varying(100) NULL,
+    `ApiKey` character varying(30) NOT NULL,
+    `Kdf` smallint NOT NULL,
+    `KdfIterations` integer NOT NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_User` PRIMARY KEY (`Id`)
+);
+
+CREATE TABLE `Collection` (
+    `Id` uuid NOT NULL,
+    `OrganizationId` uuid NOT NULL,
+    `Name` text NULL,
+    `ExternalId` character varying(300) NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_Collection` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Collection_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `Group` (
+    `Id` uuid NOT NULL,
+    `OrganizationId` uuid NOT NULL,
+    `Name` character varying(100) NULL,
+    `AccessAll` boolean NOT NULL,
+    `ExternalId` character varying(300) NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_Group` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Group_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `Policy` (
+    `Id` uuid NOT NULL,
+    `OrganizationId` uuid NOT NULL,
+    `Type` smallint NOT NULL,
+    `Data` text NULL,
+    `Enabled` boolean NOT NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_Policy` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Policy_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `SsoConfig` (
+    `Id` bigint NOT NULL,
+    `Enabled` boolean NOT NULL,
+    `OrganizationId` uuid NOT NULL,
+    `Data` text NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_SsoConfig` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_SsoConfig_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `ProviderOrganization` (
+    `Id` uuid NOT NULL,
+    `ProviderId` uuid NOT NULL,
+    `OrganizationId` uuid NOT NULL,
+    `Key` text NULL,
+    `Settings` text NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_ProviderOrganization` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_ProviderOrganization_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_ProviderOrganization_Provider_ProviderId` FOREIGN KEY (`ProviderId`) REFERENCES `Provider` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `Cipher` (
+    `Id` uuid NOT NULL,
+    `UserId` uuid NULL,
+    `OrganizationId` uuid NULL,
+    `Type` smallint NOT NULL,
+    `Data` text NULL,
+    `Favorites` text NULL,
+    `Folders` text NULL,
+    `Attachments` text NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    `DeletedDate` timestamp without time zone NULL,
+    `Reprompt` smallint NULL,
+    CONSTRAINT `PK_Cipher` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Cipher_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_Cipher_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+);
+
+CREATE TABLE `Device` (
+    `Id` uuid NOT NULL,
+    `UserId` uuid NOT NULL,
+    `Name` character varying(50) NULL,
+    `Type` smallint NOT NULL,
+    `Identifier` character varying(50) NULL,
+    `PushToken` character varying(255) NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_Device` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Device_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `EmergencyAccess` (
+    `Id` uuid NOT NULL,
+    `GrantorId` uuid NOT NULL,
+    `GranteeId` uuid NULL,
+    `Email` character varying(256) NULL,
+    `KeyEncrypted` text NULL,
+    `Type` smallint NOT NULL,
+    `Status` smallint NOT NULL,
+    `WaitTimeDays` integer NOT NULL,
+    `RecoveryInitiatedDate` timestamp without time zone NULL,
+    `LastNotificationDate` timestamp without time zone NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_EmergencyAccess` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_EmergencyAccess_User_GranteeId` FOREIGN KEY (`GranteeId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_EmergencyAccess_User_GrantorId` FOREIGN KEY (`GrantorId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `Folder` (
+    `Id` uuid NOT NULL,
+    `UserId` uuid NOT NULL,
+    `Name` text NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_Folder` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Folder_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `OrganizationUser` (
+    `Id` uuid NOT NULL,
+    `OrganizationId` uuid NOT NULL,
+    `UserId` uuid NULL,
+    `Email` character varying(256) NULL,
+    `Key` text NULL,
+    `ResetPasswordKey` text NULL,
+    `Status` smallint NOT NULL,
+    `Type` smallint NOT NULL,
+    `AccessAll` boolean NOT NULL,
+    `ExternalId` character varying(300) NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    `Permissions` text NULL,
+    CONSTRAINT `PK_OrganizationUser` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_OrganizationUser_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_OrganizationUser_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+);
+
+CREATE TABLE `ProviderUser` (
+    `Id` uuid NOT NULL,
+    `ProviderId` uuid NOT NULL,
+    `UserId` uuid NULL,
+    `Email` text NULL,
+    `Key` text NULL,
+    `Status` smallint NOT NULL,
+    `Type` smallint NOT NULL,
+    `Permissions` text NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_ProviderUser` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_ProviderUser_Provider_ProviderId` FOREIGN KEY (`ProviderId`) REFERENCES `Provider` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_ProviderUser_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+);
+
+CREATE TABLE `Send` (
+    `Id` uuid NOT NULL,
+    `UserId` uuid NULL,
+    `OrganizationId` uuid NULL,
+    `Type` smallint NOT NULL,
+    `Data` text NULL,
+    `Key` text NULL,
+    `Password` character varying(300) NULL,
+    `MaxAccessCount` integer NULL,
+    `AccessCount` integer NOT NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    `ExpirationDate` timestamp without time zone NULL,
+    `DeletionDate` timestamp without time zone NOT NULL,
+    `Disabled` boolean NOT NULL,
+    `HideEmail` boolean NULL,
+    CONSTRAINT `PK_Send` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Send_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_Send_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+);
+
+CREATE TABLE `SsoUser` (
+    `Id` bigint NOT NULL,
+    `UserId` uuid NOT NULL,
+    `OrganizationId` uuid NULL,
+    `ExternalId` character varying(50) COLLATE postgresIndetermanisticCollation NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_SsoUser` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_SsoUser_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_SsoUser_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `Transaction` (
+    `Id` uuid NOT NULL,
+    `UserId` uuid NULL,
+    `OrganizationId` uuid NULL,
+    `Type` smallint NOT NULL,
+    `Amount` numeric NOT NULL,
+    `Refunded` boolean NULL,
+    `RefundedAmount` numeric NULL,
+    `Details` character varying(100) NULL,
+    `PaymentMethodType` smallint NULL,
+    `Gateway` smallint NULL,
+    `GatewayId` character varying(50) NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_Transaction` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Transaction_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_Transaction_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+);
+
+CREATE TABLE `U2f` (
+    `Id` integer NOT NULL,
+    `UserId` uuid NOT NULL,
+    `KeyHandle` character varying(200) NULL,
+    `Challenge` character varying(200) NULL,
+    `AppId` character varying(50) NULL,
+    `Version` character varying(20) NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_U2f` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_U2f_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `CollectionGroups` (
+    `CollectionId` uuid NOT NULL,
+    `GroupId` uuid NOT NULL,
+    `ReadOnly` boolean NOT NULL,
+    `HidePasswords` boolean NOT NULL,
+    CONSTRAINT `PK_CollectionGroups` PRIMARY KEY (`CollectionId`, `GroupId`),
+    CONSTRAINT `FK_CollectionGroups_Collection_CollectionId` FOREIGN KEY (`CollectionId`) REFERENCES `Collection` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_CollectionGroups_Group_GroupId` FOREIGN KEY (`GroupId`) REFERENCES `Group` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `CollectionCipher` (
+    `CollectionId` uuid NOT NULL,
+    `CipherId` uuid NOT NULL,
+    CONSTRAINT `PK_CollectionCipher` PRIMARY KEY (`CollectionId`, `CipherId`),
+    CONSTRAINT `FK_CollectionCipher_Cipher_CipherId` FOREIGN KEY (`CipherId`) REFERENCES `Cipher` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_CollectionCipher_Collection_CollectionId` FOREIGN KEY (`CollectionId`) REFERENCES `Collection` (`Id`) ON DELETE CASCADE
+);
+
+CREATE TABLE `CollectionUsers` (
+    `CollectionId` uuid NOT NULL,
+    `OrganizationUserId` uuid NOT NULL,
+    `UserId` uuid NULL,
+    `ReadOnly` boolean NOT NULL,
+    `HidePasswords` boolean NOT NULL,
+    CONSTRAINT `PK_CollectionUsers` PRIMARY KEY (`CollectionId`, `OrganizationUserId`),
+    CONSTRAINT `FK_CollectionUsers_Collection_CollectionId` FOREIGN KEY (`CollectionId`) REFERENCES `Collection` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_CollectionUsers_OrganizationUser_OrganizationUserId` FOREIGN KEY (`OrganizationUserId`) REFERENCES `OrganizationUser` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_CollectionUsers_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+);
+
+CREATE TABLE `GroupUser` (
+    `GroupId` uuid NOT NULL,
+    `OrganizationUserId` uuid NOT NULL,
+    `UserId` uuid NULL,
+    CONSTRAINT `PK_GroupUser` PRIMARY KEY (`GroupId`, `OrganizationUserId`),
+    CONSTRAINT `FK_GroupUser_Group_GroupId` FOREIGN KEY (`GroupId`) REFERENCES `Group` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_GroupUser_OrganizationUser_OrganizationUserId` FOREIGN KEY (`OrganizationUserId`) REFERENCES `OrganizationUser` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_GroupUser_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+);
+
+CREATE TABLE `ProviderOrganizationProviderUser` (
+    `Id` uuid NOT NULL,
+    `ProviderOrganizationId` uuid NOT NULL,
+    `ProviderUserId` uuid NOT NULL,
+    `Type` smallint NOT NULL,
+    `Permissions` text NULL,
+    `CreationDate` timestamp without time zone NOT NULL,
+    `RevisionDate` timestamp without time zone NOT NULL,
+    CONSTRAINT `PK_ProviderOrganizationProviderUser` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_ProviderOrganizationProviderUser_ProviderOrganization_Provi~` FOREIGN KEY (`ProviderOrganizationId`) REFERENCES `ProviderOrganization` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_ProviderOrganizationProviderUser_ProviderUser_ProviderUserId` FOREIGN KEY (`ProviderUserId`) REFERENCES `ProviderUser` (`Id`) ON DELETE CASCADE
+);
+
+CREATE INDEX `IX_Cipher_OrganizationId` ON `Cipher` (`OrganizationId`);
+
+CREATE INDEX `IX_Cipher_UserId` ON `Cipher` (`UserId`);
+
+CREATE INDEX `IX_Collection_OrganizationId` ON `Collection` (`OrganizationId`);
+
+CREATE INDEX `IX_CollectionCipher_CipherId` ON `CollectionCipher` (`CipherId`);
+
+CREATE INDEX `IX_CollectionGroups_GroupId` ON `CollectionGroups` (`GroupId`);
+
+CREATE INDEX `IX_CollectionUsers_OrganizationUserId` ON `CollectionUsers` (`OrganizationUserId`);
+
+CREATE INDEX `IX_CollectionUsers_UserId` ON `CollectionUsers` (`UserId`);
+
+CREATE INDEX `IX_Device_UserId` ON `Device` (`UserId`);
+
+CREATE INDEX `IX_EmergencyAccess_GranteeId` ON `EmergencyAccess` (`GranteeId`);
+
+CREATE INDEX `IX_EmergencyAccess_GrantorId` ON `EmergencyAccess` (`GrantorId`);
+
+CREATE INDEX `IX_Folder_UserId` ON `Folder` (`UserId`);
+
+CREATE INDEX `IX_Group_OrganizationId` ON `Group` (`OrganizationId`);
+
+CREATE INDEX `IX_GroupUser_OrganizationUserId` ON `GroupUser` (`OrganizationUserId`);
+
+CREATE INDEX `IX_GroupUser_UserId` ON `GroupUser` (`UserId`);
+
+CREATE INDEX `IX_OrganizationUser_OrganizationId` ON `OrganizationUser` (`OrganizationId`);
+
+CREATE INDEX `IX_OrganizationUser_UserId` ON `OrganizationUser` (`UserId`);
+
+CREATE INDEX `IX_Policy_OrganizationId` ON `Policy` (`OrganizationId`);
+
+CREATE INDEX `IX_ProviderOrganization_OrganizationId` ON `ProviderOrganization` (`OrganizationId`);
+
+CREATE INDEX `IX_ProviderOrganization_ProviderId` ON `ProviderOrganization` (`ProviderId`);
+
+CREATE INDEX `IX_ProviderOrganizationProviderUser_ProviderOrganizationId` ON `ProviderOrganizationProviderUser` (`ProviderOrganizationId`);
+
+CREATE INDEX `IX_ProviderOrganizationProviderUser_ProviderUserId` ON `ProviderOrganizationProviderUser` (`ProviderUserId`);
+
+CREATE INDEX `IX_ProviderUser_ProviderId` ON `ProviderUser` (`ProviderId`);
+
+CREATE INDEX `IX_ProviderUser_UserId` ON `ProviderUser` (`UserId`);
+
+CREATE INDEX `IX_Send_OrganizationId` ON `Send` (`OrganizationId`);
+
+CREATE INDEX `IX_Send_UserId` ON `Send` (`UserId`);
+
+CREATE INDEX `IX_SsoConfig_OrganizationId` ON `SsoConfig` (`OrganizationId`);
+
+CREATE INDEX `IX_SsoUser_OrganizationId` ON `SsoUser` (`OrganizationId`);
+
+CREATE INDEX `IX_SsoUser_UserId` ON `SsoUser` (`UserId`);
+
+CREATE INDEX `IX_Transaction_OrganizationId` ON `Transaction` (`OrganizationId`);
+
+CREATE INDEX `IX_Transaction_UserId` ON `Transaction` (`UserId`);
+
+CREATE INDEX `IX_U2f_UserId` ON `U2f` (`UserId`);
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20210617143411_InitPostgres', '5.0.5');
+
+COMMIT;
+
+START TRANSACTION;
+
+ALTER TABLE `ProviderOrganizationProviderUser` DROP FOREIGN KEY `FK_ProviderOrganizationProviderUser_ProviderOrganization_Provi~`;
+
+ALTER TABLE `User` MODIFY COLUMN `TwoFactorRecoveryCode` varchar(32) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `TwoFactorProviders` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `SecurityStamp` varchar(50) CHARACTER SET utf8mb4 NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `RenewalReminderDate` datetime(6) NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `ReferenceData` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `PublicKey` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `PrivateKey` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `PremiumExpirationDate` datetime(6) NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `Premium` tinyint(1) NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `Name` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `MasterPasswordHint` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `MasterPassword` varchar(300) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `LicenseKey` varchar(100) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `Key` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `KdfIterations` int NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `Kdf` tinyint unsigned NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `GatewaySubscriptionId` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `GatewayCustomerId` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `Gateway` tinyint unsigned NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `ExcludedGlobalEquivalentDomains` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `EquivalentDomains` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `EmailVerified` tinyint(1) NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `Email` varchar(256) CHARACTER SET utf8mb4 NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `Culture` varchar(10) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `ApiKey` varchar(30) CHARACTER SET utf8mb4 NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `AccountRevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `User` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `U2f` MODIFY COLUMN `Version` varchar(20) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `U2f` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `U2f` MODIFY COLUMN `KeyHandle` varchar(200) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `U2f` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `U2f` MODIFY COLUMN `Challenge` varchar(200) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `U2f` MODIFY COLUMN `AppId` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `U2f` MODIFY COLUMN `Id` int NOT NULL AUTO_INCREMENT;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `Type` tinyint unsigned NOT NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `RefundedAmount` decimal(65,30) NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `Refunded` tinyint(1) NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `PaymentMethodType` tinyint unsigned NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `GatewayId` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `Gateway` tinyint unsigned NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `Details` varchar(100) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `Amount` decimal(65,30) NOT NULL;
+
+ALTER TABLE `Transaction` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `TaxRate` MODIFY COLUMN `State` varchar(2) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `TaxRate` MODIFY COLUMN `Rate` decimal(65,30) NOT NULL;
+
+ALTER TABLE `TaxRate` MODIFY COLUMN `PostalCode` varchar(10) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `TaxRate` MODIFY COLUMN `Country` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `TaxRate` MODIFY COLUMN `Active` tinyint(1) NOT NULL;
+
+ALTER TABLE `TaxRate` MODIFY COLUMN `Id` varchar(40) CHARACTER SET utf8mb4 NOT NULL;
+
+ALTER TABLE `SsoUser` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `SsoUser` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `SsoUser` MODIFY COLUMN `ExternalId` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `SsoUser` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `SsoConfig` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `SsoConfig` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `SsoConfig` MODIFY COLUMN `Enabled` tinyint(1) NOT NULL;
+
+ALTER TABLE `SsoConfig` MODIFY COLUMN `Data` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `SsoConfig` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `Type` tinyint unsigned NOT NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `Password` varchar(300) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `MaxAccessCount` int NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `Key` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `HideEmail` tinyint(1) NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `ExpirationDate` datetime(6) NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `Disabled` tinyint(1) NOT NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `DeletionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `Data` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `AccessCount` int NOT NULL;
+
+ALTER TABLE `Send` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `Type` tinyint unsigned NOT NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `Status` tinyint unsigned NOT NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `ProviderId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `Permissions` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `Key` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `Email` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `ProviderUser` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `ProviderOrganizationProviderUser` MODIFY COLUMN `Type` tinyint unsigned NOT NULL;
+
+ALTER TABLE `ProviderOrganizationProviderUser` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `ProviderOrganizationProviderUser` MODIFY COLUMN `ProviderUserId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `ProviderOrganizationProviderUser` MODIFY COLUMN `ProviderOrganizationId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `ProviderOrganizationProviderUser` MODIFY COLUMN `Permissions` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `ProviderOrganizationProviderUser` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `ProviderOrganizationProviderUser` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `ProviderOrganization` MODIFY COLUMN `Settings` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `ProviderOrganization` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `ProviderOrganization` MODIFY COLUMN `ProviderId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `ProviderOrganization` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `ProviderOrganization` MODIFY COLUMN `Key` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `ProviderOrganization` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `ProviderOrganization` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `Status` tinyint unsigned NOT NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `Name` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `Enabled` tinyint(1) NOT NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `BusinessTaxNumber` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `BusinessName` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `BusinessCountry` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `BusinessAddress3` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `BusinessAddress2` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `BusinessAddress1` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `BillingEmail` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Provider` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Policy` MODIFY COLUMN `Type` tinyint unsigned NOT NULL;
+
+ALTER TABLE `Policy` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Policy` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Policy` MODIFY COLUMN `Enabled` tinyint(1) NOT NULL;
+
+ALTER TABLE `Policy` MODIFY COLUMN `Data` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Policy` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Policy` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `Type` tinyint unsigned NOT NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `Status` tinyint unsigned NOT NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `ResetPasswordKey` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `Permissions` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `Key` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `ExternalId` varchar(300) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `Email` varchar(256) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `AccessAll` tinyint(1) NOT NULL;
+
+ALTER TABLE `OrganizationUser` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `UsersGetPremium` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `UseTotp` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `UseSso` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `UseResetPassword` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `UsePolicies` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `UseGroups` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `UseEvents` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `UseDirectory` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `UseApi` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `Use2fa` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `TwoFactorProviders` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `SelfHost` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `Seats` int NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `ReferenceData` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `PublicKey` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `PrivateKey` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `PlanType` tinyint unsigned NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `Plan` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `Name` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `LicenseKey` varchar(100) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `Identifier` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `GatewaySubscriptionId` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `GatewayCustomerId` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `Gateway` tinyint unsigned NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `ExpirationDate` datetime(6) NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `Enabled` tinyint(1) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `BusinessTaxNumber` varchar(30) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `BusinessName` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `BusinessCountry` varchar(2) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `BusinessAddress3` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `BusinessAddress2` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `BusinessAddress1` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `BillingEmail` varchar(256) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `ApiKey` varchar(30) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Organization` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Installation` MODIFY COLUMN `Key` varchar(150) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Installation` MODIFY COLUMN `Enabled` tinyint(1) NOT NULL;
+
+ALTER TABLE `Installation` MODIFY COLUMN `Email` varchar(256) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Installation` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Installation` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `GroupUser` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `GroupUser` MODIFY COLUMN `OrganizationUserId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `GroupUser` MODIFY COLUMN `GroupId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Group` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Group` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Group` MODIFY COLUMN `Name` varchar(100) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Group` MODIFY COLUMN `ExternalId` varchar(300) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Group` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Group` MODIFY COLUMN `AccessAll` tinyint(1) NOT NULL;
+
+ALTER TABLE `Group` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `Type` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `SubjectId` varchar(200) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `SessionId` varchar(100) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `ExpirationDate` datetime(6) NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `Description` varchar(200) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `Data` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `ConsumedDate` datetime(6) NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `ClientId` varchar(200) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Grant` MODIFY COLUMN `Key` varchar(200) CHARACTER SET utf8mb4 NOT NULL;
+
+ALTER TABLE `Folder` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Folder` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Folder` MODIFY COLUMN `Name` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Folder` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Folder` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `Type` int NOT NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `PolicyId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `OrganizationUserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `IpAddress` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `GroupId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `DeviceType` tinyint unsigned NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `Date` datetime(6) NOT NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `CollectionId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `CipherId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `ActingUserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Event` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `WaitTimeDays` int NOT NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `Type` tinyint unsigned NOT NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `Status` tinyint unsigned NOT NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `RecoveryInitiatedDate` datetime(6) NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `LastNotificationDate` datetime(6) NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `KeyEncrypted` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `GrantorId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `GranteeId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `Email` varchar(256) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `EmergencyAccess` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Device` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Device` MODIFY COLUMN `Type` tinyint unsigned NOT NULL;
+
+ALTER TABLE `Device` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Device` MODIFY COLUMN `PushToken` varchar(255) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Device` MODIFY COLUMN `Name` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Device` MODIFY COLUMN `Identifier` varchar(50) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Device` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Device` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `CollectionUsers` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `CollectionUsers` MODIFY COLUMN `ReadOnly` tinyint(1) NOT NULL;
+
+ALTER TABLE `CollectionUsers` MODIFY COLUMN `HidePasswords` tinyint(1) NOT NULL;
+
+ALTER TABLE `CollectionUsers` MODIFY COLUMN `OrganizationUserId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `CollectionUsers` MODIFY COLUMN `CollectionId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `CollectionGroups` MODIFY COLUMN `ReadOnly` tinyint(1) NOT NULL;
+
+ALTER TABLE `CollectionGroups` MODIFY COLUMN `HidePasswords` tinyint(1) NOT NULL;
+
+ALTER TABLE `CollectionGroups` MODIFY COLUMN `GroupId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `CollectionGroups` MODIFY COLUMN `CollectionId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `CollectionCipher` MODIFY COLUMN `CipherId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `CollectionCipher` MODIFY COLUMN `CollectionId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Collection` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Collection` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Collection` MODIFY COLUMN `Name` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Collection` MODIFY COLUMN `ExternalId` varchar(300) CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Collection` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Collection` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `UserId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `Type` tinyint unsigned NOT NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `RevisionDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `Reprompt` tinyint unsigned NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `OrganizationId` char(36) COLLATE ascii_general_ci NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `Folders` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `Favorites` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `DeletedDate` datetime(6) NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `Data` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `CreationDate` datetime(6) NOT NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `Attachments` longtext CHARACTER SET utf8mb4 NULL;
+
+ALTER TABLE `Cipher` MODIFY COLUMN `Id` char(36) COLLATE ascii_general_ci NOT NULL;
+
+ALTER TABLE `ProviderOrganizationProviderUser` ADD CONSTRAINT `FK_ProviderOrganizationProviderUser_ProviderOrganization_Provid~` FOREIGN KEY (`ProviderOrganizationId`) REFERENCES `ProviderOrganization` (`Id`) ON DELETE CASCADE;
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20210617152444_InitMySql', '5.0.5');
+
+COMMIT;
\ No newline at end of file
diff --git a/util/MySqlMigrations/Factories.cs b/util/MySqlMigrations/Factories.cs
new file mode 100644
index 0000000000..1fad15f524
--- /dev/null
+++ b/util/MySqlMigrations/Factories.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using Bit.Core.Repositories.EntityFramework;
+using Bit.Core.Settings;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using Bit.Core.Enums;
+using Microsoft.EntityFrameworkCore.Design;
+using System;
+
+namespace MySqlMigrations
+{
+    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 class DatabaseContextFactory : IDesignTimeDbContextFactory<DatabaseContext>
+    {
+        public DatabaseContext CreateDbContext(string[] args)
+        {
+            var globalSettings = GlobalSettingsFactory.GlobalSettings;
+            var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>();
+
+            var selectedDatabaseProvider = globalSettings.DatabaseProvider;
+            var provider = SupportedDatabaseProviders.Postgres;
+            var connectionString = string.Empty;
+            if (!string.IsNullOrWhiteSpace(selectedDatabaseProvider))
+            {
+                switch (selectedDatabaseProvider.ToLowerInvariant())
+                {
+                    case "postgres":
+                    case "postgresql":
+                        provider = SupportedDatabaseProviders.Postgres;
+                        connectionString = globalSettings.PostgreSql.ConnectionString;
+                        break;
+                    case "mysql":
+                    case "mariadb":
+                        provider = SupportedDatabaseProviders.MySql;
+                        connectionString = globalSettings.MySql.ConnectionString;
+                        break;
+                    default:
+                        throw new Exception("No database provider selected");
+                        break;
+                }
+            }
+            if (provider.Equals(SupportedDatabaseProviders.Postgres))
+            {
+                optionsBuilder.UseNpgsql(
+                    connectionString,  
+                    b => b.MigrationsAssembly("PostgresMigrations"));
+            }
+            else if (provider.Equals(SupportedDatabaseProviders.MySql))
+            {
+                optionsBuilder.UseMySql(
+                    connectionString, 
+                    ServerVersion.AutoDetect(connectionString),
+                    b => b.MigrationsAssembly("MySqlMigrations"));
+            }
+            return new DatabaseContext(optionsBuilder.Options);
+        }
+    }
+}
diff --git a/util/MySqlMigrations/Migrations/20210617183900_Init.Designer.cs b/util/MySqlMigrations/Migrations/20210617183900_Init.Designer.cs
new file mode 100644
index 0000000000..932da8d2bb
--- /dev/null
+++ b/util/MySqlMigrations/Migrations/20210617183900_Init.Designer.cs
@@ -0,0 +1,1522 @@
+// <auto-generated />
+using System;
+using Bit.Core.Repositories.EntityFramework;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace Bit.MySqlMigrations.Migrations
+{
+    [DbContext(typeof(DatabaseContext))]
+    [Migration("20210617183900_Init")]
+    partial class Init
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("Relational:MaxIdentifierLength", 64)
+                .HasAnnotation("ProductVersion", "5.0.5");
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Attachments")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime?>("DeletedDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Favorites")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Folders")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<byte?>("Reprompt")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Cipher");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Collection");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionCipher", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("CipherId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("CollectionId", "CipherId");
+
+                    b.HasIndex("CipherId");
+
+                    b.ToTable("CollectionCipher");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionGroup", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("GroupId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("HidePasswords")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("ReadOnly")
+                        .HasColumnType("tinyint(1)");
+
+                    b.HasKey("CollectionId", "GroupId");
+
+                    b.HasIndex("GroupId");
+
+                    b.ToTable("CollectionGroups");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionUser", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("OrganizationUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("HidePasswords")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("ReadOnly")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("CollectionId", "OrganizationUserId");
+
+                    b.HasIndex("OrganizationUserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Device", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Identifier")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("PushToken")
+                        .HasMaxLength(255)
+                        .HasColumnType("varchar(255)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Device");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.EmergencyAccess", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<Guid?>("GranteeId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("GrantorId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("KeyEncrypted")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime?>("LastNotificationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime?>("RecoveryInitiatedDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<int>("WaitTimeDays")
+                        .HasColumnType("int");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("GranteeId");
+
+                    b.HasIndex("GrantorId");
+
+                    b.ToTable("EmergencyAccess");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Event", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("ActingUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("CipherId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte?>("DeviceType")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("GroupId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("IpAddress")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("OrganizationUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("PolicyId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<int>("Type")
+                        .HasColumnType("int");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Event");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Folder", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Folder");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Grant", b =>
+                {
+                    b.Property<string>("Key")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<string>("ClientId")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<DateTime?>("ConsumedDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Description")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("SessionId")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<string>("SubjectId")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<string>("Type")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.HasKey("Key");
+
+                    b.ToTable("Grant");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("AccessAll")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Group");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.GroupUser", b =>
+                {
+                    b.Property<Guid>("GroupId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("OrganizationUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("GroupId", "OrganizationUserId");
+
+                    b.HasIndex("OrganizationUserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("GroupUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Installation", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Key")
+                        .HasMaxLength(150)
+                        .HasColumnType("varchar(150)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Installation");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Organization", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("ApiKey")
+                        .HasMaxLength(30)
+                        .HasColumnType("varchar(30)");
+
+                    b.Property<string>("BillingEmail")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<string>("BusinessAddress1")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessAddress2")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessAddress3")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessCountry")
+                        .HasMaxLength(2)
+                        .HasColumnType("varchar(2)");
+
+                    b.Property<string>("BusinessName")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessTaxNumber")
+                        .HasMaxLength(30)
+                        .HasColumnType("varchar(30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("GatewayCustomerId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("GatewaySubscriptionId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Identifier")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("LicenseKey")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<short?>("MaxCollections")
+                        .HasColumnType("smallint");
+
+                    b.Property<short?>("MaxStorageGb")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Plan")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<byte>("PlanType")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("PrivateKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("PublicKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ReferenceData")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int?>("Seats")
+                        .HasColumnType("int");
+
+                    b.Property<bool>("SelfHost")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<long?>("Storage")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("TwoFactorProviders")
+                        .HasColumnType("longtext");
+
+                    b.Property<bool>("Use2fa")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseApi")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseDirectory")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseEvents")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseGroups")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UsePolicies")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseResetPassword")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseSso")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseTotp")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UsersGetPremium")
+                        .HasColumnType("tinyint(1)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("AccessAll")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ResetPasswordKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Policy", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Policy");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.Provider", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("BillingEmail")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessAddress1")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessAddress2")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessAddress3")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessCountry")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessName")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessTaxNumber")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Provider");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("ProviderId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Settings")
+                        .HasColumnType("longtext");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("ProviderId");
+
+                    b.ToTable("ProviderOrganization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganizationProviderUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("ProviderOrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("ProviderUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProviderOrganizationId");
+
+                    b.HasIndex("ProviderUserId");
+
+                    b.ToTable("ProviderOrganizationProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("ProviderId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProviderId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("ProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Send", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<int>("AccessCount")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("DeletionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool>("Disabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool?>("HideEmail")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<int?>("MaxAccessCount")
+                        .HasColumnType("int");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Password")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Send");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoConfig", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("SsoConfig");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoUser", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("SsoUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.TaxRate", b =>
+                {
+                    b.Property<string>("Id")
+                        .HasMaxLength(40)
+                        .HasColumnType("varchar(40)");
+
+                    b.Property<bool>("Active")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Country")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("PostalCode")
+                        .HasMaxLength(10)
+                        .HasColumnType("varchar(10)");
+
+                    b.Property<decimal>("Rate")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("State")
+                        .HasMaxLength(2)
+                        .HasColumnType("varchar(2)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("TaxRate");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Transaction", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Details")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("GatewayId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<byte?>("PaymentMethodType")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<bool?>("Refunded")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<decimal?>("RefundedAmount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Transaction");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.U2f", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("AppId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Challenge")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("KeyHandle")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Version")
+                        .HasMaxLength(20)
+                        .HasColumnType("varchar(20)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("U2f");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.User", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("AccountRevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ApiKey")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("varchar(30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Culture")
+                        .HasMaxLength(10)
+                        .HasColumnType("varchar(10)");
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<bool>("EmailVerified")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("EquivalentDomains")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ExcludedGlobalEquivalentDomains")
+                        .HasColumnType("longtext");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("GatewayCustomerId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("GatewaySubscriptionId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<byte>("Kdf")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<int>("KdfIterations")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("LicenseKey")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<string>("MasterPassword")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("MasterPasswordHint")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<short?>("MaxStorageGb")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<bool>("Premium")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime?>("PremiumExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("PrivateKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("PublicKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ReferenceData")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime?>("RenewalReminderDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("SecurityStamp")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<long?>("Storage")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("TwoFactorProviders")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("TwoFactorRecoveryCode")
+                        .HasMaxLength(32)
+                        .HasColumnType("varchar(32)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Ciphers")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Ciphers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionCipher", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Cipher", "Cipher")
+                        .WithMany("CollectionCiphers")
+                        .HasForeignKey("CipherId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionCiphers")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Cipher");
+
+                    b.Navigation("Collection");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionGroup", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionGroups")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Group", "Group")
+                        .WithMany()
+                        .HasForeignKey("GroupId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Collection");
+
+                    b.Navigation("Group");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.OrganizationUser", "OrganizationUser")
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("OrganizationUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", null)
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Collection");
+
+                    b.Navigation("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Device", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.EmergencyAccess", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "Grantee")
+                        .WithMany()
+                        .HasForeignKey("GranteeId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "Grantor")
+                        .WithMany()
+                        .HasForeignKey("GrantorId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Grantee");
+
+                    b.Navigation("Grantor");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Folder", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Folders")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Groups")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.GroupUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Group", "Group")
+                        .WithMany("GroupUsers")
+                        .HasForeignKey("GroupId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.OrganizationUser", "OrganizationUser")
+                        .WithMany()
+                        .HasForeignKey("OrganizationUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", null)
+                        .WithMany("GroupUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Group");
+
+                    b.Navigation("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("OrganizationUsers")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("OrganizationUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Policy", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Policies")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.Provider", "Provider")
+                        .WithMany()
+                        .HasForeignKey("ProviderId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("Provider");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganizationProviderUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", "ProviderOrganization")
+                        .WithMany()
+                        .HasForeignKey("ProviderOrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.ProviderUser", "ProviderUser")
+                        .WithMany()
+                        .HasForeignKey("ProviderUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("ProviderOrganization");
+
+                    b.Navigation("ProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.Provider", "Provider")
+                        .WithMany()
+                        .HasForeignKey("ProviderId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Provider");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Send", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoConfig", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("SsoConfigs")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("SsoUsers")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("SsoUsers")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Transaction", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Transactions")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Transactions")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.U2f", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("U2fs")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.Navigation("CollectionCiphers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.Navigation("CollectionCiphers");
+
+                    b.Navigation("CollectionGroups");
+
+                    b.Navigation("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.Navigation("GroupUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Organization", b =>
+                {
+                    b.Navigation("Ciphers");
+
+                    b.Navigation("Groups");
+
+                    b.Navigation("OrganizationUsers");
+
+                    b.Navigation("Policies");
+
+                    b.Navigation("SsoConfigs");
+
+                    b.Navigation("SsoUsers");
+
+                    b.Navigation("Transactions");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.Navigation("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.User", b =>
+                {
+                    b.Navigation("Ciphers");
+
+                    b.Navigation("CollectionUsers");
+
+                    b.Navigation("Folders");
+
+                    b.Navigation("GroupUsers");
+
+                    b.Navigation("OrganizationUsers");
+
+                    b.Navigation("SsoUsers");
+
+                    b.Navigation("Transactions");
+
+                    b.Navigation("U2fs");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/util/MySqlMigrations/Migrations/20210617183900_Init.cs b/util/MySqlMigrations/Migrations/20210617183900_Init.cs
new file mode 100644
index 0000000000..2da6edc446
--- /dev/null
+++ b/util/MySqlMigrations/Migrations/20210617183900_Init.cs
@@ -0,0 +1,1130 @@
+using System;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+namespace Bit.MySqlMigrations.Migrations
+{
+    public partial class Init : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AlterDatabase()
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Event",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Date = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    Type = table.Column<int>(type: "int", nullable: false),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    CipherId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    CollectionId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    PolicyId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    GroupId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    OrganizationUserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    DeviceType = table.Column<byte>(type: "tinyint unsigned", nullable: true),
+                    IpAddress = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ActingUserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci")
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Event", x => x.Id);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Grant",
+                columns: table => new
+                {
+                    Key = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Type = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    SubjectId = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    SessionId = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ClientId = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Description = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    ExpirationDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
+                    ConsumedDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
+                    Data = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4")
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Grant", x => x.Key);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Installation",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Key = table.Column<string>(type: "varchar(150)", maxLength: 150, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Enabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Installation", x => x.Id);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Organization",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Identifier = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Name = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessName = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessAddress1 = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessAddress2 = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessAddress3 = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessCountry = table.Column<string>(type: "varchar(2)", maxLength: 2, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessTaxNumber = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BillingEmail = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Plan = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    PlanType = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Seats = table.Column<int>(type: "int", nullable: true),
+                    MaxCollections = table.Column<short>(type: "smallint", nullable: true),
+                    UsePolicies = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    UseSso = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    UseGroups = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    UseDirectory = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    UseEvents = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    UseTotp = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    Use2fa = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    UseApi = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    UseResetPassword = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    SelfHost = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    UsersGetPremium = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    Storage = table.Column<long>(type: "bigint", nullable: true),
+                    MaxStorageGb = table.Column<short>(type: "smallint", nullable: true),
+                    Gateway = table.Column<byte>(type: "tinyint unsigned", nullable: true),
+                    GatewayCustomerId = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    GatewaySubscriptionId = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ReferenceData = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Enabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    LicenseKey = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ApiKey = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    PublicKey = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    PrivateKey = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    TwoFactorProviders = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ExpirationDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Organization", x => x.Id);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Provider",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Name = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessName = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessAddress1 = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessAddress2 = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessAddress3 = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessCountry = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BusinessTaxNumber = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    BillingEmail = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Status = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Enabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Provider", x => x.Id);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "TaxRate",
+                columns: table => new
+                {
+                    Id = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Country = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    State = table.Column<string>(type: "varchar(2)", maxLength: 2, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    PostalCode = table.Column<string>(type: "varchar(10)", maxLength: 10, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Rate = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
+                    Active = table.Column<bool>(type: "tinyint(1)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_TaxRate", x => x.Id);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "User",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Name = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: false)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    EmailVerified = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    MasterPassword = table.Column<string>(type: "varchar(300)", maxLength: 300, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    MasterPasswordHint = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Culture = table.Column<string>(type: "varchar(10)", maxLength: 10, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    SecurityStamp = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    TwoFactorProviders = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    TwoFactorRecoveryCode = table.Column<string>(type: "varchar(32)", maxLength: 32, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    EquivalentDomains = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ExcludedGlobalEquivalentDomains = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    AccountRevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    Key = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    PublicKey = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    PrivateKey = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Premium = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    PremiumExpirationDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
+                    RenewalReminderDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
+                    Storage = table.Column<long>(type: "bigint", nullable: true),
+                    MaxStorageGb = table.Column<short>(type: "smallint", nullable: true),
+                    Gateway = table.Column<byte>(type: "tinyint unsigned", nullable: true),
+                    GatewayCustomerId = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    GatewaySubscriptionId = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ReferenceData = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    LicenseKey = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ApiKey = table.Column<string>(type: "varchar(30)", maxLength: 30, nullable: false)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Kdf = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    KdfIterations = table.Column<int>(type: "int", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_User", x => x.Id);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Collection",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Name = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ExternalId = table.Column<string>(type: "varchar(300)", maxLength: 300, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Collection", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Collection_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Group",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    AccessAll = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    ExternalId = table.Column<string>(type: "varchar(300)", maxLength: 300, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Group", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Group_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Policy",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Type = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Data = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Enabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Policy", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Policy_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "SsoConfig",
+                columns: table => new
+                {
+                    Id = table.Column<long>(type: "bigint", nullable: false)
+                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
+                    Enabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Data = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_SsoConfig", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_SsoConfig_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "ProviderOrganization",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    ProviderId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Key = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Settings = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_ProviderOrganization", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_ProviderOrganization_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_ProviderOrganization_Provider_ProviderId",
+                        column: x => x.ProviderId,
+                        principalTable: "Provider",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Cipher",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    Type = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Data = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Favorites = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Folders = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Attachments = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    DeletedDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
+                    Reprompt = table.Column<byte>(type: "tinyint unsigned", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Cipher", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Cipher_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_Cipher_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Device",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Name = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Type = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Identifier = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    PushToken = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Device", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Device_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "EmergencyAccess",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    GrantorId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    GranteeId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    KeyEncrypted = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Type = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Status = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    WaitTimeDays = table.Column<int>(type: "int", nullable: false),
+                    RecoveryInitiatedDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
+                    LastNotificationDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_EmergencyAccess", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_EmergencyAccess_User_GranteeId",
+                        column: x => x.GranteeId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_EmergencyAccess_User_GrantorId",
+                        column: x => x.GrantorId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Folder",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Name = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Folder", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Folder_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "OrganizationUser",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    Email = table.Column<string>(type: "varchar(256)", maxLength: 256, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Key = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    ResetPasswordKey = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Status = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Type = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    AccessAll = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    ExternalId = table.Column<string>(type: "varchar(300)", maxLength: 300, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    Permissions = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4")
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_OrganizationUser", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_OrganizationUser_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_OrganizationUser_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "ProviderUser",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    ProviderId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    Email = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Key = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Status = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Type = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Permissions = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_ProviderUser", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_ProviderUser_Provider_ProviderId",
+                        column: x => x.ProviderId,
+                        principalTable: "Provider",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_ProviderUser_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Send",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    Type = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Data = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Key = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Password = table.Column<string>(type: "varchar(300)", maxLength: 300, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    MaxAccessCount = table.Column<int>(type: "int", nullable: true),
+                    AccessCount = table.Column<int>(type: "int", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    ExpirationDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
+                    DeletionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    Disabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    HideEmail = table.Column<bool>(type: "tinyint(1)", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Send", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Send_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_Send_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "SsoUser",
+                columns: table => new
+                {
+                    Id = table.Column<long>(type: "bigint", nullable: false)
+                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    ExternalId = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_SsoUser", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_SsoUser_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_SsoUser_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "Transaction",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    OrganizationId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    Type = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Amount = table.Column<decimal>(type: "decimal(65,30)", nullable: false),
+                    Refunded = table.Column<bool>(type: "tinyint(1)", nullable: true),
+                    RefundedAmount = table.Column<decimal>(type: "decimal(65,30)", nullable: true),
+                    Details = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    PaymentMethodType = table.Column<byte>(type: "tinyint unsigned", nullable: true),
+                    Gateway = table.Column<byte>(type: "tinyint unsigned", nullable: true),
+                    GatewayId = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Transaction", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Transaction_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_Transaction_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "U2f",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "int", nullable: false)
+                        .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    KeyHandle = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Challenge = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    AppId = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    Version = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_U2f", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_U2f_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "CollectionGroups",
+                columns: table => new
+                {
+                    CollectionId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    GroupId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    ReadOnly = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    HidePasswords = table.Column<bool>(type: "tinyint(1)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_CollectionGroups", x => new { x.CollectionId, x.GroupId });
+                    table.ForeignKey(
+                        name: "FK_CollectionGroups_Collection_CollectionId",
+                        column: x => x.CollectionId,
+                        principalTable: "Collection",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_CollectionGroups_Group_GroupId",
+                        column: x => x.GroupId,
+                        principalTable: "Group",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "CollectionCipher",
+                columns: table => new
+                {
+                    CollectionId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    CipherId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_CollectionCipher", x => new { x.CollectionId, x.CipherId });
+                    table.ForeignKey(
+                        name: "FK_CollectionCipher_Cipher_CipherId",
+                        column: x => x.CipherId,
+                        principalTable: "Cipher",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_CollectionCipher_Collection_CollectionId",
+                        column: x => x.CollectionId,
+                        principalTable: "Collection",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "CollectionUsers",
+                columns: table => new
+                {
+                    CollectionId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    OrganizationUserId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
+                    ReadOnly = table.Column<bool>(type: "tinyint(1)", nullable: false),
+                    HidePasswords = table.Column<bool>(type: "tinyint(1)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_CollectionUsers", x => new { x.CollectionId, x.OrganizationUserId });
+                    table.ForeignKey(
+                        name: "FK_CollectionUsers_Collection_CollectionId",
+                        column: x => x.CollectionId,
+                        principalTable: "Collection",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_CollectionUsers_OrganizationUser_OrganizationUserId",
+                        column: x => x.OrganizationUserId,
+                        principalTable: "OrganizationUser",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_CollectionUsers_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "GroupUser",
+                columns: table => new
+                {
+                    GroupId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    OrganizationUserId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    UserId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci")
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_GroupUser", x => new { x.GroupId, x.OrganizationUserId });
+                    table.ForeignKey(
+                        name: "FK_GroupUser_Group_GroupId",
+                        column: x => x.GroupId,
+                        principalTable: "Group",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_GroupUser_OrganizationUser_OrganizationUserId",
+                        column: x => x.OrganizationUserId,
+                        principalTable: "OrganizationUser",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_GroupUser_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateTable(
+                name: "ProviderOrganizationProviderUser",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    ProviderOrganizationId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    ProviderUserId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
+                    Type = table.Column<byte>(type: "tinyint unsigned", nullable: false),
+                    Permissions = table.Column<string>(type: "longtext", nullable: true)
+                        .Annotation("MySql:CharSet", "utf8mb4"),
+                    CreationDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "datetime(6)", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_ProviderOrganizationProviderUser", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_ProviderOrganizationProviderUser_ProviderOrganization_Provid~",
+                        column: x => x.ProviderOrganizationId,
+                        principalTable: "ProviderOrganization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_ProviderOrganizationProviderUser_ProviderUser_ProviderUserId",
+                        column: x => x.ProviderUserId,
+                        principalTable: "ProviderUser",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                })
+                .Annotation("MySql:CharSet", "utf8mb4");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Cipher_OrganizationId",
+                table: "Cipher",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Cipher_UserId",
+                table: "Cipher",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Collection_OrganizationId",
+                table: "Collection",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_CollectionCipher_CipherId",
+                table: "CollectionCipher",
+                column: "CipherId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_CollectionGroups_GroupId",
+                table: "CollectionGroups",
+                column: "GroupId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_CollectionUsers_OrganizationUserId",
+                table: "CollectionUsers",
+                column: "OrganizationUserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_CollectionUsers_UserId",
+                table: "CollectionUsers",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Device_UserId",
+                table: "Device",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_EmergencyAccess_GranteeId",
+                table: "EmergencyAccess",
+                column: "GranteeId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_EmergencyAccess_GrantorId",
+                table: "EmergencyAccess",
+                column: "GrantorId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Folder_UserId",
+                table: "Folder",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Group_OrganizationId",
+                table: "Group",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_GroupUser_OrganizationUserId",
+                table: "GroupUser",
+                column: "OrganizationUserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_GroupUser_UserId",
+                table: "GroupUser",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_OrganizationUser_OrganizationId",
+                table: "OrganizationUser",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_OrganizationUser_UserId",
+                table: "OrganizationUser",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Policy_OrganizationId",
+                table: "Policy",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderOrganization_OrganizationId",
+                table: "ProviderOrganization",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderOrganization_ProviderId",
+                table: "ProviderOrganization",
+                column: "ProviderId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderOrganizationProviderUser_ProviderOrganizationId",
+                table: "ProviderOrganizationProviderUser",
+                column: "ProviderOrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderOrganizationProviderUser_ProviderUserId",
+                table: "ProviderOrganizationProviderUser",
+                column: "ProviderUserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderUser_ProviderId",
+                table: "ProviderUser",
+                column: "ProviderId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderUser_UserId",
+                table: "ProviderUser",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Send_OrganizationId",
+                table: "Send",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Send_UserId",
+                table: "Send",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_SsoConfig_OrganizationId",
+                table: "SsoConfig",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_SsoUser_OrganizationId",
+                table: "SsoUser",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_SsoUser_UserId",
+                table: "SsoUser",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Transaction_OrganizationId",
+                table: "Transaction",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Transaction_UserId",
+                table: "Transaction",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_U2f_UserId",
+                table: "U2f",
+                column: "UserId");
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "CollectionCipher");
+
+            migrationBuilder.DropTable(
+                name: "CollectionGroups");
+
+            migrationBuilder.DropTable(
+                name: "CollectionUsers");
+
+            migrationBuilder.DropTable(
+                name: "Device");
+
+            migrationBuilder.DropTable(
+                name: "EmergencyAccess");
+
+            migrationBuilder.DropTable(
+                name: "Event");
+
+            migrationBuilder.DropTable(
+                name: "Folder");
+
+            migrationBuilder.DropTable(
+                name: "Grant");
+
+            migrationBuilder.DropTable(
+                name: "GroupUser");
+
+            migrationBuilder.DropTable(
+                name: "Installation");
+
+            migrationBuilder.DropTable(
+                name: "Policy");
+
+            migrationBuilder.DropTable(
+                name: "ProviderOrganizationProviderUser");
+
+            migrationBuilder.DropTable(
+                name: "Send");
+
+            migrationBuilder.DropTable(
+                name: "SsoConfig");
+
+            migrationBuilder.DropTable(
+                name: "SsoUser");
+
+            migrationBuilder.DropTable(
+                name: "TaxRate");
+
+            migrationBuilder.DropTable(
+                name: "Transaction");
+
+            migrationBuilder.DropTable(
+                name: "U2f");
+
+            migrationBuilder.DropTable(
+                name: "Cipher");
+
+            migrationBuilder.DropTable(
+                name: "Collection");
+
+            migrationBuilder.DropTable(
+                name: "Group");
+
+            migrationBuilder.DropTable(
+                name: "OrganizationUser");
+
+            migrationBuilder.DropTable(
+                name: "ProviderOrganization");
+
+            migrationBuilder.DropTable(
+                name: "ProviderUser");
+
+            migrationBuilder.DropTable(
+                name: "Organization");
+
+            migrationBuilder.DropTable(
+                name: "Provider");
+
+            migrationBuilder.DropTable(
+                name: "User");
+        }
+    }
+}
diff --git a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs
new file mode 100644
index 0000000000..244f0865df
--- /dev/null
+++ b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs
@@ -0,0 +1,1520 @@
+// <auto-generated />
+using System;
+using Bit.Core.Repositories.EntityFramework;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace Bit.MySqlMigrations.Migrations
+{
+    [DbContext(typeof(DatabaseContext))]
+    partial class DatabaseContextModelSnapshot : ModelSnapshot
+    {
+        protected override void BuildModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("Relational:MaxIdentifierLength", 64)
+                .HasAnnotation("ProductVersion", "5.0.5");
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Attachments")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime?>("DeletedDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Favorites")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Folders")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<byte?>("Reprompt")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Cipher");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Collection");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionCipher", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("CipherId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("CollectionId", "CipherId");
+
+                    b.HasIndex("CipherId");
+
+                    b.ToTable("CollectionCipher");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionGroup", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("GroupId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("HidePasswords")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("ReadOnly")
+                        .HasColumnType("tinyint(1)");
+
+                    b.HasKey("CollectionId", "GroupId");
+
+                    b.HasIndex("GroupId");
+
+                    b.ToTable("CollectionGroups");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionUser", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("OrganizationUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("HidePasswords")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("ReadOnly")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("CollectionId", "OrganizationUserId");
+
+                    b.HasIndex("OrganizationUserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Device", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Identifier")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("PushToken")
+                        .HasMaxLength(255)
+                        .HasColumnType("varchar(255)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Device");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.EmergencyAccess", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<Guid?>("GranteeId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("GrantorId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("KeyEncrypted")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime?>("LastNotificationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime?>("RecoveryInitiatedDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<int>("WaitTimeDays")
+                        .HasColumnType("int");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("GranteeId");
+
+                    b.HasIndex("GrantorId");
+
+                    b.ToTable("EmergencyAccess");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Event", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("ActingUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("CipherId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte?>("DeviceType")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("GroupId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("IpAddress")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("OrganizationUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("PolicyId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<int>("Type")
+                        .HasColumnType("int");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Event");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Folder", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Folder");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Grant", b =>
+                {
+                    b.Property<string>("Key")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<string>("ClientId")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<DateTime?>("ConsumedDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Description")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("SessionId")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<string>("SubjectId")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<string>("Type")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.HasKey("Key");
+
+                    b.ToTable("Grant");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("AccessAll")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Group");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.GroupUser", b =>
+                {
+                    b.Property<Guid>("GroupId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("OrganizationUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("GroupId", "OrganizationUserId");
+
+                    b.HasIndex("OrganizationUserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("GroupUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Installation", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Key")
+                        .HasMaxLength(150)
+                        .HasColumnType("varchar(150)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Installation");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Organization", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("ApiKey")
+                        .HasMaxLength(30)
+                        .HasColumnType("varchar(30)");
+
+                    b.Property<string>("BillingEmail")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<string>("BusinessAddress1")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessAddress2")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessAddress3")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessCountry")
+                        .HasMaxLength(2)
+                        .HasColumnType("varchar(2)");
+
+                    b.Property<string>("BusinessName")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessTaxNumber")
+                        .HasMaxLength(30)
+                        .HasColumnType("varchar(30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("GatewayCustomerId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("GatewaySubscriptionId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Identifier")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("LicenseKey")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<short?>("MaxCollections")
+                        .HasColumnType("smallint");
+
+                    b.Property<short?>("MaxStorageGb")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Plan")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<byte>("PlanType")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("PrivateKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("PublicKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ReferenceData")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int?>("Seats")
+                        .HasColumnType("int");
+
+                    b.Property<bool>("SelfHost")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<long?>("Storage")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("TwoFactorProviders")
+                        .HasColumnType("longtext");
+
+                    b.Property<bool>("Use2fa")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseApi")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseDirectory")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseEvents")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseGroups")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UsePolicies")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseResetPassword")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseSso")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseTotp")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UsersGetPremium")
+                        .HasColumnType("tinyint(1)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("AccessAll")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ResetPasswordKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Policy", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Policy");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.Provider", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("BillingEmail")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessAddress1")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessAddress2")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessAddress3")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessCountry")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessName")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessTaxNumber")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Provider");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("ProviderId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Settings")
+                        .HasColumnType("longtext");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("ProviderId");
+
+                    b.ToTable("ProviderOrganization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganizationProviderUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("ProviderOrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("ProviderUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProviderOrganizationId");
+
+                    b.HasIndex("ProviderUserId");
+
+                    b.ToTable("ProviderOrganizationProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("ProviderId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProviderId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("ProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Send", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<int>("AccessCount")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("DeletionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool>("Disabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool?>("HideEmail")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<int?>("MaxAccessCount")
+                        .HasColumnType("int");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Password")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Send");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoConfig", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("SsoConfig");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoUser", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("SsoUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.TaxRate", b =>
+                {
+                    b.Property<string>("Id")
+                        .HasMaxLength(40)
+                        .HasColumnType("varchar(40)");
+
+                    b.Property<bool>("Active")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Country")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("PostalCode")
+                        .HasMaxLength(10)
+                        .HasColumnType("varchar(10)");
+
+                    b.Property<decimal>("Rate")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("State")
+                        .HasMaxLength(2)
+                        .HasColumnType("varchar(2)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("TaxRate");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Transaction", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Details")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("GatewayId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<byte?>("PaymentMethodType")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<bool?>("Refunded")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<decimal?>("RefundedAmount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Transaction");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.U2f", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("AppId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Challenge")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("KeyHandle")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Version")
+                        .HasMaxLength(20)
+                        .HasColumnType("varchar(20)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("U2f");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.User", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("AccountRevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ApiKey")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("varchar(30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Culture")
+                        .HasMaxLength(10)
+                        .HasColumnType("varchar(10)");
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<bool>("EmailVerified")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("EquivalentDomains")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ExcludedGlobalEquivalentDomains")
+                        .HasColumnType("longtext");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("GatewayCustomerId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("GatewaySubscriptionId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<byte>("Kdf")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<int>("KdfIterations")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("LicenseKey")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<string>("MasterPassword")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("MasterPasswordHint")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<short?>("MaxStorageGb")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<bool>("Premium")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime?>("PremiumExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("PrivateKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("PublicKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ReferenceData")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime?>("RenewalReminderDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("SecurityStamp")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<long?>("Storage")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("TwoFactorProviders")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("TwoFactorRecoveryCode")
+                        .HasMaxLength(32)
+                        .HasColumnType("varchar(32)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Ciphers")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Ciphers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionCipher", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Cipher", "Cipher")
+                        .WithMany("CollectionCiphers")
+                        .HasForeignKey("CipherId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionCiphers")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Cipher");
+
+                    b.Navigation("Collection");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionGroup", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionGroups")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Group", "Group")
+                        .WithMany()
+                        .HasForeignKey("GroupId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Collection");
+
+                    b.Navigation("Group");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.OrganizationUser", "OrganizationUser")
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("OrganizationUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", null)
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Collection");
+
+                    b.Navigation("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Device", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.EmergencyAccess", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "Grantee")
+                        .WithMany()
+                        .HasForeignKey("GranteeId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "Grantor")
+                        .WithMany()
+                        .HasForeignKey("GrantorId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Grantee");
+
+                    b.Navigation("Grantor");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Folder", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Folders")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Groups")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.GroupUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Group", "Group")
+                        .WithMany("GroupUsers")
+                        .HasForeignKey("GroupId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.OrganizationUser", "OrganizationUser")
+                        .WithMany()
+                        .HasForeignKey("OrganizationUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", null)
+                        .WithMany("GroupUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Group");
+
+                    b.Navigation("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("OrganizationUsers")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("OrganizationUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Policy", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Policies")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.Provider", "Provider")
+                        .WithMany()
+                        .HasForeignKey("ProviderId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("Provider");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganizationProviderUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", "ProviderOrganization")
+                        .WithMany()
+                        .HasForeignKey("ProviderOrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.ProviderUser", "ProviderUser")
+                        .WithMany()
+                        .HasForeignKey("ProviderUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("ProviderOrganization");
+
+                    b.Navigation("ProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.Provider", "Provider")
+                        .WithMany()
+                        .HasForeignKey("ProviderId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Provider");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Send", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoConfig", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("SsoConfigs")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("SsoUsers")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("SsoUsers")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Transaction", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Transactions")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Transactions")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.U2f", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("U2fs")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.Navigation("CollectionCiphers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.Navigation("CollectionCiphers");
+
+                    b.Navigation("CollectionGroups");
+
+                    b.Navigation("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.Navigation("GroupUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Organization", b =>
+                {
+                    b.Navigation("Ciphers");
+
+                    b.Navigation("Groups");
+
+                    b.Navigation("OrganizationUsers");
+
+                    b.Navigation("Policies");
+
+                    b.Navigation("SsoConfigs");
+
+                    b.Navigation("SsoUsers");
+
+                    b.Navigation("Transactions");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.Navigation("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.User", b =>
+                {
+                    b.Navigation("Ciphers");
+
+                    b.Navigation("CollectionUsers");
+
+                    b.Navigation("Folders");
+
+                    b.Navigation("GroupUsers");
+
+                    b.Navigation("OrganizationUsers");
+
+                    b.Navigation("SsoUsers");
+
+                    b.Navigation("Transactions");
+
+                    b.Navigation("U2fs");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/util/MySqlMigrations/MySqlMigrations.csproj b/util/MySqlMigrations/MySqlMigrations.csproj
new file mode 100644
index 0000000000..d07adb1dc6
--- /dev/null
+++ b/util/MySqlMigrations/MySqlMigrations.csproj
@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\Core\Core.csproj" />
+    <ProjectReference Include="..\..\src\Api\Api.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.5">
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+      <PrivateAssets>all</PrivateAssets>
+    </PackageReference>
+  </ItemGroup>
+
+</Project>
diff --git a/util/MySqlMigrations/Scripts/Init.sql b/util/MySqlMigrations/Scripts/Init.sql
new file mode 100644
index 0000000000..9dc51948a4
--- /dev/null
+++ b/util/MySqlMigrations/Scripts/Init.sql
@@ -0,0 +1,491 @@
+ALTER DATABASE CHARACTER SET utf8mb4;
+CREATE TABLE IF NOT EXISTS `__EFMigrationsHistory` (
+    `MigrationId` varchar(150) CHARACTER SET utf8mb4 NOT NULL,
+    `ProductVersion` varchar(32) CHARACTER SET utf8mb4 NOT NULL,
+    CONSTRAINT `PK___EFMigrationsHistory` PRIMARY KEY (`MigrationId`)
+) CHARACTER SET utf8mb4;
+
+START TRANSACTION;
+
+ALTER DATABASE CHARACTER SET utf8mb4;
+
+CREATE TABLE `Event` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Date` datetime(6) NOT NULL,
+    `Type` int NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NULL,
+    `CipherId` char(36) COLLATE ascii_general_ci NULL,
+    `CollectionId` char(36) COLLATE ascii_general_ci NULL,
+    `PolicyId` char(36) COLLATE ascii_general_ci NULL,
+    `GroupId` char(36) COLLATE ascii_general_ci NULL,
+    `OrganizationUserId` char(36) COLLATE ascii_general_ci NULL,
+    `DeviceType` tinyint unsigned NULL,
+    `IpAddress` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `ActingUserId` char(36) COLLATE ascii_general_ci NULL,
+    CONSTRAINT `PK_Event` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Grant` (
+    `Key` varchar(200) CHARACTER SET utf8mb4 NOT NULL,
+    `Type` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `SubjectId` varchar(200) CHARACTER SET utf8mb4 NULL,
+    `SessionId` varchar(100) CHARACTER SET utf8mb4 NULL,
+    `ClientId` varchar(200) CHARACTER SET utf8mb4 NULL,
+    `Description` varchar(200) CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `ExpirationDate` datetime(6) NULL,
+    `ConsumedDate` datetime(6) NULL,
+    `Data` longtext CHARACTER SET utf8mb4 NULL,
+    CONSTRAINT `PK_Grant` PRIMARY KEY (`Key`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Installation` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Email` varchar(256) CHARACTER SET utf8mb4 NULL,
+    `Key` varchar(150) CHARACTER SET utf8mb4 NULL,
+    `Enabled` tinyint(1) NOT NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_Installation` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Organization` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Identifier` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `Name` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `BusinessName` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `BusinessAddress1` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `BusinessAddress2` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `BusinessAddress3` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `BusinessCountry` varchar(2) CHARACTER SET utf8mb4 NULL,
+    `BusinessTaxNumber` varchar(30) CHARACTER SET utf8mb4 NULL,
+    `BillingEmail` varchar(256) CHARACTER SET utf8mb4 NULL,
+    `Plan` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `PlanType` tinyint unsigned NOT NULL,
+    `Seats` int NULL,
+    `MaxCollections` smallint NULL,
+    `UsePolicies` tinyint(1) NOT NULL,
+    `UseSso` tinyint(1) NOT NULL,
+    `UseGroups` tinyint(1) NOT NULL,
+    `UseDirectory` tinyint(1) NOT NULL,
+    `UseEvents` tinyint(1) NOT NULL,
+    `UseTotp` tinyint(1) NOT NULL,
+    `Use2fa` tinyint(1) NOT NULL,
+    `UseApi` tinyint(1) NOT NULL,
+    `UseResetPassword` tinyint(1) NOT NULL,
+    `SelfHost` tinyint(1) NOT NULL,
+    `UsersGetPremium` tinyint(1) NOT NULL,
+    `Storage` bigint NULL,
+    `MaxStorageGb` smallint NULL,
+    `Gateway` tinyint unsigned NULL,
+    `GatewayCustomerId` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `GatewaySubscriptionId` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `ReferenceData` longtext CHARACTER SET utf8mb4 NULL,
+    `Enabled` tinyint(1) NOT NULL,
+    `LicenseKey` varchar(100) CHARACTER SET utf8mb4 NULL,
+    `ApiKey` varchar(30) CHARACTER SET utf8mb4 NULL,
+    `PublicKey` longtext CHARACTER SET utf8mb4 NULL,
+    `PrivateKey` longtext CHARACTER SET utf8mb4 NULL,
+    `TwoFactorProviders` longtext CHARACTER SET utf8mb4 NULL,
+    `ExpirationDate` datetime(6) NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_Organization` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Provider` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Name` longtext CHARACTER SET utf8mb4 NULL,
+    `BusinessName` longtext CHARACTER SET utf8mb4 NULL,
+    `BusinessAddress1` longtext CHARACTER SET utf8mb4 NULL,
+    `BusinessAddress2` longtext CHARACTER SET utf8mb4 NULL,
+    `BusinessAddress3` longtext CHARACTER SET utf8mb4 NULL,
+    `BusinessCountry` longtext CHARACTER SET utf8mb4 NULL,
+    `BusinessTaxNumber` longtext CHARACTER SET utf8mb4 NULL,
+    `BillingEmail` longtext CHARACTER SET utf8mb4 NULL,
+    `Status` tinyint unsigned NOT NULL,
+    `Enabled` tinyint(1) NOT NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_Provider` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `TaxRate` (
+    `Id` varchar(40) CHARACTER SET utf8mb4 NOT NULL,
+    `Country` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `State` varchar(2) CHARACTER SET utf8mb4 NULL,
+    `PostalCode` varchar(10) CHARACTER SET utf8mb4 NULL,
+    `Rate` decimal(65,30) NOT NULL,
+    `Active` tinyint(1) NOT NULL,
+    CONSTRAINT `PK_TaxRate` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `User` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Name` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `Email` varchar(256) CHARACTER SET utf8mb4 NOT NULL,
+    `EmailVerified` tinyint(1) NOT NULL,
+    `MasterPassword` varchar(300) CHARACTER SET utf8mb4 NULL,
+    `MasterPasswordHint` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `Culture` varchar(10) CHARACTER SET utf8mb4 NULL,
+    `SecurityStamp` varchar(50) CHARACTER SET utf8mb4 NOT NULL,
+    `TwoFactorProviders` longtext CHARACTER SET utf8mb4 NULL,
+    `TwoFactorRecoveryCode` varchar(32) CHARACTER SET utf8mb4 NULL,
+    `EquivalentDomains` longtext CHARACTER SET utf8mb4 NULL,
+    `ExcludedGlobalEquivalentDomains` longtext CHARACTER SET utf8mb4 NULL,
+    `AccountRevisionDate` datetime(6) NOT NULL,
+    `Key` longtext CHARACTER SET utf8mb4 NULL,
+    `PublicKey` longtext CHARACTER SET utf8mb4 NULL,
+    `PrivateKey` longtext CHARACTER SET utf8mb4 NULL,
+    `Premium` tinyint(1) NOT NULL,
+    `PremiumExpirationDate` datetime(6) NULL,
+    `RenewalReminderDate` datetime(6) NULL,
+    `Storage` bigint NULL,
+    `MaxStorageGb` smallint NULL,
+    `Gateway` tinyint unsigned NULL,
+    `GatewayCustomerId` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `GatewaySubscriptionId` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `ReferenceData` longtext CHARACTER SET utf8mb4 NULL,
+    `LicenseKey` varchar(100) CHARACTER SET utf8mb4 NULL,
+    `ApiKey` varchar(30) CHARACTER SET utf8mb4 NOT NULL,
+    `Kdf` tinyint unsigned NOT NULL,
+    `KdfIterations` int NOT NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_User` PRIMARY KEY (`Id`)
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Collection` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Name` longtext CHARACTER SET utf8mb4 NULL,
+    `ExternalId` varchar(300) CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_Collection` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Collection_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Group` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Name` varchar(100) CHARACTER SET utf8mb4 NULL,
+    `AccessAll` tinyint(1) NOT NULL,
+    `ExternalId` varchar(300) CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_Group` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Group_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Policy` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Type` tinyint unsigned NOT NULL,
+    `Data` longtext CHARACTER SET utf8mb4 NULL,
+    `Enabled` tinyint(1) NOT NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_Policy` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Policy_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `SsoConfig` (
+    `Id` bigint NOT NULL AUTO_INCREMENT,
+    `Enabled` tinyint(1) NOT NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Data` longtext CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_SsoConfig` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_SsoConfig_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `ProviderOrganization` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `ProviderId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Key` longtext CHARACTER SET utf8mb4 NULL,
+    `Settings` longtext CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_ProviderOrganization` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_ProviderOrganization_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_ProviderOrganization_Provider_ProviderId` FOREIGN KEY (`ProviderId`) REFERENCES `Provider` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Cipher` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NULL,
+    `Type` tinyint unsigned NOT NULL,
+    `Data` longtext CHARACTER SET utf8mb4 NULL,
+    `Favorites` longtext CHARACTER SET utf8mb4 NULL,
+    `Folders` longtext CHARACTER SET utf8mb4 NULL,
+    `Attachments` longtext CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    `DeletedDate` datetime(6) NULL,
+    `Reprompt` tinyint unsigned NULL,
+    CONSTRAINT `PK_Cipher` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Cipher_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_Cipher_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Device` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Name` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `Type` tinyint unsigned NOT NULL,
+    `Identifier` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `PushToken` varchar(255) CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_Device` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Device_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `EmergencyAccess` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `GrantorId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `GranteeId` char(36) COLLATE ascii_general_ci NULL,
+    `Email` varchar(256) CHARACTER SET utf8mb4 NULL,
+    `KeyEncrypted` longtext CHARACTER SET utf8mb4 NULL,
+    `Type` tinyint unsigned NOT NULL,
+    `Status` tinyint unsigned NOT NULL,
+    `WaitTimeDays` int NOT NULL,
+    `RecoveryInitiatedDate` datetime(6) NULL,
+    `LastNotificationDate` datetime(6) NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_EmergencyAccess` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_EmergencyAccess_User_GranteeId` FOREIGN KEY (`GranteeId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_EmergencyAccess_User_GrantorId` FOREIGN KEY (`GrantorId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Folder` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Name` longtext CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_Folder` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Folder_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `OrganizationUser` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NULL,
+    `Email` varchar(256) CHARACTER SET utf8mb4 NULL,
+    `Key` longtext CHARACTER SET utf8mb4 NULL,
+    `ResetPasswordKey` longtext CHARACTER SET utf8mb4 NULL,
+    `Status` tinyint unsigned NOT NULL,
+    `Type` tinyint unsigned NOT NULL,
+    `AccessAll` tinyint(1) NOT NULL,
+    `ExternalId` varchar(300) CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    `Permissions` longtext CHARACTER SET utf8mb4 NULL,
+    CONSTRAINT `PK_OrganizationUser` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_OrganizationUser_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_OrganizationUser_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `ProviderUser` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `ProviderId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NULL,
+    `Email` longtext CHARACTER SET utf8mb4 NULL,
+    `Key` longtext CHARACTER SET utf8mb4 NULL,
+    `Status` tinyint unsigned NOT NULL,
+    `Type` tinyint unsigned NOT NULL,
+    `Permissions` longtext CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_ProviderUser` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_ProviderUser_Provider_ProviderId` FOREIGN KEY (`ProviderId`) REFERENCES `Provider` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_ProviderUser_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Send` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NULL,
+    `Type` tinyint unsigned NOT NULL,
+    `Data` longtext CHARACTER SET utf8mb4 NULL,
+    `Key` longtext CHARACTER SET utf8mb4 NULL,
+    `Password` varchar(300) CHARACTER SET utf8mb4 NULL,
+    `MaxAccessCount` int NULL,
+    `AccessCount` int NOT NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    `ExpirationDate` datetime(6) NULL,
+    `DeletionDate` datetime(6) NOT NULL,
+    `Disabled` tinyint(1) NOT NULL,
+    `HideEmail` tinyint(1) NULL,
+    CONSTRAINT `PK_Send` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Send_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_Send_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `SsoUser` (
+    `Id` bigint NOT NULL AUTO_INCREMENT,
+    `UserId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NULL,
+    `ExternalId` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_SsoUser` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_SsoUser_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_SsoUser_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `Transaction` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NULL,
+    `OrganizationId` char(36) COLLATE ascii_general_ci NULL,
+    `Type` tinyint unsigned NOT NULL,
+    `Amount` decimal(65,30) NOT NULL,
+    `Refunded` tinyint(1) NULL,
+    `RefundedAmount` decimal(65,30) NULL,
+    `Details` varchar(100) CHARACTER SET utf8mb4 NULL,
+    `PaymentMethodType` tinyint unsigned NULL,
+    `Gateway` tinyint unsigned NULL,
+    `GatewayId` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_Transaction` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_Transaction_Organization_OrganizationId` FOREIGN KEY (`OrganizationId`) REFERENCES `Organization` (`Id`) ON DELETE RESTRICT,
+    CONSTRAINT `FK_Transaction_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `U2f` (
+    `Id` int NOT NULL AUTO_INCREMENT,
+    `UserId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `KeyHandle` varchar(200) CHARACTER SET utf8mb4 NULL,
+    `Challenge` varchar(200) CHARACTER SET utf8mb4 NULL,
+    `AppId` varchar(50) CHARACTER SET utf8mb4 NULL,
+    `Version` varchar(20) CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_U2f` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_U2f_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `CollectionGroups` (
+    `CollectionId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `GroupId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `ReadOnly` tinyint(1) NOT NULL,
+    `HidePasswords` tinyint(1) NOT NULL,
+    CONSTRAINT `PK_CollectionGroups` PRIMARY KEY (`CollectionId`, `GroupId`),
+    CONSTRAINT `FK_CollectionGroups_Collection_CollectionId` FOREIGN KEY (`CollectionId`) REFERENCES `Collection` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_CollectionGroups_Group_GroupId` FOREIGN KEY (`GroupId`) REFERENCES `Group` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `CollectionCipher` (
+    `CollectionId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `CipherId` char(36) COLLATE ascii_general_ci NOT NULL,
+    CONSTRAINT `PK_CollectionCipher` PRIMARY KEY (`CollectionId`, `CipherId`),
+    CONSTRAINT `FK_CollectionCipher_Cipher_CipherId` FOREIGN KEY (`CipherId`) REFERENCES `Cipher` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_CollectionCipher_Collection_CollectionId` FOREIGN KEY (`CollectionId`) REFERENCES `Collection` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `CollectionUsers` (
+    `CollectionId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `OrganizationUserId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NULL,
+    `ReadOnly` tinyint(1) NOT NULL,
+    `HidePasswords` tinyint(1) NOT NULL,
+    CONSTRAINT `PK_CollectionUsers` PRIMARY KEY (`CollectionId`, `OrganizationUserId`),
+    CONSTRAINT `FK_CollectionUsers_Collection_CollectionId` FOREIGN KEY (`CollectionId`) REFERENCES `Collection` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_CollectionUsers_OrganizationUser_OrganizationUserId` FOREIGN KEY (`OrganizationUserId`) REFERENCES `OrganizationUser` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_CollectionUsers_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `GroupUser` (
+    `GroupId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `OrganizationUserId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `UserId` char(36) COLLATE ascii_general_ci NULL,
+    CONSTRAINT `PK_GroupUser` PRIMARY KEY (`GroupId`, `OrganizationUserId`),
+    CONSTRAINT `FK_GroupUser_Group_GroupId` FOREIGN KEY (`GroupId`) REFERENCES `Group` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_GroupUser_OrganizationUser_OrganizationUserId` FOREIGN KEY (`OrganizationUserId`) REFERENCES `OrganizationUser` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_GroupUser_User_UserId` FOREIGN KEY (`UserId`) REFERENCES `User` (`Id`) ON DELETE RESTRICT
+) CHARACTER SET utf8mb4;
+
+CREATE TABLE `ProviderOrganizationProviderUser` (
+    `Id` char(36) COLLATE ascii_general_ci NOT NULL,
+    `ProviderOrganizationId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `ProviderUserId` char(36) COLLATE ascii_general_ci NOT NULL,
+    `Type` tinyint unsigned NOT NULL,
+    `Permissions` longtext CHARACTER SET utf8mb4 NULL,
+    `CreationDate` datetime(6) NOT NULL,
+    `RevisionDate` datetime(6) NOT NULL,
+    CONSTRAINT `PK_ProviderOrganizationProviderUser` PRIMARY KEY (`Id`),
+    CONSTRAINT `FK_ProviderOrganizationProviderUser_ProviderOrganization_Provid~` FOREIGN KEY (`ProviderOrganizationId`) REFERENCES `ProviderOrganization` (`Id`) ON DELETE CASCADE,
+    CONSTRAINT `FK_ProviderOrganizationProviderUser_ProviderUser_ProviderUserId` FOREIGN KEY (`ProviderUserId`) REFERENCES `ProviderUser` (`Id`) ON DELETE CASCADE
+) CHARACTER SET utf8mb4;
+
+CREATE INDEX `IX_Cipher_OrganizationId` ON `Cipher` (`OrganizationId`);
+
+CREATE INDEX `IX_Cipher_UserId` ON `Cipher` (`UserId`);
+
+CREATE INDEX `IX_Collection_OrganizationId` ON `Collection` (`OrganizationId`);
+
+CREATE INDEX `IX_CollectionCipher_CipherId` ON `CollectionCipher` (`CipherId`);
+
+CREATE INDEX `IX_CollectionGroups_GroupId` ON `CollectionGroups` (`GroupId`);
+
+CREATE INDEX `IX_CollectionUsers_OrganizationUserId` ON `CollectionUsers` (`OrganizationUserId`);
+
+CREATE INDEX `IX_CollectionUsers_UserId` ON `CollectionUsers` (`UserId`);
+
+CREATE INDEX `IX_Device_UserId` ON `Device` (`UserId`);
+
+CREATE INDEX `IX_EmergencyAccess_GranteeId` ON `EmergencyAccess` (`GranteeId`);
+
+CREATE INDEX `IX_EmergencyAccess_GrantorId` ON `EmergencyAccess` (`GrantorId`);
+
+CREATE INDEX `IX_Folder_UserId` ON `Folder` (`UserId`);
+
+CREATE INDEX `IX_Group_OrganizationId` ON `Group` (`OrganizationId`);
+
+CREATE INDEX `IX_GroupUser_OrganizationUserId` ON `GroupUser` (`OrganizationUserId`);
+
+CREATE INDEX `IX_GroupUser_UserId` ON `GroupUser` (`UserId`);
+
+CREATE INDEX `IX_OrganizationUser_OrganizationId` ON `OrganizationUser` (`OrganizationId`);
+
+CREATE INDEX `IX_OrganizationUser_UserId` ON `OrganizationUser` (`UserId`);
+
+CREATE INDEX `IX_Policy_OrganizationId` ON `Policy` (`OrganizationId`);
+
+CREATE INDEX `IX_ProviderOrganization_OrganizationId` ON `ProviderOrganization` (`OrganizationId`);
+
+CREATE INDEX `IX_ProviderOrganization_ProviderId` ON `ProviderOrganization` (`ProviderId`);
+
+CREATE INDEX `IX_ProviderOrganizationProviderUser_ProviderOrganizationId` ON `ProviderOrganizationProviderUser` (`ProviderOrganizationId`);
+
+CREATE INDEX `IX_ProviderOrganizationProviderUser_ProviderUserId` ON `ProviderOrganizationProviderUser` (`ProviderUserId`);
+
+CREATE INDEX `IX_ProviderUser_ProviderId` ON `ProviderUser` (`ProviderId`);
+
+CREATE INDEX `IX_ProviderUser_UserId` ON `ProviderUser` (`UserId`);
+
+CREATE INDEX `IX_Send_OrganizationId` ON `Send` (`OrganizationId`);
+
+CREATE INDEX `IX_Send_UserId` ON `Send` (`UserId`);
+
+CREATE INDEX `IX_SsoConfig_OrganizationId` ON `SsoConfig` (`OrganizationId`);
+
+CREATE INDEX `IX_SsoUser_OrganizationId` ON `SsoUser` (`OrganizationId`);
+
+CREATE INDEX `IX_SsoUser_UserId` ON `SsoUser` (`UserId`);
+
+CREATE INDEX `IX_Transaction_OrganizationId` ON `Transaction` (`OrganizationId`);
+
+CREATE INDEX `IX_Transaction_UserId` ON `Transaction` (`UserId`);
+
+CREATE INDEX `IX_U2f_UserId` ON `U2f` (`UserId`);
+
+INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`)
+VALUES ('20210617183900_Init', '5.0.5');
+
+COMMIT;
\ No newline at end of file
diff --git a/util/PostgresMigrations/Factories.cs b/util/PostgresMigrations/Factories.cs
new file mode 100644
index 0000000000..1fad15f524
--- /dev/null
+++ b/util/PostgresMigrations/Factories.cs
@@ -0,0 +1,68 @@
+using System.Collections.Generic;
+using Bit.Core.Repositories.EntityFramework;
+using Bit.Core.Settings;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Configuration;
+using Bit.Core.Enums;
+using Microsoft.EntityFrameworkCore.Design;
+using System;
+
+namespace MySqlMigrations
+{
+    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 class DatabaseContextFactory : IDesignTimeDbContextFactory<DatabaseContext>
+    {
+        public DatabaseContext CreateDbContext(string[] args)
+        {
+            var globalSettings = GlobalSettingsFactory.GlobalSettings;
+            var optionsBuilder = new DbContextOptionsBuilder<DatabaseContext>();
+
+            var selectedDatabaseProvider = globalSettings.DatabaseProvider;
+            var provider = SupportedDatabaseProviders.Postgres;
+            var connectionString = string.Empty;
+            if (!string.IsNullOrWhiteSpace(selectedDatabaseProvider))
+            {
+                switch (selectedDatabaseProvider.ToLowerInvariant())
+                {
+                    case "postgres":
+                    case "postgresql":
+                        provider = SupportedDatabaseProviders.Postgres;
+                        connectionString = globalSettings.PostgreSql.ConnectionString;
+                        break;
+                    case "mysql":
+                    case "mariadb":
+                        provider = SupportedDatabaseProviders.MySql;
+                        connectionString = globalSettings.MySql.ConnectionString;
+                        break;
+                    default:
+                        throw new Exception("No database provider selected");
+                        break;
+                }
+            }
+            if (provider.Equals(SupportedDatabaseProviders.Postgres))
+            {
+                optionsBuilder.UseNpgsql(
+                    connectionString,  
+                    b => b.MigrationsAssembly("PostgresMigrations"));
+            }
+            else if (provider.Equals(SupportedDatabaseProviders.MySql))
+            {
+                optionsBuilder.UseMySql(
+                    connectionString, 
+                    ServerVersion.AutoDetect(connectionString),
+                    b => b.MigrationsAssembly("MySqlMigrations"));
+            }
+            return new DatabaseContext(optionsBuilder.Options);
+        }
+    }
+}
diff --git a/util/PostgresMigrations/Migrations/20210617163014_Postgres_Init.Designer.cs b/util/PostgresMigrations/Migrations/20210617163014_Postgres_Init.Designer.cs
new file mode 100644
index 0000000000..1cdd6c9bd3
--- /dev/null
+++ b/util/PostgresMigrations/Migrations/20210617163014_Postgres_Init.Designer.cs
@@ -0,0 +1,1531 @@
+// <auto-generated />
+using System;
+using Bit.Core.Repositories.EntityFramework;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+namespace Bit.EntityFrameworkMigrations.Migrations
+{
+    [DbContext(typeof(DatabaseContext))]
+    [Migration("20210617163014_Postgres_Init")]
+    partial class Postgres_Init
+    {
+        protected override void BuildTargetModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("Npgsql:CollationDefinition:postgresIndetermanisticCollation", "en-u-ks-primary,en-u-ks-primary,icu,False")
+                .HasAnnotation("Relational:MaxIdentifierLength", 63)
+                .HasAnnotation("ProductVersion", "5.0.5")
+                .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<string>("Attachments")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime?>("DeletedDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Favorites")
+                        .HasColumnType("text");
+
+                    b.Property<string>("Folders")
+                        .HasColumnType("text");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<byte?>("Reprompt")
+                        .HasColumnType("smallint");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("smallint");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Cipher");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("character varying(300)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("text");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Collection");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionCipher", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid>("CipherId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("CollectionId", "CipherId");
+
+                    b.HasIndex("CipherId");
+
+                    b.ToTable("CollectionCipher");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionGroup", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid>("GroupId")
+                        .HasColumnType("uuid");
+
+                    b.Property<bool>("HidePasswords")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("ReadOnly")
+                        .HasColumnType("boolean");
+
+                    b.HasKey("CollectionId", "GroupId");
+
+                    b.HasIndex("GroupId");
+
+                    b.ToTable("CollectionGroups");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionUser", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid>("OrganizationUserId")
+                        .HasColumnType("uuid");
+
+                    b.Property<bool>("HidePasswords")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("ReadOnly")
+                        .HasColumnType("boolean");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("CollectionId", "OrganizationUserId");
+
+                    b.HasIndex("OrganizationUserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Device", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Identifier")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("PushToken")
+                        .HasMaxLength(255)
+                        .HasColumnType("character varying(255)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("smallint");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Device");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.EmergencyAccess", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<Guid?>("GranteeId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid>("GrantorId")
+                        .HasColumnType("uuid");
+
+                    b.Property<string>("KeyEncrypted")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime?>("LastNotificationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<DateTime?>("RecoveryInitiatedDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("smallint");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("smallint");
+
+                    b.Property<int>("WaitTimeDays")
+                        .HasColumnType("integer");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("GranteeId");
+
+                    b.HasIndex("GrantorId");
+
+                    b.ToTable("EmergencyAccess");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Event", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid?>("ActingUserId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid?>("CipherId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid?>("CollectionId")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte?>("DeviceType")
+                        .HasColumnType("smallint");
+
+                    b.Property<Guid?>("GroupId")
+                        .HasColumnType("uuid");
+
+                    b.Property<string>("IpAddress")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid?>("OrganizationUserId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid?>("PolicyId")
+                        .HasColumnType("uuid");
+
+                    b.Property<int>("Type")
+                        .HasColumnType("integer");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Event");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Folder", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Folder");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Grant", b =>
+                {
+                    b.Property<string>("Key")
+                        .HasMaxLength(200)
+                        .HasColumnType("character varying(200)");
+
+                    b.Property<string>("ClientId")
+                        .HasMaxLength(200)
+                        .HasColumnType("character varying(200)");
+
+                    b.Property<DateTime?>("ConsumedDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("text");
+
+                    b.Property<string>("Description")
+                        .HasMaxLength(200)
+                        .HasColumnType("character varying(200)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("SessionId")
+                        .HasMaxLength(100)
+                        .HasColumnType("character varying(100)");
+
+                    b.Property<string>("SubjectId")
+                        .HasMaxLength(200)
+                        .HasColumnType("character varying(200)");
+
+                    b.Property<string>("Type")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.HasKey("Key");
+
+                    b.ToTable("Grant");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<bool>("AccessAll")
+                        .HasColumnType("boolean");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("character varying(300)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(100)
+                        .HasColumnType("character varying(100)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Group");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.GroupUser", b =>
+                {
+                    b.Property<Guid>("GroupId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid>("OrganizationUserId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("GroupId", "OrganizationUserId");
+
+                    b.HasIndex("OrganizationUserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("GroupUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Installation", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("boolean");
+
+                    b.Property<string>("Key")
+                        .HasMaxLength(150)
+                        .HasColumnType("character varying(150)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Installation");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Organization", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<string>("ApiKey")
+                        .HasMaxLength(30)
+                        .HasColumnType("character varying(30)");
+
+                    b.Property<string>("BillingEmail")
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<string>("BusinessAddress1")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("BusinessAddress2")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("BusinessAddress3")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("BusinessCountry")
+                        .HasMaxLength(2)
+                        .HasColumnType("character varying(2)");
+
+                    b.Property<string>("BusinessName")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("BusinessTaxNumber")
+                        .HasMaxLength(30)
+                        .HasColumnType("character varying(30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("boolean");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("GatewayCustomerId")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("GatewaySubscriptionId")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Identifier")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)")
+                        .UseCollation("postgresIndetermanisticCollation");
+
+                    b.Property<string>("LicenseKey")
+                        .HasMaxLength(100)
+                        .HasColumnType("character varying(100)");
+
+                    b.Property<short?>("MaxCollections")
+                        .HasColumnType("smallint");
+
+                    b.Property<short?>("MaxStorageGb")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Plan")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<byte>("PlanType")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("PrivateKey")
+                        .HasColumnType("text");
+
+                    b.Property<string>("PublicKey")
+                        .HasColumnType("text");
+
+                    b.Property<string>("ReferenceData")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<int?>("Seats")
+                        .HasColumnType("integer");
+
+                    b.Property<bool>("SelfHost")
+                        .HasColumnType("boolean");
+
+                    b.Property<long?>("Storage")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("TwoFactorProviders")
+                        .HasColumnType("text");
+
+                    b.Property<bool>("Use2fa")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("UseApi")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("UseDirectory")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("UseEvents")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("UseGroups")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("UsePolicies")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("UseResetPassword")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("UseSso")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("UseTotp")
+                        .HasColumnType("boolean");
+
+                    b.Property<bool>("UsersGetPremium")
+                        .HasColumnType("boolean");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<bool>("AccessAll")
+                        .HasColumnType("boolean");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("character varying(300)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("text");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("text");
+
+                    b.Property<string>("ResetPasswordKey")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("smallint");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("smallint");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Policy", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("text");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("boolean");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("smallint");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Policy");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.Provider", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<string>("BillingEmail")
+                        .HasColumnType("text");
+
+                    b.Property<string>("BusinessAddress1")
+                        .HasColumnType("text");
+
+                    b.Property<string>("BusinessAddress2")
+                        .HasColumnType("text");
+
+                    b.Property<string>("BusinessAddress3")
+                        .HasColumnType("text");
+
+                    b.Property<string>("BusinessCountry")
+                        .HasColumnType("text");
+
+                    b.Property<string>("BusinessName")
+                        .HasColumnType("text");
+
+                    b.Property<string>("BusinessTaxNumber")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("boolean");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("smallint");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Provider");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("text");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid>("ProviderId")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Settings")
+                        .HasColumnType("text");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("ProviderId");
+
+                    b.ToTable("ProviderOrganization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganizationProviderUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("text");
+
+                    b.Property<Guid>("ProviderOrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid>("ProviderUserId")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("smallint");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProviderOrganizationId");
+
+                    b.HasIndex("ProviderUserId");
+
+                    b.ToTable("ProviderOrganizationProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Email")
+                        .HasColumnType("text");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("text");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("text");
+
+                    b.Property<Guid>("ProviderId")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("smallint");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("smallint");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProviderId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("ProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Send", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<int>("AccessCount")
+                        .HasColumnType("integer");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime>("DeletionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<bool>("Disabled")
+                        .HasColumnType("boolean");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<bool?>("HideEmail")
+                        .HasColumnType("boolean");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("text");
+
+                    b.Property<int?>("MaxAccessCount")
+                        .HasColumnType("integer");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<string>("Password")
+                        .HasMaxLength(300)
+                        .HasColumnType("character varying(300)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("smallint");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Send");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoConfig", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("text");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("boolean");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("SsoConfig");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoUser", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)")
+                        .UseCollation("postgresIndetermanisticCollation");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("SsoUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.TaxRate", b =>
+                {
+                    b.Property<string>("Id")
+                        .HasMaxLength(40)
+                        .HasColumnType("character varying(40)");
+
+                    b.Property<bool>("Active")
+                        .HasColumnType("boolean");
+
+                    b.Property<string>("Country")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("PostalCode")
+                        .HasMaxLength(10)
+                        .HasColumnType("character varying(10)");
+
+                    b.Property<decimal>("Rate")
+                        .HasColumnType("numeric");
+
+                    b.Property<string>("State")
+                        .HasMaxLength(2)
+                        .HasColumnType("character varying(2)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("TaxRate");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Transaction", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("numeric");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Details")
+                        .HasMaxLength(100)
+                        .HasColumnType("character varying(100)");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("GatewayId")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("uuid");
+
+                    b.Property<byte?>("PaymentMethodType")
+                        .HasColumnType("smallint");
+
+                    b.Property<bool?>("Refunded")
+                        .HasColumnType("boolean");
+
+                    b.Property<decimal?>("RefundedAmount")
+                        .HasColumnType("numeric");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("smallint");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Transaction");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.U2f", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("integer")
+                        .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn);
+
+                    b.Property<string>("AppId")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("Challenge")
+                        .HasMaxLength(200)
+                        .HasColumnType("character varying(200)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("KeyHandle")
+                        .HasMaxLength(200)
+                        .HasColumnType("character varying(200)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("uuid");
+
+                    b.Property<string>("Version")
+                        .HasMaxLength(20)
+                        .HasColumnType("character varying(20)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("U2f");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.User", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("uuid");
+
+                    b.Property<DateTime>("AccountRevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("ApiKey")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("character varying(30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("Culture")
+                        .HasMaxLength(10)
+                        .HasColumnType("character varying(10)");
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("character varying(256)")
+                        .UseCollation("postgresIndetermanisticCollation");
+
+                    b.Property<bool>("EmailVerified")
+                        .HasColumnType("boolean");
+
+                    b.Property<string>("EquivalentDomains")
+                        .HasColumnType("text");
+
+                    b.Property<string>("ExcludedGlobalEquivalentDomains")
+                        .HasColumnType("text");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("GatewayCustomerId")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<string>("GatewaySubscriptionId")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<byte>("Kdf")
+                        .HasColumnType("smallint");
+
+                    b.Property<int>("KdfIterations")
+                        .HasColumnType("integer");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("text");
+
+                    b.Property<string>("LicenseKey")
+                        .HasMaxLength(100)
+                        .HasColumnType("character varying(100)");
+
+                    b.Property<string>("MasterPassword")
+                        .HasMaxLength(300)
+                        .HasColumnType("character varying(300)");
+
+                    b.Property<string>("MasterPasswordHint")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<short?>("MaxStorageGb")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<bool>("Premium")
+                        .HasColumnType("boolean");
+
+                    b.Property<DateTime?>("PremiumExpirationDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("PrivateKey")
+                        .HasColumnType("text");
+
+                    b.Property<string>("PublicKey")
+                        .HasColumnType("text");
+
+                    b.Property<string>("ReferenceData")
+                        .HasColumnType("text");
+
+                    b.Property<DateTime?>("RenewalReminderDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("timestamp without time zone");
+
+                    b.Property<string>("SecurityStamp")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("character varying(50)");
+
+                    b.Property<long?>("Storage")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("TwoFactorProviders")
+                        .HasColumnType("text");
+
+                    b.Property<string>("TwoFactorRecoveryCode")
+                        .HasMaxLength(32)
+                        .HasColumnType("character varying(32)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Ciphers")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Ciphers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionCipher", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Cipher", "Cipher")
+                        .WithMany("CollectionCiphers")
+                        .HasForeignKey("CipherId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionCiphers")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Cipher");
+
+                    b.Navigation("Collection");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionGroup", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionGroups")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Group", "Group")
+                        .WithMany()
+                        .HasForeignKey("GroupId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Collection");
+
+                    b.Navigation("Group");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.OrganizationUser", "OrganizationUser")
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("OrganizationUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", null)
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Collection");
+
+                    b.Navigation("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Device", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.EmergencyAccess", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "Grantee")
+                        .WithMany()
+                        .HasForeignKey("GranteeId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "Grantor")
+                        .WithMany()
+                        .HasForeignKey("GrantorId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Grantee");
+
+                    b.Navigation("Grantor");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Folder", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Folders")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Groups")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.GroupUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Group", "Group")
+                        .WithMany("GroupUsers")
+                        .HasForeignKey("GroupId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.OrganizationUser", "OrganizationUser")
+                        .WithMany()
+                        .HasForeignKey("OrganizationUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", null)
+                        .WithMany("GroupUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Group");
+
+                    b.Navigation("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("OrganizationUsers")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("OrganizationUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Policy", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Policies")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.Provider", "Provider")
+                        .WithMany()
+                        .HasForeignKey("ProviderId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("Provider");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganizationProviderUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", "ProviderOrganization")
+                        .WithMany()
+                        .HasForeignKey("ProviderOrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.ProviderUser", "ProviderUser")
+                        .WithMany()
+                        .HasForeignKey("ProviderUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("ProviderOrganization");
+
+                    b.Navigation("ProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.Provider", "Provider")
+                        .WithMany()
+                        .HasForeignKey("ProviderId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Provider");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Send", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoConfig", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("SsoConfigs")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("SsoUsers")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("SsoUsers")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Transaction", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Transactions")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Transactions")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.U2f", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("U2fs")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.Navigation("CollectionCiphers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.Navigation("CollectionCiphers");
+
+                    b.Navigation("CollectionGroups");
+
+                    b.Navigation("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.Navigation("GroupUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Organization", b =>
+                {
+                    b.Navigation("Ciphers");
+
+                    b.Navigation("Groups");
+
+                    b.Navigation("OrganizationUsers");
+
+                    b.Navigation("Policies");
+
+                    b.Navigation("SsoConfigs");
+
+                    b.Navigation("SsoUsers");
+
+                    b.Navigation("Transactions");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.Navigation("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.User", b =>
+                {
+                    b.Navigation("Ciphers");
+
+                    b.Navigation("CollectionUsers");
+
+                    b.Navigation("Folders");
+
+                    b.Navigation("GroupUsers");
+
+                    b.Navigation("OrganizationUsers");
+
+                    b.Navigation("SsoUsers");
+
+                    b.Navigation("Transactions");
+
+                    b.Navigation("U2fs");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/util/PostgresMigrations/Migrations/20210617163014_Postgres_Init.cs b/util/PostgresMigrations/Migrations/20210617163014_Postgres_Init.cs
new file mode 100644
index 0000000000..1f0344dcb7
--- /dev/null
+++ b/util/PostgresMigrations/Migrations/20210617163014_Postgres_Init.cs
@@ -0,0 +1,1008 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+namespace Bit.EntityFrameworkMigrations.Migrations
+{
+    public partial class Postgres_Init : Migration
+    {
+        protected override void Up(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.AlterDatabase()
+                .Annotation("Npgsql:CollationDefinition:postgresIndetermanisticCollation", "en-u-ks-primary,en-u-ks-primary,icu,False");
+
+            migrationBuilder.CreateTable(
+                name: "Event",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    Date = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    Type = table.Column<int>(type: "integer", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: true),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: true),
+                    CipherId = table.Column<Guid>(type: "uuid", nullable: true),
+                    CollectionId = table.Column<Guid>(type: "uuid", nullable: true),
+                    PolicyId = table.Column<Guid>(type: "uuid", nullable: true),
+                    GroupId = table.Column<Guid>(type: "uuid", nullable: true),
+                    OrganizationUserId = table.Column<Guid>(type: "uuid", nullable: true),
+                    DeviceType = table.Column<byte>(type: "smallint", nullable: true),
+                    IpAddress = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    ActingUserId = table.Column<Guid>(type: "uuid", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Event", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Grant",
+                columns: table => new
+                {
+                    Key = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: false),
+                    Type = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    SubjectId = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
+                    SessionId = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
+                    ClientId = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
+                    Description = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    ExpirationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
+                    ConsumedDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
+                    Data = table.Column<string>(type: "text", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Grant", x => x.Key);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Installation",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
+                    Key = table.Column<string>(type: "character varying(150)", maxLength: 150, nullable: true),
+                    Enabled = table.Column<bool>(type: "boolean", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Installation", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Organization",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    Identifier = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true, collation: "postgresIndetermanisticCollation"),
+                    Name = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    BusinessName = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    BusinessAddress1 = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    BusinessAddress2 = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    BusinessAddress3 = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    BusinessCountry = table.Column<string>(type: "character varying(2)", maxLength: 2, nullable: true),
+                    BusinessTaxNumber = table.Column<string>(type: "character varying(30)", maxLength: 30, nullable: true),
+                    BillingEmail = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
+                    Plan = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    PlanType = table.Column<byte>(type: "smallint", nullable: false),
+                    Seats = table.Column<int>(type: "integer", nullable: true),
+                    MaxCollections = table.Column<short>(type: "smallint", nullable: true),
+                    UsePolicies = table.Column<bool>(type: "boolean", nullable: false),
+                    UseSso = table.Column<bool>(type: "boolean", nullable: false),
+                    UseGroups = table.Column<bool>(type: "boolean", nullable: false),
+                    UseDirectory = table.Column<bool>(type: "boolean", nullable: false),
+                    UseEvents = table.Column<bool>(type: "boolean", nullable: false),
+                    UseTotp = table.Column<bool>(type: "boolean", nullable: false),
+                    Use2fa = table.Column<bool>(type: "boolean", nullable: false),
+                    UseApi = table.Column<bool>(type: "boolean", nullable: false),
+                    UseResetPassword = table.Column<bool>(type: "boolean", nullable: false),
+                    SelfHost = table.Column<bool>(type: "boolean", nullable: false),
+                    UsersGetPremium = table.Column<bool>(type: "boolean", nullable: false),
+                    Storage = table.Column<long>(type: "bigint", nullable: true),
+                    MaxStorageGb = table.Column<short>(type: "smallint", nullable: true),
+                    Gateway = table.Column<byte>(type: "smallint", nullable: true),
+                    GatewayCustomerId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    GatewaySubscriptionId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    ReferenceData = table.Column<string>(type: "text", nullable: true),
+                    Enabled = table.Column<bool>(type: "boolean", nullable: false),
+                    LicenseKey = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
+                    ApiKey = table.Column<string>(type: "character varying(30)", maxLength: 30, nullable: true),
+                    PublicKey = table.Column<string>(type: "text", nullable: true),
+                    PrivateKey = table.Column<string>(type: "text", nullable: true),
+                    TwoFactorProviders = table.Column<string>(type: "text", nullable: true),
+                    ExpirationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Organization", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Provider",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    Name = table.Column<string>(type: "text", nullable: true),
+                    BusinessName = table.Column<string>(type: "text", nullable: true),
+                    BusinessAddress1 = table.Column<string>(type: "text", nullable: true),
+                    BusinessAddress2 = table.Column<string>(type: "text", nullable: true),
+                    BusinessAddress3 = table.Column<string>(type: "text", nullable: true),
+                    BusinessCountry = table.Column<string>(type: "text", nullable: true),
+                    BusinessTaxNumber = table.Column<string>(type: "text", nullable: true),
+                    BillingEmail = table.Column<string>(type: "text", nullable: true),
+                    Status = table.Column<byte>(type: "smallint", nullable: false),
+                    Enabled = table.Column<bool>(type: "boolean", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Provider", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "TaxRate",
+                columns: table => new
+                {
+                    Id = table.Column<string>(type: "character varying(40)", maxLength: 40, nullable: false),
+                    Country = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    State = table.Column<string>(type: "character varying(2)", maxLength: 2, nullable: true),
+                    PostalCode = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: true),
+                    Rate = table.Column<decimal>(type: "numeric", nullable: false),
+                    Active = table.Column<bool>(type: "boolean", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_TaxRate", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "User",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    Name = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: false, collation: "postgresIndetermanisticCollation"),
+                    EmailVerified = table.Column<bool>(type: "boolean", nullable: false),
+                    MasterPassword = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
+                    MasterPasswordHint = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    Culture = table.Column<string>(type: "character varying(10)", maxLength: 10, nullable: true),
+                    SecurityStamp = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
+                    TwoFactorProviders = table.Column<string>(type: "text", nullable: true),
+                    TwoFactorRecoveryCode = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: true),
+                    EquivalentDomains = table.Column<string>(type: "text", nullable: true),
+                    ExcludedGlobalEquivalentDomains = table.Column<string>(type: "text", nullable: true),
+                    AccountRevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    Key = table.Column<string>(type: "text", nullable: true),
+                    PublicKey = table.Column<string>(type: "text", nullable: true),
+                    PrivateKey = table.Column<string>(type: "text", nullable: true),
+                    Premium = table.Column<bool>(type: "boolean", nullable: false),
+                    PremiumExpirationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
+                    RenewalReminderDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
+                    Storage = table.Column<long>(type: "bigint", nullable: true),
+                    MaxStorageGb = table.Column<short>(type: "smallint", nullable: true),
+                    Gateway = table.Column<byte>(type: "smallint", nullable: true),
+                    GatewayCustomerId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    GatewaySubscriptionId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    ReferenceData = table.Column<string>(type: "text", nullable: true),
+                    LicenseKey = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
+                    ApiKey = table.Column<string>(type: "character varying(30)", maxLength: 30, nullable: false),
+                    Kdf = table.Column<byte>(type: "smallint", nullable: false),
+                    KdfIterations = table.Column<int>(type: "integer", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_User", x => x.Id);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Collection",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: false),
+                    Name = table.Column<string>(type: "text", nullable: true),
+                    ExternalId = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Collection", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Collection_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Group",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: false),
+                    Name = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
+                    AccessAll = table.Column<bool>(type: "boolean", nullable: false),
+                    ExternalId = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Group", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Group_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Policy",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: false),
+                    Type = table.Column<byte>(type: "smallint", nullable: false),
+                    Data = table.Column<string>(type: "text", nullable: true),
+                    Enabled = table.Column<bool>(type: "boolean", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Policy", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Policy_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "SsoConfig",
+                columns: table => new
+                {
+                    Id = table.Column<long>(type: "bigint", nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    Enabled = table.Column<bool>(type: "boolean", nullable: false),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: false),
+                    Data = table.Column<string>(type: "text", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_SsoConfig", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_SsoConfig_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "ProviderOrganization",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    ProviderId = table.Column<Guid>(type: "uuid", nullable: false),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: false),
+                    Key = table.Column<string>(type: "text", nullable: true),
+                    Settings = table.Column<string>(type: "text", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_ProviderOrganization", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_ProviderOrganization_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_ProviderOrganization_Provider_ProviderId",
+                        column: x => x.ProviderId,
+                        principalTable: "Provider",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Cipher",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: true),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: true),
+                    Type = table.Column<byte>(type: "smallint", nullable: false),
+                    Data = table.Column<string>(type: "text", nullable: true),
+                    Favorites = table.Column<string>(type: "text", nullable: true),
+                    Folders = table.Column<string>(type: "text", nullable: true),
+                    Attachments = table.Column<string>(type: "text", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    DeletedDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
+                    Reprompt = table.Column<byte>(type: "smallint", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Cipher", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Cipher_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_Cipher_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Device",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: false),
+                    Name = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    Type = table.Column<byte>(type: "smallint", nullable: false),
+                    Identifier = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    PushToken = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Device", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Device_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "EmergencyAccess",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    GrantorId = table.Column<Guid>(type: "uuid", nullable: false),
+                    GranteeId = table.Column<Guid>(type: "uuid", nullable: true),
+                    Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
+                    KeyEncrypted = table.Column<string>(type: "text", nullable: true),
+                    Type = table.Column<byte>(type: "smallint", nullable: false),
+                    Status = table.Column<byte>(type: "smallint", nullable: false),
+                    WaitTimeDays = table.Column<int>(type: "integer", nullable: false),
+                    RecoveryInitiatedDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
+                    LastNotificationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_EmergencyAccess", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_EmergencyAccess_User_GranteeId",
+                        column: x => x.GranteeId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_EmergencyAccess_User_GrantorId",
+                        column: x => x.GrantorId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Folder",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: false),
+                    Name = table.Column<string>(type: "text", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Folder", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Folder_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "OrganizationUser",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: true),
+                    Email = table.Column<string>(type: "character varying(256)", maxLength: 256, nullable: true),
+                    Key = table.Column<string>(type: "text", nullable: true),
+                    ResetPasswordKey = table.Column<string>(type: "text", nullable: true),
+                    Status = table.Column<byte>(type: "smallint", nullable: false),
+                    Type = table.Column<byte>(type: "smallint", nullable: false),
+                    AccessAll = table.Column<bool>(type: "boolean", nullable: false),
+                    ExternalId = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    Permissions = table.Column<string>(type: "text", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_OrganizationUser", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_OrganizationUser_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_OrganizationUser_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "ProviderUser",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    ProviderId = table.Column<Guid>(type: "uuid", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: true),
+                    Email = table.Column<string>(type: "text", nullable: true),
+                    Key = table.Column<string>(type: "text", nullable: true),
+                    Status = table.Column<byte>(type: "smallint", nullable: false),
+                    Type = table.Column<byte>(type: "smallint", nullable: false),
+                    Permissions = table.Column<string>(type: "text", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_ProviderUser", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_ProviderUser_Provider_ProviderId",
+                        column: x => x.ProviderId,
+                        principalTable: "Provider",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_ProviderUser_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Send",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: true),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: true),
+                    Type = table.Column<byte>(type: "smallint", nullable: false),
+                    Data = table.Column<string>(type: "text", nullable: true),
+                    Key = table.Column<string>(type: "text", nullable: true),
+                    Password = table.Column<string>(type: "character varying(300)", maxLength: 300, nullable: true),
+                    MaxAccessCount = table.Column<int>(type: "integer", nullable: true),
+                    AccessCount = table.Column<int>(type: "integer", nullable: false),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    ExpirationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: true),
+                    DeletionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    Disabled = table.Column<bool>(type: "boolean", nullable: false),
+                    HideEmail = table.Column<bool>(type: "boolean", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Send", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Send_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_Send_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "SsoUser",
+                columns: table => new
+                {
+                    Id = table.Column<long>(type: "bigint", nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: false),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: true),
+                    ExternalId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true, collation: "postgresIndetermanisticCollation"),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_SsoUser", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_SsoUser_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_SsoUser_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "Transaction",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: true),
+                    OrganizationId = table.Column<Guid>(type: "uuid", nullable: true),
+                    Type = table.Column<byte>(type: "smallint", nullable: false),
+                    Amount = table.Column<decimal>(type: "numeric", nullable: false),
+                    Refunded = table.Column<bool>(type: "boolean", nullable: true),
+                    RefundedAmount = table.Column<decimal>(type: "numeric", nullable: true),
+                    Details = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: true),
+                    PaymentMethodType = table.Column<byte>(type: "smallint", nullable: true),
+                    Gateway = table.Column<byte>(type: "smallint", nullable: true),
+                    GatewayId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_Transaction", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_Transaction_Organization_OrganizationId",
+                        column: x => x.OrganizationId,
+                        principalTable: "Organization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                    table.ForeignKey(
+                        name: "FK_Transaction_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "U2f",
+                columns: table => new
+                {
+                    Id = table.Column<int>(type: "integer", nullable: false)
+                        .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: false),
+                    KeyHandle = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
+                    Challenge = table.Column<string>(type: "character varying(200)", maxLength: 200, nullable: true),
+                    AppId = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: true),
+                    Version = table.Column<string>(type: "character varying(20)", maxLength: 20, nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_U2f", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_U2f_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "CollectionGroups",
+                columns: table => new
+                {
+                    CollectionId = table.Column<Guid>(type: "uuid", nullable: false),
+                    GroupId = table.Column<Guid>(type: "uuid", nullable: false),
+                    ReadOnly = table.Column<bool>(type: "boolean", nullable: false),
+                    HidePasswords = table.Column<bool>(type: "boolean", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_CollectionGroups", x => new { x.CollectionId, x.GroupId });
+                    table.ForeignKey(
+                        name: "FK_CollectionGroups_Collection_CollectionId",
+                        column: x => x.CollectionId,
+                        principalTable: "Collection",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_CollectionGroups_Group_GroupId",
+                        column: x => x.GroupId,
+                        principalTable: "Group",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "CollectionCipher",
+                columns: table => new
+                {
+                    CollectionId = table.Column<Guid>(type: "uuid", nullable: false),
+                    CipherId = table.Column<Guid>(type: "uuid", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_CollectionCipher", x => new { x.CollectionId, x.CipherId });
+                    table.ForeignKey(
+                        name: "FK_CollectionCipher_Cipher_CipherId",
+                        column: x => x.CipherId,
+                        principalTable: "Cipher",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_CollectionCipher_Collection_CollectionId",
+                        column: x => x.CollectionId,
+                        principalTable: "Collection",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "CollectionUsers",
+                columns: table => new
+                {
+                    CollectionId = table.Column<Guid>(type: "uuid", nullable: false),
+                    OrganizationUserId = table.Column<Guid>(type: "uuid", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: true),
+                    ReadOnly = table.Column<bool>(type: "boolean", nullable: false),
+                    HidePasswords = table.Column<bool>(type: "boolean", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_CollectionUsers", x => new { x.CollectionId, x.OrganizationUserId });
+                    table.ForeignKey(
+                        name: "FK_CollectionUsers_Collection_CollectionId",
+                        column: x => x.CollectionId,
+                        principalTable: "Collection",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_CollectionUsers_OrganizationUser_OrganizationUserId",
+                        column: x => x.OrganizationUserId,
+                        principalTable: "OrganizationUser",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_CollectionUsers_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "GroupUser",
+                columns: table => new
+                {
+                    GroupId = table.Column<Guid>(type: "uuid", nullable: false),
+                    OrganizationUserId = table.Column<Guid>(type: "uuid", nullable: false),
+                    UserId = table.Column<Guid>(type: "uuid", nullable: true)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_GroupUser", x => new { x.GroupId, x.OrganizationUserId });
+                    table.ForeignKey(
+                        name: "FK_GroupUser_Group_GroupId",
+                        column: x => x.GroupId,
+                        principalTable: "Group",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_GroupUser_OrganizationUser_OrganizationUserId",
+                        column: x => x.OrganizationUserId,
+                        principalTable: "OrganizationUser",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_GroupUser_User_UserId",
+                        column: x => x.UserId,
+                        principalTable: "User",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Restrict);
+                });
+
+            migrationBuilder.CreateTable(
+                name: "ProviderOrganizationProviderUser",
+                columns: table => new
+                {
+                    Id = table.Column<Guid>(type: "uuid", nullable: false),
+                    ProviderOrganizationId = table.Column<Guid>(type: "uuid", nullable: false),
+                    ProviderUserId = table.Column<Guid>(type: "uuid", nullable: false),
+                    Type = table.Column<byte>(type: "smallint", nullable: false),
+                    Permissions = table.Column<string>(type: "text", nullable: true),
+                    CreationDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false),
+                    RevisionDate = table.Column<DateTime>(type: "timestamp without time zone", nullable: false)
+                },
+                constraints: table =>
+                {
+                    table.PrimaryKey("PK_ProviderOrganizationProviderUser", x => x.Id);
+                    table.ForeignKey(
+                        name: "FK_ProviderOrganizationProviderUser_ProviderOrganization_Provi~",
+                        column: x => x.ProviderOrganizationId,
+                        principalTable: "ProviderOrganization",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                    table.ForeignKey(
+                        name: "FK_ProviderOrganizationProviderUser_ProviderUser_ProviderUserId",
+                        column: x => x.ProviderUserId,
+                        principalTable: "ProviderUser",
+                        principalColumn: "Id",
+                        onDelete: ReferentialAction.Cascade);
+                });
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Cipher_OrganizationId",
+                table: "Cipher",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Cipher_UserId",
+                table: "Cipher",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Collection_OrganizationId",
+                table: "Collection",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_CollectionCipher_CipherId",
+                table: "CollectionCipher",
+                column: "CipherId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_CollectionGroups_GroupId",
+                table: "CollectionGroups",
+                column: "GroupId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_CollectionUsers_OrganizationUserId",
+                table: "CollectionUsers",
+                column: "OrganizationUserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_CollectionUsers_UserId",
+                table: "CollectionUsers",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Device_UserId",
+                table: "Device",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_EmergencyAccess_GranteeId",
+                table: "EmergencyAccess",
+                column: "GranteeId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_EmergencyAccess_GrantorId",
+                table: "EmergencyAccess",
+                column: "GrantorId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Folder_UserId",
+                table: "Folder",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Group_OrganizationId",
+                table: "Group",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_GroupUser_OrganizationUserId",
+                table: "GroupUser",
+                column: "OrganizationUserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_GroupUser_UserId",
+                table: "GroupUser",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_OrganizationUser_OrganizationId",
+                table: "OrganizationUser",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_OrganizationUser_UserId",
+                table: "OrganizationUser",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Policy_OrganizationId",
+                table: "Policy",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderOrganization_OrganizationId",
+                table: "ProviderOrganization",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderOrganization_ProviderId",
+                table: "ProviderOrganization",
+                column: "ProviderId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderOrganizationProviderUser_ProviderOrganizationId",
+                table: "ProviderOrganizationProviderUser",
+                column: "ProviderOrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderOrganizationProviderUser_ProviderUserId",
+                table: "ProviderOrganizationProviderUser",
+                column: "ProviderUserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderUser_ProviderId",
+                table: "ProviderUser",
+                column: "ProviderId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_ProviderUser_UserId",
+                table: "ProviderUser",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Send_OrganizationId",
+                table: "Send",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Send_UserId",
+                table: "Send",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_SsoConfig_OrganizationId",
+                table: "SsoConfig",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_SsoUser_OrganizationId",
+                table: "SsoUser",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_SsoUser_UserId",
+                table: "SsoUser",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Transaction_OrganizationId",
+                table: "Transaction",
+                column: "OrganizationId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_Transaction_UserId",
+                table: "Transaction",
+                column: "UserId");
+
+            migrationBuilder.CreateIndex(
+                name: "IX_U2f_UserId",
+                table: "U2f",
+                column: "UserId");
+        }
+
+        protected override void Down(MigrationBuilder migrationBuilder)
+        {
+            migrationBuilder.DropTable(
+                name: "CollectionCipher");
+
+            migrationBuilder.DropTable(
+                name: "CollectionGroups");
+
+            migrationBuilder.DropTable(
+                name: "CollectionUsers");
+
+            migrationBuilder.DropTable(
+                name: "Device");
+
+            migrationBuilder.DropTable(
+                name: "EmergencyAccess");
+
+            migrationBuilder.DropTable(
+                name: "Event");
+
+            migrationBuilder.DropTable(
+                name: "Folder");
+
+            migrationBuilder.DropTable(
+                name: "Grant");
+
+            migrationBuilder.DropTable(
+                name: "GroupUser");
+
+            migrationBuilder.DropTable(
+                name: "Installation");
+
+            migrationBuilder.DropTable(
+                name: "Policy");
+
+            migrationBuilder.DropTable(
+                name: "ProviderOrganizationProviderUser");
+
+            migrationBuilder.DropTable(
+                name: "Send");
+
+            migrationBuilder.DropTable(
+                name: "SsoConfig");
+
+            migrationBuilder.DropTable(
+                name: "SsoUser");
+
+            migrationBuilder.DropTable(
+                name: "TaxRate");
+
+            migrationBuilder.DropTable(
+                name: "Transaction");
+
+            migrationBuilder.DropTable(
+                name: "U2f");
+
+            migrationBuilder.DropTable(
+                name: "Cipher");
+
+            migrationBuilder.DropTable(
+                name: "Collection");
+
+            migrationBuilder.DropTable(
+                name: "Group");
+
+            migrationBuilder.DropTable(
+                name: "OrganizationUser");
+
+            migrationBuilder.DropTable(
+                name: "ProviderOrganization");
+
+            migrationBuilder.DropTable(
+                name: "ProviderUser");
+
+            migrationBuilder.DropTable(
+                name: "Organization");
+
+            migrationBuilder.DropTable(
+                name: "Provider");
+
+            migrationBuilder.DropTable(
+                name: "User");
+        }
+    }
+}
diff --git a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs
new file mode 100644
index 0000000000..74399182ab
--- /dev/null
+++ b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs
@@ -0,0 +1,1520 @@
+// <auto-generated />
+using System;
+using Bit.Core.Repositories.EntityFramework;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+
+namespace Bit.EntityFrameworkMigrations.Migrations
+{
+    [DbContext(typeof(DatabaseContext))]
+    partial class DatabaseContextModelSnapshot : ModelSnapshot
+    {
+        protected override void BuildModel(ModelBuilder modelBuilder)
+        {
+#pragma warning disable 612, 618
+            modelBuilder
+                .HasAnnotation("Relational:MaxIdentifierLength", 64)
+                .HasAnnotation("ProductVersion", "5.0.5");
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Attachments")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime?>("DeletedDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Favorites")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Folders")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<byte?>("Reprompt")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Cipher");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Collection");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionCipher", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("CipherId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("CollectionId", "CipherId");
+
+                    b.HasIndex("CipherId");
+
+                    b.ToTable("CollectionCipher");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionGroup", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("GroupId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("HidePasswords")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("ReadOnly")
+                        .HasColumnType("tinyint(1)");
+
+                    b.HasKey("CollectionId", "GroupId");
+
+                    b.HasIndex("GroupId");
+
+                    b.ToTable("CollectionGroups");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionUser", b =>
+                {
+                    b.Property<Guid>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("OrganizationUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("HidePasswords")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("ReadOnly")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("CollectionId", "OrganizationUserId");
+
+                    b.HasIndex("OrganizationUserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Device", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Identifier")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("PushToken")
+                        .HasMaxLength(255)
+                        .HasColumnType("varchar(255)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Device");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.EmergencyAccess", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<Guid?>("GranteeId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("GrantorId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("KeyEncrypted")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime?>("LastNotificationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime?>("RecoveryInitiatedDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<int>("WaitTimeDays")
+                        .HasColumnType("int");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("GranteeId");
+
+                    b.HasIndex("GrantorId");
+
+                    b.ToTable("EmergencyAccess");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Event", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("ActingUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("CipherId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("CollectionId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("Date")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte?>("DeviceType")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("GroupId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("IpAddress")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("OrganizationUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("PolicyId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<int>("Type")
+                        .HasColumnType("int");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Event");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Folder", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Folder");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Grant", b =>
+                {
+                    b.Property<string>("Key")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<string>("ClientId")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<DateTime?>("ConsumedDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Description")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("SessionId")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<string>("SubjectId")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<string>("Type")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.HasKey("Key");
+
+                    b.ToTable("Grant");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("AccessAll")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Group");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.GroupUser", b =>
+                {
+                    b.Property<Guid>("GroupId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("OrganizationUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("GroupId", "OrganizationUserId");
+
+                    b.HasIndex("OrganizationUserId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("GroupUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Installation", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Key")
+                        .HasMaxLength(150)
+                        .HasColumnType("varchar(150)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Installation");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Organization", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("ApiKey")
+                        .HasMaxLength(30)
+                        .HasColumnType("varchar(30)");
+
+                    b.Property<string>("BillingEmail")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<string>("BusinessAddress1")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessAddress2")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessAddress3")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessCountry")
+                        .HasMaxLength(2)
+                        .HasColumnType("varchar(2)");
+
+                    b.Property<string>("BusinessName")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("BusinessTaxNumber")
+                        .HasMaxLength(30)
+                        .HasColumnType("varchar(30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("GatewayCustomerId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("GatewaySubscriptionId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Identifier")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("LicenseKey")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<short?>("MaxCollections")
+                        .HasColumnType("smallint");
+
+                    b.Property<short?>("MaxStorageGb")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Plan")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<byte>("PlanType")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("PrivateKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("PublicKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ReferenceData")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<int?>("Seats")
+                        .HasColumnType("int");
+
+                    b.Property<bool>("SelfHost")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<long?>("Storage")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("TwoFactorProviders")
+                        .HasColumnType("longtext");
+
+                    b.Property<bool>("Use2fa")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseApi")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseDirectory")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseEvents")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseGroups")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UsePolicies")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseResetPassword")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseSso")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UseTotp")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<bool>("UsersGetPremium")
+                        .HasColumnType("tinyint(1)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<bool>("AccessAll")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ResetPasswordKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Policy", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("Policy");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.Provider", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("BillingEmail")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessAddress1")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessAddress2")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessAddress3")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessCountry")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessName")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("BusinessTaxNumber")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Name")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("Provider");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("ProviderId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Settings")
+                        .HasColumnType("longtext");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("ProviderId");
+
+                    b.ToTable("ProviderOrganization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganizationProviderUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("ProviderOrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("ProviderUserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProviderOrganizationId");
+
+                    b.HasIndex("ProviderUserId");
+
+                    b.ToTable("ProviderOrganizationProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderUser", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Email")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("Permissions")
+                        .HasColumnType("longtext");
+
+                    b.Property<Guid>("ProviderId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Status")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("ProviderId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("ProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Send", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<int>("AccessCount")
+                        .HasColumnType("int");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime>("DeletionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool>("Disabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime?>("ExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<bool?>("HideEmail")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<int?>("MaxAccessCount")
+                        .HasColumnType("int");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Password")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Send");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoConfig", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Data")
+                        .HasColumnType("longtext");
+
+                    b.Property<bool>("Enabled")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<Guid>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.ToTable("SsoConfig");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoUser", b =>
+                {
+                    b.Property<long>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("bigint");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ExternalId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("SsoUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.TaxRate", b =>
+                {
+                    b.Property<string>("Id")
+                        .HasMaxLength(40)
+                        .HasColumnType("varchar(40)");
+
+                    b.Property<bool>("Active")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("Country")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("PostalCode")
+                        .HasMaxLength(10)
+                        .HasColumnType("varchar(10)");
+
+                    b.Property<decimal>("Rate")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<string>("State")
+                        .HasMaxLength(2)
+                        .HasColumnType("varchar(2)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("TaxRate");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Transaction", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<decimal>("Amount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Details")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("GatewayId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<Guid?>("OrganizationId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<byte?>("PaymentMethodType")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<bool?>("Refunded")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<decimal?>("RefundedAmount")
+                        .HasColumnType("decimal(65,30)");
+
+                    b.Property<byte>("Type")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<Guid?>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("OrganizationId");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("Transaction");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.U2f", b =>
+                {
+                    b.Property<int>("Id")
+                        .ValueGeneratedOnAdd()
+                        .HasColumnType("int");
+
+                    b.Property<string>("AppId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("Challenge")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("KeyHandle")
+                        .HasMaxLength(200)
+                        .HasColumnType("varchar(200)");
+
+                    b.Property<Guid>("UserId")
+                        .HasColumnType("char(36)");
+
+                    b.Property<string>("Version")
+                        .HasMaxLength(20)
+                        .HasColumnType("varchar(20)");
+
+                    b.HasKey("Id");
+
+                    b.HasIndex("UserId");
+
+                    b.ToTable("U2f");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.User", b =>
+                {
+                    b.Property<Guid>("Id")
+                        .HasColumnType("char(36)");
+
+                    b.Property<DateTime>("AccountRevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("ApiKey")
+                        .IsRequired()
+                        .HasMaxLength(30)
+                        .HasColumnType("varchar(30)");
+
+                    b.Property<DateTime>("CreationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("Culture")
+                        .HasMaxLength(10)
+                        .HasColumnType("varchar(10)");
+
+                    b.Property<string>("Email")
+                        .IsRequired()
+                        .HasMaxLength(256)
+                        .HasColumnType("varchar(256)");
+
+                    b.Property<bool>("EmailVerified")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<string>("EquivalentDomains")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ExcludedGlobalEquivalentDomains")
+                        .HasColumnType("longtext");
+
+                    b.Property<byte?>("Gateway")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<string>("GatewayCustomerId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<string>("GatewaySubscriptionId")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<byte>("Kdf")
+                        .HasColumnType("tinyint unsigned");
+
+                    b.Property<int>("KdfIterations")
+                        .HasColumnType("int");
+
+                    b.Property<string>("Key")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("LicenseKey")
+                        .HasMaxLength(100)
+                        .HasColumnType("varchar(100)");
+
+                    b.Property<string>("MasterPassword")
+                        .HasMaxLength(300)
+                        .HasColumnType("varchar(300)");
+
+                    b.Property<string>("MasterPasswordHint")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<short?>("MaxStorageGb")
+                        .HasColumnType("smallint");
+
+                    b.Property<string>("Name")
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<bool>("Premium")
+                        .HasColumnType("tinyint(1)");
+
+                    b.Property<DateTime?>("PremiumExpirationDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("PrivateKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("PublicKey")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("ReferenceData")
+                        .HasColumnType("longtext");
+
+                    b.Property<DateTime?>("RenewalReminderDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<DateTime>("RevisionDate")
+                        .HasColumnType("datetime(6)");
+
+                    b.Property<string>("SecurityStamp")
+                        .IsRequired()
+                        .HasMaxLength(50)
+                        .HasColumnType("varchar(50)");
+
+                    b.Property<long?>("Storage")
+                        .HasColumnType("bigint");
+
+                    b.Property<string>("TwoFactorProviders")
+                        .HasColumnType("longtext");
+
+                    b.Property<string>("TwoFactorRecoveryCode")
+                        .HasMaxLength(32)
+                        .HasColumnType("varchar(32)");
+
+                    b.HasKey("Id");
+
+                    b.ToTable("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Ciphers")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Ciphers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionCipher", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Cipher", "Cipher")
+                        .WithMany("CollectionCiphers")
+                        .HasForeignKey("CipherId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionCiphers")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Cipher");
+
+                    b.Navigation("Collection");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionGroup", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionGroups")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Group", "Group")
+                        .WithMany()
+                        .HasForeignKey("GroupId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Collection");
+
+                    b.Navigation("Group");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.CollectionUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Collection", "Collection")
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("CollectionId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.OrganizationUser", "OrganizationUser")
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("OrganizationUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", null)
+                        .WithMany("CollectionUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Collection");
+
+                    b.Navigation("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Device", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.EmergencyAccess", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "Grantee")
+                        .WithMany()
+                        .HasForeignKey("GranteeId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "Grantor")
+                        .WithMany()
+                        .HasForeignKey("GrantorId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Grantee");
+
+                    b.Navigation("Grantor");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Folder", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Folders")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Groups")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.GroupUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Group", "Group")
+                        .WithMany("GroupUsers")
+                        .HasForeignKey("GroupId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.OrganizationUser", "OrganizationUser")
+                        .WithMany()
+                        .HasForeignKey("OrganizationUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", null)
+                        .WithMany("GroupUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Group");
+
+                    b.Navigation("OrganizationUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("OrganizationUsers")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("OrganizationUsers")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Policy", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Policies")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.Provider", "Provider")
+                        .WithMany()
+                        .HasForeignKey("ProviderId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("Provider");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderOrganizationProviderUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.ProviderOrganization", "ProviderOrganization")
+                        .WithMany()
+                        .HasForeignKey("ProviderOrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.ProviderUser", "ProviderUser")
+                        .WithMany()
+                        .HasForeignKey("ProviderUserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("ProviderOrganization");
+
+                    b.Navigation("ProviderUser");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Provider.ProviderUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Provider.Provider", "Provider")
+                        .WithMany()
+                        .HasForeignKey("ProviderId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Provider");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Send", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany()
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany()
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoConfig", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("SsoConfigs")
+                        .HasForeignKey("OrganizationId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.SsoUser", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("SsoUsers")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("SsoUsers")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Transaction", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.Organization", "Organization")
+                        .WithMany("Transactions")
+                        .HasForeignKey("OrganizationId");
+
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("Transactions")
+                        .HasForeignKey("UserId");
+
+                    b.Navigation("Organization");
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.U2f", b =>
+                {
+                    b.HasOne("Bit.Core.Models.EntityFramework.User", "User")
+                        .WithMany("U2fs")
+                        .HasForeignKey("UserId")
+                        .OnDelete(DeleteBehavior.Cascade)
+                        .IsRequired();
+
+                    b.Navigation("User");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Cipher", b =>
+                {
+                    b.Navigation("CollectionCiphers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Collection", b =>
+                {
+                    b.Navigation("CollectionCiphers");
+
+                    b.Navigation("CollectionGroups");
+
+                    b.Navigation("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Group", b =>
+                {
+                    b.Navigation("GroupUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.Organization", b =>
+                {
+                    b.Navigation("Ciphers");
+
+                    b.Navigation("Groups");
+
+                    b.Navigation("OrganizationUsers");
+
+                    b.Navigation("Policies");
+
+                    b.Navigation("SsoConfigs");
+
+                    b.Navigation("SsoUsers");
+
+                    b.Navigation("Transactions");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.OrganizationUser", b =>
+                {
+                    b.Navigation("CollectionUsers");
+                });
+
+            modelBuilder.Entity("Bit.Core.Models.EntityFramework.User", b =>
+                {
+                    b.Navigation("Ciphers");
+
+                    b.Navigation("CollectionUsers");
+
+                    b.Navigation("Folders");
+
+                    b.Navigation("GroupUsers");
+
+                    b.Navigation("OrganizationUsers");
+
+                    b.Navigation("SsoUsers");
+
+                    b.Navigation("Transactions");
+
+                    b.Navigation("U2fs");
+                });
+#pragma warning restore 612, 618
+        }
+    }
+}
diff --git a/util/PostgresMigrations/PostgresMigrations.csproj b/util/PostgresMigrations/PostgresMigrations.csproj
new file mode 100644
index 0000000000..d07adb1dc6
--- /dev/null
+++ b/util/PostgresMigrations/PostgresMigrations.csproj
@@ -0,0 +1,19 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net5.0</TargetFramework>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\src\Core\Core.csproj" />
+    <ProjectReference Include="..\..\src\Api\Api.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.5">
+      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+      <PrivateAssets>all</PrivateAssets>
+    </PackageReference>
+  </ItemGroup>
+
+</Project>
diff --git a/util/PostgresMigrations/Scripts/Init.psql b/util/PostgresMigrations/Scripts/Init.psql
new file mode 100644
index 0000000000..4ad6012448
--- /dev/null
+++ b/util/PostgresMigrations/Scripts/Init.psql
@@ -0,0 +1,494 @@
+CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
+    "MigrationId" character varying(150) NOT NULL,
+    "ProductVersion" character varying(32) NOT NULL,
+    CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
+);
+
+START TRANSACTION;
+
+CREATE COLLATION "postgresIndetermanisticCollation" (LC_COLLATE = 'en-u-ks-primary',
+    LC_CTYPE = 'en-u-ks-primary',
+    PROVIDER = icu,
+    DETERMINISTIC = False
+);
+
+CREATE TABLE "Event" (
+    "Id" uuid NOT NULL,
+    "Date" timestamp without time zone NOT NULL,
+    "Type" integer NOT NULL,
+    "UserId" uuid NULL,
+    "OrganizationId" uuid NULL,
+    "CipherId" uuid NULL,
+    "CollectionId" uuid NULL,
+    "PolicyId" uuid NULL,
+    "GroupId" uuid NULL,
+    "OrganizationUserId" uuid NULL,
+    "DeviceType" smallint NULL,
+    "IpAddress" character varying(50) NULL,
+    "ActingUserId" uuid NULL,
+    CONSTRAINT "PK_Event" PRIMARY KEY ("Id")
+);
+
+CREATE TABLE "Grant" (
+    "Key" character varying(200) NOT NULL,
+    "Type" character varying(50) NULL,
+    "SubjectId" character varying(200) NULL,
+    "SessionId" character varying(100) NULL,
+    "ClientId" character varying(200) NULL,
+    "Description" character varying(200) NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "ExpirationDate" timestamp without time zone NULL,
+    "ConsumedDate" timestamp without time zone NULL,
+    "Data" text NULL,
+    CONSTRAINT "PK_Grant" PRIMARY KEY ("Key")
+);
+
+CREATE TABLE "Installation" (
+    "Id" uuid NOT NULL,
+    "Email" character varying(256) NULL,
+    "Key" character varying(150) NULL,
+    "Enabled" boolean NOT NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_Installation" PRIMARY KEY ("Id")
+);
+
+CREATE TABLE "Organization" (
+    "Id" uuid NOT NULL,
+    "Identifier" character varying(50) COLLATE "postgresIndetermanisticCollation" NULL,
+    "Name" character varying(50) NULL,
+    "BusinessName" character varying(50) NULL,
+    "BusinessAddress1" character varying(50) NULL,
+    "BusinessAddress2" character varying(50) NULL,
+    "BusinessAddress3" character varying(50) NULL,
+    "BusinessCountry" character varying(2) NULL,
+    "BusinessTaxNumber" character varying(30) NULL,
+    "BillingEmail" character varying(256) NULL,
+    "Plan" character varying(50) NULL,
+    "PlanType" smallint NOT NULL,
+    "Seats" integer NULL,
+    "MaxCollections" smallint NULL,
+    "UsePolicies" boolean NOT NULL,
+    "UseSso" boolean NOT NULL,
+    "UseGroups" boolean NOT NULL,
+    "UseDirectory" boolean NOT NULL,
+    "UseEvents" boolean NOT NULL,
+    "UseTotp" boolean NOT NULL,
+    "Use2fa" boolean NOT NULL,
+    "UseApi" boolean NOT NULL,
+    "UseResetPassword" boolean NOT NULL,
+    "SelfHost" boolean NOT NULL,
+    "UsersGetPremium" boolean NOT NULL,
+    "Storage" bigint NULL,
+    "MaxStorageGb" smallint NULL,
+    "Gateway" smallint NULL,
+    "GatewayCustomerId" character varying(50) NULL,
+    "GatewaySubscriptionId" character varying(50) NULL,
+    "ReferenceData" text NULL,
+    "Enabled" boolean NOT NULL,
+    "LicenseKey" character varying(100) NULL,
+    "ApiKey" character varying(30) NULL,
+    "PublicKey" text NULL,
+    "PrivateKey" text NULL,
+    "TwoFactorProviders" text NULL,
+    "ExpirationDate" timestamp without time zone NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_Organization" PRIMARY KEY ("Id")
+);
+
+CREATE TABLE "Provider" (
+    "Id" uuid NOT NULL,
+    "Name" text NULL,
+    "BusinessName" text NULL,
+    "BusinessAddress1" text NULL,
+    "BusinessAddress2" text NULL,
+    "BusinessAddress3" text NULL,
+    "BusinessCountry" text NULL,
+    "BusinessTaxNumber" text NULL,
+    "BillingEmail" text NULL,
+    "Status" smallint NOT NULL,
+    "Enabled" boolean NOT NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_Provider" PRIMARY KEY ("Id")
+);
+
+CREATE TABLE "TaxRate" (
+    "Id" character varying(40) NOT NULL,
+    "Country" character varying(50) NULL,
+    "State" character varying(2) NULL,
+    "PostalCode" character varying(10) NULL,
+    "Rate" numeric NOT NULL,
+    "Active" boolean NOT NULL,
+    CONSTRAINT "PK_TaxRate" PRIMARY KEY ("Id")
+);
+
+CREATE TABLE "User" (
+    "Id" uuid NOT NULL,
+    "Name" character varying(50) NULL,
+    "Email" character varying(256) COLLATE "postgresIndetermanisticCollation" NOT NULL,
+    "EmailVerified" boolean NOT NULL,
+    "MasterPassword" character varying(300) NULL,
+    "MasterPasswordHint" character varying(50) NULL,
+    "Culture" character varying(10) NULL,
+    "SecurityStamp" character varying(50) NOT NULL,
+    "TwoFactorProviders" text NULL,
+    "TwoFactorRecoveryCode" character varying(32) NULL,
+    "EquivalentDomains" text NULL,
+    "ExcludedGlobalEquivalentDomains" text NULL,
+    "AccountRevisionDate" timestamp without time zone NOT NULL,
+    "Key" text NULL,
+    "PublicKey" text NULL,
+    "PrivateKey" text NULL,
+    "Premium" boolean NOT NULL,
+    "PremiumExpirationDate" timestamp without time zone NULL,
+    "RenewalReminderDate" timestamp without time zone NULL,
+    "Storage" bigint NULL,
+    "MaxStorageGb" smallint NULL,
+    "Gateway" smallint NULL,
+    "GatewayCustomerId" character varying(50) NULL,
+    "GatewaySubscriptionId" character varying(50) NULL,
+    "ReferenceData" text NULL,
+    "LicenseKey" character varying(100) NULL,
+    "ApiKey" character varying(30) NOT NULL,
+    "Kdf" smallint NOT NULL,
+    "KdfIterations" integer NOT NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_User" PRIMARY KEY ("Id")
+);
+
+CREATE TABLE "Collection" (
+    "Id" uuid NOT NULL,
+    "OrganizationId" uuid NOT NULL,
+    "Name" text NULL,
+    "ExternalId" character varying(300) NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_Collection" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_Collection_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "Group" (
+    "Id" uuid NOT NULL,
+    "OrganizationId" uuid NOT NULL,
+    "Name" character varying(100) NULL,
+    "AccessAll" boolean NOT NULL,
+    "ExternalId" character varying(300) NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_Group" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_Group_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "Policy" (
+    "Id" uuid NOT NULL,
+    "OrganizationId" uuid NOT NULL,
+    "Type" smallint NOT NULL,
+    "Data" text NULL,
+    "Enabled" boolean NOT NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_Policy" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_Policy_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "SsoConfig" (
+    "Id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "Enabled" boolean NOT NULL,
+    "OrganizationId" uuid NOT NULL,
+    "Data" text NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_SsoConfig" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_SsoConfig_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "ProviderOrganization" (
+    "Id" uuid NOT NULL,
+    "ProviderId" uuid NOT NULL,
+    "OrganizationId" uuid NOT NULL,
+    "Key" text NULL,
+    "Settings" text NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_ProviderOrganization" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_ProviderOrganization_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_ProviderOrganization_Provider_ProviderId" FOREIGN KEY ("ProviderId") REFERENCES "Provider" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "Cipher" (
+    "Id" uuid NOT NULL,
+    "UserId" uuid NULL,
+    "OrganizationId" uuid NULL,
+    "Type" smallint NOT NULL,
+    "Data" text NULL,
+    "Favorites" text NULL,
+    "Folders" text NULL,
+    "Attachments" text NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    "DeletedDate" timestamp without time zone NULL,
+    "Reprompt" smallint NULL,
+    CONSTRAINT "PK_Cipher" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_Cipher_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE RESTRICT,
+    CONSTRAINT "FK_Cipher_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE RESTRICT
+);
+
+CREATE TABLE "Device" (
+    "Id" uuid NOT NULL,
+    "UserId" uuid NOT NULL,
+    "Name" character varying(50) NULL,
+    "Type" smallint NOT NULL,
+    "Identifier" character varying(50) NULL,
+    "PushToken" character varying(255) NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_Device" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_Device_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "EmergencyAccess" (
+    "Id" uuid NOT NULL,
+    "GrantorId" uuid NOT NULL,
+    "GranteeId" uuid NULL,
+    "Email" character varying(256) NULL,
+    "KeyEncrypted" text NULL,
+    "Type" smallint NOT NULL,
+    "Status" smallint NOT NULL,
+    "WaitTimeDays" integer NOT NULL,
+    "RecoveryInitiatedDate" timestamp without time zone NULL,
+    "LastNotificationDate" timestamp without time zone NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_EmergencyAccess" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_EmergencyAccess_User_GranteeId" FOREIGN KEY ("GranteeId") REFERENCES "User" ("Id") ON DELETE RESTRICT,
+    CONSTRAINT "FK_EmergencyAccess_User_GrantorId" FOREIGN KEY ("GrantorId") REFERENCES "User" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "Folder" (
+    "Id" uuid NOT NULL,
+    "UserId" uuid NOT NULL,
+    "Name" text NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_Folder" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_Folder_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "OrganizationUser" (
+    "Id" uuid NOT NULL,
+    "OrganizationId" uuid NOT NULL,
+    "UserId" uuid NULL,
+    "Email" character varying(256) NULL,
+    "Key" text NULL,
+    "ResetPasswordKey" text NULL,
+    "Status" smallint NOT NULL,
+    "Type" smallint NOT NULL,
+    "AccessAll" boolean NOT NULL,
+    "ExternalId" character varying(300) NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    "Permissions" text NULL,
+    CONSTRAINT "PK_OrganizationUser" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_OrganizationUser_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_OrganizationUser_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE RESTRICT
+);
+
+CREATE TABLE "ProviderUser" (
+    "Id" uuid NOT NULL,
+    "ProviderId" uuid NOT NULL,
+    "UserId" uuid NULL,
+    "Email" text NULL,
+    "Key" text NULL,
+    "Status" smallint NOT NULL,
+    "Type" smallint NOT NULL,
+    "Permissions" text NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_ProviderUser" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_ProviderUser_Provider_ProviderId" FOREIGN KEY ("ProviderId") REFERENCES "Provider" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_ProviderUser_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE RESTRICT
+);
+
+CREATE TABLE "Send" (
+    "Id" uuid NOT NULL,
+    "UserId" uuid NULL,
+    "OrganizationId" uuid NULL,
+    "Type" smallint NOT NULL,
+    "Data" text NULL,
+    "Key" text NULL,
+    "Password" character varying(300) NULL,
+    "MaxAccessCount" integer NULL,
+    "AccessCount" integer NOT NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    "ExpirationDate" timestamp without time zone NULL,
+    "DeletionDate" timestamp without time zone NOT NULL,
+    "Disabled" boolean NOT NULL,
+    "HideEmail" boolean NULL,
+    CONSTRAINT "PK_Send" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_Send_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE RESTRICT,
+    CONSTRAINT "FK_Send_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE RESTRICT
+);
+
+CREATE TABLE "SsoUser" (
+    "Id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "UserId" uuid NOT NULL,
+    "OrganizationId" uuid NULL,
+    "ExternalId" character varying(50) COLLATE "postgresIndetermanisticCollation" NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_SsoUser" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_SsoUser_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE RESTRICT,
+    CONSTRAINT "FK_SsoUser_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "Transaction" (
+    "Id" uuid NOT NULL,
+    "UserId" uuid NULL,
+    "OrganizationId" uuid NULL,
+    "Type" smallint NOT NULL,
+    "Amount" numeric NOT NULL,
+    "Refunded" boolean NULL,
+    "RefundedAmount" numeric NULL,
+    "Details" character varying(100) NULL,
+    "PaymentMethodType" smallint NULL,
+    "Gateway" smallint NULL,
+    "GatewayId" character varying(50) NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_Transaction" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_Transaction_Organization_OrganizationId" FOREIGN KEY ("OrganizationId") REFERENCES "Organization" ("Id") ON DELETE RESTRICT,
+    CONSTRAINT "FK_Transaction_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE RESTRICT
+);
+
+CREATE TABLE "U2f" (
+    "Id" integer NOT NULL GENERATED BY DEFAULT AS IDENTITY,
+    "UserId" uuid NOT NULL,
+    "KeyHandle" character varying(200) NULL,
+    "Challenge" character varying(200) NULL,
+    "AppId" character varying(50) NULL,
+    "Version" character varying(20) NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_U2f" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_U2f_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "CollectionGroups" (
+    "CollectionId" uuid NOT NULL,
+    "GroupId" uuid NOT NULL,
+    "ReadOnly" boolean NOT NULL,
+    "HidePasswords" boolean NOT NULL,
+    CONSTRAINT "PK_CollectionGroups" PRIMARY KEY ("CollectionId", "GroupId"),
+    CONSTRAINT "FK_CollectionGroups_Collection_CollectionId" FOREIGN KEY ("CollectionId") REFERENCES "Collection" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_CollectionGroups_Group_GroupId" FOREIGN KEY ("GroupId") REFERENCES "Group" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "CollectionCipher" (
+    "CollectionId" uuid NOT NULL,
+    "CipherId" uuid NOT NULL,
+    CONSTRAINT "PK_CollectionCipher" PRIMARY KEY ("CollectionId", "CipherId"),
+    CONSTRAINT "FK_CollectionCipher_Cipher_CipherId" FOREIGN KEY ("CipherId") REFERENCES "Cipher" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_CollectionCipher_Collection_CollectionId" FOREIGN KEY ("CollectionId") REFERENCES "Collection" ("Id") ON DELETE CASCADE
+);
+
+CREATE TABLE "CollectionUsers" (
+    "CollectionId" uuid NOT NULL,
+    "OrganizationUserId" uuid NOT NULL,
+    "UserId" uuid NULL,
+    "ReadOnly" boolean NOT NULL,
+    "HidePasswords" boolean NOT NULL,
+    CONSTRAINT "PK_CollectionUsers" PRIMARY KEY ("CollectionId", "OrganizationUserId"),
+    CONSTRAINT "FK_CollectionUsers_Collection_CollectionId" FOREIGN KEY ("CollectionId") REFERENCES "Collection" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_CollectionUsers_OrganizationUser_OrganizationUserId" FOREIGN KEY ("OrganizationUserId") REFERENCES "OrganizationUser" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_CollectionUsers_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE RESTRICT
+);
+
+CREATE TABLE "GroupUser" (
+    "GroupId" uuid NOT NULL,
+    "OrganizationUserId" uuid NOT NULL,
+    "UserId" uuid NULL,
+    CONSTRAINT "PK_GroupUser" PRIMARY KEY ("GroupId", "OrganizationUserId"),
+    CONSTRAINT "FK_GroupUser_Group_GroupId" FOREIGN KEY ("GroupId") REFERENCES "Group" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_GroupUser_OrganizationUser_OrganizationUserId" FOREIGN KEY ("OrganizationUserId") REFERENCES "OrganizationUser" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_GroupUser_User_UserId" FOREIGN KEY ("UserId") REFERENCES "User" ("Id") ON DELETE RESTRICT
+);
+
+CREATE TABLE "ProviderOrganizationProviderUser" (
+    "Id" uuid NOT NULL,
+    "ProviderOrganizationId" uuid NOT NULL,
+    "ProviderUserId" uuid NOT NULL,
+    "Type" smallint NOT NULL,
+    "Permissions" text NULL,
+    "CreationDate" timestamp without time zone NOT NULL,
+    "RevisionDate" timestamp without time zone NOT NULL,
+    CONSTRAINT "PK_ProviderOrganizationProviderUser" PRIMARY KEY ("Id"),
+    CONSTRAINT "FK_ProviderOrganizationProviderUser_ProviderOrganization_Provi~" FOREIGN KEY ("ProviderOrganizationId") REFERENCES "ProviderOrganization" ("Id") ON DELETE CASCADE,
+    CONSTRAINT "FK_ProviderOrganizationProviderUser_ProviderUser_ProviderUserId" FOREIGN KEY ("ProviderUserId") REFERENCES "ProviderUser" ("Id") ON DELETE CASCADE
+);
+
+CREATE INDEX "IX_Cipher_OrganizationId" ON "Cipher" ("OrganizationId");
+
+CREATE INDEX "IX_Cipher_UserId" ON "Cipher" ("UserId");
+
+CREATE INDEX "IX_Collection_OrganizationId" ON "Collection" ("OrganizationId");
+
+CREATE INDEX "IX_CollectionCipher_CipherId" ON "CollectionCipher" ("CipherId");
+
+CREATE INDEX "IX_CollectionGroups_GroupId" ON "CollectionGroups" ("GroupId");
+
+CREATE INDEX "IX_CollectionUsers_OrganizationUserId" ON "CollectionUsers" ("OrganizationUserId");
+
+CREATE INDEX "IX_CollectionUsers_UserId" ON "CollectionUsers" ("UserId");
+
+CREATE INDEX "IX_Device_UserId" ON "Device" ("UserId");
+
+CREATE INDEX "IX_EmergencyAccess_GranteeId" ON "EmergencyAccess" ("GranteeId");
+
+CREATE INDEX "IX_EmergencyAccess_GrantorId" ON "EmergencyAccess" ("GrantorId");
+
+CREATE INDEX "IX_Folder_UserId" ON "Folder" ("UserId");
+
+CREATE INDEX "IX_Group_OrganizationId" ON "Group" ("OrganizationId");
+
+CREATE INDEX "IX_GroupUser_OrganizationUserId" ON "GroupUser" ("OrganizationUserId");
+
+CREATE INDEX "IX_GroupUser_UserId" ON "GroupUser" ("UserId");
+
+CREATE INDEX "IX_OrganizationUser_OrganizationId" ON "OrganizationUser" ("OrganizationId");
+
+CREATE INDEX "IX_OrganizationUser_UserId" ON "OrganizationUser" ("UserId");
+
+CREATE INDEX "IX_Policy_OrganizationId" ON "Policy" ("OrganizationId");
+
+CREATE INDEX "IX_ProviderOrganization_OrganizationId" ON "ProviderOrganization" ("OrganizationId");
+
+CREATE INDEX "IX_ProviderOrganization_ProviderId" ON "ProviderOrganization" ("ProviderId");
+
+CREATE INDEX "IX_ProviderOrganizationProviderUser_ProviderOrganizationId" ON "ProviderOrganizationProviderUser" ("ProviderOrganizationId");
+
+CREATE INDEX "IX_ProviderOrganizationProviderUser_ProviderUserId" ON "ProviderOrganizationProviderUser" ("ProviderUserId");
+
+CREATE INDEX "IX_ProviderUser_ProviderId" ON "ProviderUser" ("ProviderId");
+
+CREATE INDEX "IX_ProviderUser_UserId" ON "ProviderUser" ("UserId");
+
+CREATE INDEX "IX_Send_OrganizationId" ON "Send" ("OrganizationId");
+
+CREATE INDEX "IX_Send_UserId" ON "Send" ("UserId");
+
+CREATE INDEX "IX_SsoConfig_OrganizationId" ON "SsoConfig" ("OrganizationId");
+
+CREATE INDEX "IX_SsoUser_OrganizationId" ON "SsoUser" ("OrganizationId");
+
+CREATE INDEX "IX_SsoUser_UserId" ON "SsoUser" ("UserId");
+
+CREATE INDEX "IX_Transaction_OrganizationId" ON "Transaction" ("OrganizationId");
+
+CREATE INDEX "IX_Transaction_UserId" ON "Transaction" ("UserId");
+
+CREATE INDEX "IX_U2f_UserId" ON "U2f" ("UserId");
+
+INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
+VALUES ('20210617163014_Postgres_Init', '5.0.5');
+
+COMMIT;
\ No newline at end of file
diff --git a/util/Server/Dockerfile b/util/Server/Dockerfile
index 69de097f43..114deb18c7 100644
--- a/util/Server/Dockerfile
+++ b/util/Server/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden"
 
diff --git a/util/Setup/Dockerfile b/util/Setup/Dockerfile
index f63e4ed8cc..cbf000747a 100644
--- a/util/Setup/Dockerfile
+++ b/util/Setup/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/core/aspnet:3.1
+FROM mcr.microsoft.com/dotnet/aspnet:5.0
 
 LABEL com.bitwarden.product="bitwarden" com.bitwarden.project="setup"
 
diff --git a/util/Setup/Setup.csproj b/util/Setup/Setup.csproj
index daa6754460..744242e60e 100644
--- a/util/Setup/Setup.csproj
+++ b/util/Setup/Setup.csproj
@@ -11,7 +11,7 @@
 
   <ItemGroup>
     <PackageReference Include="Handlebars.Net" Version="1.10.1" />
-    <PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.6" />
+    <PackageReference Include="Microsoft.Extensions.Logging" Version="5.0.0" />
     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
     <PackageReference Include="YamlDotNet" Version="8.1.2" />
   </ItemGroup>