From b070e9a387deda9a94d0517c3c1156fb5e684db7 Mon Sep 17 00:00:00 2001 From: Federico Maccaroni Date: Mon, 6 Jun 2022 14:52:50 -0300 Subject: [PATCH] [PS-589] Fix emergency contact takeover device verification and endpoints for its settings (#2016) * Added UnknownDeviceVerificationEnabled on User that is turned off when emergency contact takes over the account. Also added endpoints to get and update 2fa device verification settings. And Updated migrations & tests * Applied dotnet format * Fixed method rename call on TwoFactorController * PS-589 Format fixes * PS-589 changed UnknownDeviceVerificationEnabled to be non-nullable --- src/Api/Controllers/TwoFactorController.cs | 36 + .../Request/DeviceVerificationRequestModel.cs | 18 + .../DeviceVerificationResponseModel.cs | 18 + src/Core/Entities/User.cs | 1 + src/Core/Services/IUserService.cs | 1 + .../Implementations/EmergencyAccessService.cs | 1 + .../Services/Implementations/UserService.cs | 12 +- src/Core/Utilities/ClaimsExtensions.cs | 15 + src/Sql/dbo/Stored Procedures/User_Create.sql | 9 +- src/Sql/dbo/Stored Procedures/User_Update.sql | 6 +- src/Sql/dbo/Tables/User.sql | 1 + .../Services/EmergencyAccessServiceTests.cs | 35 + test/Core.Test/Services/UserServiceTests.cs | 97 +- .../Utilities/ClaimsExtensionsTests.cs | 39 + ...022-05-24_00_DeviceUnknownVerification.sql | 245 +++ ...1600_DeviceUnknownVerification.Designer.cs | 1591 ++++++++++++++++ ...0220524171600_DeviceUnknownVerification.cs | 24 + .../DatabaseContextModelSnapshot.cs | 3 + ...022-05-24_00_DeviceUnknownVerification.sql | 8 + ...0740_DeviceUnknownVerification.Designer.cs | 1599 +++++++++++++++++ ...0220524170740_DeviceUnknownVerification.cs | 24 + .../DatabaseContextModelSnapshot.cs | 3 + ...22-05-24_00_DeviceUnknownVerification.psql | 8 + 23 files changed, 3781 insertions(+), 13 deletions(-) create mode 100644 src/Api/Models/Request/DeviceVerificationRequestModel.cs create mode 100644 src/Api/Models/Response/DeviceVerificationResponseModel.cs create mode 100644 src/Core/Utilities/ClaimsExtensions.cs create mode 100644 test/Core.Test/Utilities/ClaimsExtensionsTests.cs create mode 100644 util/Migrator/DbScripts/2022-05-24_00_DeviceUnknownVerification.sql create mode 100644 util/MySqlMigrations/Migrations/20220524171600_DeviceUnknownVerification.Designer.cs create mode 100644 util/MySqlMigrations/Migrations/20220524171600_DeviceUnknownVerification.cs create mode 100644 util/MySqlMigrations/Scripts/2022-05-24_00_DeviceUnknownVerification.sql create mode 100644 util/PostgresMigrations/Migrations/20220524170740_DeviceUnknownVerification.Designer.cs create mode 100644 util/PostgresMigrations/Migrations/20220524170740_DeviceUnknownVerification.cs create mode 100644 util/PostgresMigrations/Scripts/2022-05-24_00_DeviceUnknownVerification.psql diff --git a/src/Api/Controllers/TwoFactorController.cs b/src/Api/Controllers/TwoFactorController.cs index 7b834dd47..9238e53f0 100644 --- a/src/Api/Controllers/TwoFactorController.cs +++ b/src/Api/Controllers/TwoFactorController.cs @@ -380,6 +380,42 @@ namespace Bit.Api.Controllers } } + [HttpGet("get-device-verification-settings")] + public async Task GetDeviceVerificationSettings() + { + var user = await _userService.GetUserByPrincipalAsync(User); + if (user == null) + { + throw new UnauthorizedAccessException(); + } + + if (User.Claims.HasSsoIdP()) + { + return new DeviceVerificationResponseModel(false, false); + } + + return new DeviceVerificationResponseModel(_userService.CanEditDeviceVerificationSettings(user), user.UnknownDeviceVerificationEnabled); + } + + [HttpPut("device-verification-settings")] + public async Task PutDeviceVerificationSettings([FromBody] DeviceVerificationRequestModel model) + { + var user = await _userService.GetUserByPrincipalAsync(User); + if (user == null) + { + throw new UnauthorizedAccessException(); + } + if (!_userService.CanEditDeviceVerificationSettings(user) + || User.Claims.HasSsoIdP()) + { + throw new InvalidOperationException("Can't update device verification settings"); + } + + model.ToUser(user); + await _userService.SaveUserAsync(user); + return new DeviceVerificationResponseModel(true, user.UnknownDeviceVerificationEnabled); + } + private async Task CheckAsync(SecretVerificationRequestModel model, bool premium) { var user = await _userService.GetUserByPrincipalAsync(User); diff --git a/src/Api/Models/Request/DeviceVerificationRequestModel.cs b/src/Api/Models/Request/DeviceVerificationRequestModel.cs new file mode 100644 index 000000000..acc7aead8 --- /dev/null +++ b/src/Api/Models/Request/DeviceVerificationRequestModel.cs @@ -0,0 +1,18 @@ +using System; +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; + +namespace Bit.Api.Models.Request +{ + public class DeviceVerificationRequestModel + { + [Required] + public bool UnknownDeviceVerificationEnabled { get; set; } + + public User ToUser(User user) + { + user.UnknownDeviceVerificationEnabled = UnknownDeviceVerificationEnabled; + return user; + } + } +} diff --git a/src/Api/Models/Response/DeviceVerificationResponseModel.cs b/src/Api/Models/Response/DeviceVerificationResponseModel.cs new file mode 100644 index 000000000..14711a789 --- /dev/null +++ b/src/Api/Models/Response/DeviceVerificationResponseModel.cs @@ -0,0 +1,18 @@ +using System; +using Bit.Core.Models.Api; + +namespace Bit.Api.Models.Response +{ + public class DeviceVerificationResponseModel : ResponseModel + { + public DeviceVerificationResponseModel(bool isDeviceVerificationSectionEnabled, bool unknownDeviceVerificationEnabled) + : base("deviceVerificationSettings") + { + IsDeviceVerificationSectionEnabled = isDeviceVerificationSectionEnabled; + UnknownDeviceVerificationEnabled = unknownDeviceVerificationEnabled; + } + + public bool IsDeviceVerificationSectionEnabled { get; } + public bool UnknownDeviceVerificationEnabled { get; } + } +} diff --git a/src/Core/Entities/User.cs b/src/Core/Entities/User.cs index 94ec64558..a434a82fd 100644 --- a/src/Core/Entities/User.cs +++ b/src/Core/Entities/User.cs @@ -62,6 +62,7 @@ namespace Bit.Core.Entities public bool UsesKeyConnector { get; set; } public int FailedLoginCount { get; set; } public DateTime? LastFailedLoginDate { get; set; } + public bool UnknownDeviceVerificationEnabled { get; set; } public void SetNewId() { diff --git a/src/Core/Services/IUserService.cs b/src/Core/Services/IUserService.cs index 9abc99bfc..da316fb7a 100644 --- a/src/Core/Services/IUserService.cs +++ b/src/Core/Services/IUserService.cs @@ -79,5 +79,6 @@ namespace Bit.Core.Services Task VerifyOTPAsync(User user, string token); Task VerifySecretAsync(User user, string secret); Task Needs2FABecauseNewDeviceAsync(User user, string deviceIdentifier, string grantType); + bool CanEditDeviceVerificationSettings(User user); } } diff --git a/src/Core/Services/Implementations/EmergencyAccessService.cs b/src/Core/Services/Implementations/EmergencyAccessService.cs index bbd933b03..07fa5fe68 100644 --- a/src/Core/Services/Implementations/EmergencyAccessService.cs +++ b/src/Core/Services/Implementations/EmergencyAccessService.cs @@ -327,6 +327,7 @@ namespace Bit.Core.Services grantor.Key = key; // Disable TwoFactor providers since they will otherwise block logins grantor.SetTwoFactorProviders(new Dictionary()); + grantor.UnknownDeviceVerificationEnabled = false; await _userRepository.ReplaceAsync(grantor); // Remove grantor from all organizations unless Owner diff --git a/src/Core/Services/Implementations/UserService.cs b/src/Core/Services/Implementations/UserService.cs index 558d75dbf..858eef5d3 100644 --- a/src/Core/Services/Implementations/UserService.cs +++ b/src/Core/Services/Implementations/UserService.cs @@ -1417,12 +1417,20 @@ namespace Bit.Core.Services public async Task Needs2FABecauseNewDeviceAsync(User user, string deviceIdentifier, string grantType) { - return _globalSettings.TwoFactorAuth.EmailOnNewDeviceLogin - && user.EmailVerified + return CanEditDeviceVerificationSettings(user) + && user.UnknownDeviceVerificationEnabled && grantType != "authorization_code" && await IsNewDeviceAndNotTheFirstOneAsync(user, deviceIdentifier); } + public bool CanEditDeviceVerificationSettings(User user) + { + return _globalSettings.TwoFactorAuth.EmailOnNewDeviceLogin + && user.EmailVerified + && !user.UsesKeyConnector + && !(user.GetTwoFactorProviders()?.Any() ?? false); + } + private async Task IsNewDeviceAndNotTheFirstOneAsync(User user, string deviceIdentifier) { if (user == null) diff --git a/src/Core/Utilities/ClaimsExtensions.cs b/src/Core/Utilities/ClaimsExtensions.cs new file mode 100644 index 000000000..5f1fe8832 --- /dev/null +++ b/src/Core/Utilities/ClaimsExtensions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; + +namespace Bit.Core.Utilities +{ + public static class ClaimsExtensions + { + public static bool HasSsoIdP(this IEnumerable claims) + { + return claims.Any(c => c.Type == "idp" && c.Value == "sso"); + } + } +} diff --git a/src/Sql/dbo/Stored Procedures/User_Create.sql b/src/Sql/dbo/Stored Procedures/User_Create.sql index 84bb1947d..c5d49a189 100644 --- a/src/Sql/dbo/Stored Procedures/User_Create.sql +++ b/src/Sql/dbo/Stored Procedures/User_Create.sql @@ -33,7 +33,8 @@ @ForcePasswordReset BIT = 0, @UsesKeyConnector BIT = 0, @FailedLoginCount INT = 0, - @LastFailedLoginDate DATETIME2(7) + @LastFailedLoginDate DATETIME2(7), + @UnknownDeviceVerificationEnabled BIT NULL AS BEGIN SET NOCOUNT ON @@ -74,7 +75,8 @@ BEGIN [ForcePasswordReset], [UsesKeyConnector], [FailedLoginCount], - [LastFailedLoginDate] + [LastFailedLoginDate], + [UnknownDeviceVerificationEnabled] ) VALUES ( @@ -112,6 +114,7 @@ BEGIN @ForcePasswordReset, @UsesKeyConnector, @FailedLoginCount, - @LastFailedLoginDate + @LastFailedLoginDate, + @UnknownDeviceVerificationEnabled ) END diff --git a/src/Sql/dbo/Stored Procedures/User_Update.sql b/src/Sql/dbo/Stored Procedures/User_Update.sql index f50ea243d..91fdfe3ef 100644 --- a/src/Sql/dbo/Stored Procedures/User_Update.sql +++ b/src/Sql/dbo/Stored Procedures/User_Update.sql @@ -33,7 +33,8 @@ @ForcePasswordReset BIT = 0, @UsesKeyConnector BIT = 0, @FailedLoginCount INT, - @LastFailedLoginDate DATETIME2(7) + @LastFailedLoginDate DATETIME2(7), + @UnknownDeviceVerificationEnabled BIT NULL AS BEGIN SET NOCOUNT ON @@ -74,7 +75,8 @@ BEGIN [ForcePasswordReset] = @ForcePasswordReset, [UsesKeyConnector] = @UsesKeyConnector, [FailedLoginCount] = @FailedLoginCount, - [LastFailedLoginDate] = @LastFailedLoginDate + [LastFailedLoginDate] = @LastFailedLoginDate, + [UnknownDeviceVerificationEnabled] = @UnknownDeviceVerificationEnabled WHERE [Id] = @Id END diff --git a/src/Sql/dbo/Tables/User.sql b/src/Sql/dbo/Tables/User.sql index fbe17cdfa..13f704811 100644 --- a/src/Sql/dbo/Tables/User.sql +++ b/src/Sql/dbo/Tables/User.sql @@ -34,6 +34,7 @@ [UsesKeyConnector] BIT NOT NULL, [FailedLoginCount] INT NOT NULL, [LastFailedLoginDate] DATETIME2 (7) NULL, + [UnknownDeviceVerificationEnabled] BIT NULL, CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED ([Id] ASC) ); diff --git a/test/Core.Test/Services/EmergencyAccessServiceTests.cs b/test/Core.Test/Services/EmergencyAccessServiceTests.cs index f9319e763..8086845b6 100644 --- a/test/Core.Test/Services/EmergencyAccessServiceTests.cs +++ b/test/Core.Test/Services/EmergencyAccessServiceTests.cs @@ -1,7 +1,10 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using Bit.Core.Entities; +using Bit.Core.Enums; using Bit.Core.Exceptions; +using Bit.Core.Models; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Test.AutoFixture; @@ -137,5 +140,37 @@ namespace Bit.Core.Test.Services Assert.Contains("You cannot takeover an account that is using Key Connector", exception.Message); } + + [Theory, CustomAutoData(typeof(SutProviderCustomization))] + public async Task PasswordAsync_Disables_2FA_Providers_And_Unknown_Device_Verification_On_The_Grantor( + SutProvider sutProvider, User requestingUser, User grantor) + { + grantor.UsesKeyConnector = true; + grantor.UnknownDeviceVerificationEnabled = true; + grantor.SetTwoFactorProviders(new Dictionary + { + [TwoFactorProviderType.Email] = new TwoFactorProvider + { + MetaData = new Dictionary { ["Email"] = "asdfasf" }, + Enabled = true + } + }); + var emergencyAccess = new EmergencyAccess + { + GrantorId = grantor.Id, + GranteeId = requestingUser.Id, + Status = Enums.EmergencyAccessStatusType.RecoveryApproved, + Type = Enums.EmergencyAccessType.Takeover, + }; + + sutProvider.GetDependency().GetByIdAsync(Arg.Any()).Returns(emergencyAccess); + sutProvider.GetDependency().GetByIdAsync(grantor.Id).Returns(grantor); + + await sutProvider.Sut.PasswordAsync(Guid.NewGuid(), requestingUser, "blablahash", "blablakey"); + + Assert.False(grantor.UnknownDeviceVerificationEnabled); + Assert.Empty(grantor.GetTwoFactorProviders()); + await sutProvider.GetDependency().Received().ReplaceAsync(grantor); + } } } diff --git a/test/Core.Test/Services/UserServiceTests.cs b/test/Core.Test/Services/UserServiceTests.cs index 85e19e880..655af0d16 100644 --- a/test/Core.Test/Services/UserServiceTests.cs +++ b/test/Core.Test/Services/UserServiceTests.cs @@ -161,8 +161,9 @@ namespace Bit.Core.Test.Services [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task Needs2FABecauseNewDeviceAsync_ReturnsTrue(SutProvider sutProvider, User user) { - user.Id = Guid.NewGuid(); user.EmailVerified = true; + user.TwoFactorProviders = null; + user.UnknownDeviceVerificationEnabled = true; const string deviceIdToCheck = "7b01b586-b210-499f-8d52-0c3fdaa646fc"; const string deviceIdInRepo = "ea29126c-91b7-4cc4-8ce6-00105b37f64a"; @@ -182,8 +183,8 @@ namespace Bit.Core.Test.Services [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task Needs2FABecauseNewDeviceAsync_ReturnsFalse_When_GranType_Is_AuthorizationCode(SutProvider sutProvider, User user) { - user.Id = Guid.NewGuid(); user.EmailVerified = true; + user.TwoFactorProviders = null; const string deviceIdToCheck = "7b01b586-b210-499f-8d52-0c3fdaa646fc"; const string deviceIdInRepo = "ea29126c-91b7-4cc4-8ce6-00105b37f64a"; @@ -200,8 +201,8 @@ namespace Bit.Core.Test.Services [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task Needs2FABecauseNewDeviceAsync_ReturnsFalse_When_Email_Is_Not_Verified(SutProvider sutProvider, User user) { - user.Id = Guid.NewGuid(); user.EmailVerified = false; + user.TwoFactorProviders = null; const string deviceIdToCheck = "7b01b586-b210-499f-8d52-0c3fdaa646fc"; const string deviceIdInRepo = "ea29126c-91b7-4cc4-8ce6-00105b37f64a"; @@ -218,8 +219,8 @@ namespace Bit.Core.Test.Services [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task Needs2FABecauseNewDeviceAsync_ReturnsFalse_When_Is_The_First_Device(SutProvider sutProvider, User user) { - user.Id = Guid.NewGuid(); user.EmailVerified = true; + user.TwoFactorProviders = null; const string deviceIdToCheck = "7b01b586-b210-499f-8d52-0c3fdaa646fc"; sutProvider.GetDependency() @@ -232,8 +233,8 @@ namespace Bit.Core.Test.Services [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task Needs2FABecauseNewDeviceAsync_ReturnsFalse_When_DeviceId_Is_Already_In_Repo(SutProvider sutProvider, User user) { - user.Id = Guid.NewGuid(); user.EmailVerified = true; + user.TwoFactorProviders = null; const string deviceIdToCheck = "7b01b586-b210-499f-8d52-0c3fdaa646fc"; sutProvider.GetDependency() @@ -249,8 +250,8 @@ namespace Bit.Core.Test.Services [Theory, CustomAutoData(typeof(SutProviderCustomization))] public async Task Needs2FABecauseNewDeviceAsync_ReturnsFalse_When_GlobalSettings_2FA_EmailOnNewDeviceLogin_Is_Disabled(SutProvider sutProvider, User user) { - user.Id = Guid.NewGuid(); user.EmailVerified = true; + user.TwoFactorProviders = null; const string deviceIdToCheck = "7b01b586-b210-499f-8d52-0c3fdaa646fc"; const string deviceIdInRepo = "ea29126c-91b7-4cc4-8ce6-00105b37f64a"; @@ -265,5 +266,89 @@ namespace Bit.Core.Test.Services Assert.False(await sutProvider.Sut.Needs2FABecauseNewDeviceAsync(user, deviceIdToCheck, "password")); } + + [Theory, CustomAutoData(typeof(SutProviderCustomization))] + public async Task Needs2FABecauseNewDeviceAsync_ReturnsFalse_When_UnknownDeviceVerification_Is_Disabled(SutProvider sutProvider, User user) + { + user.EmailVerified = true; + user.TwoFactorProviders = null; + user.UnknownDeviceVerificationEnabled = false; + const string deviceIdToCheck = "7b01b586-b210-499f-8d52-0c3fdaa646fc"; + const string deviceIdInRepo = "ea29126c-91b7-4cc4-8ce6-00105b37f64a"; + + sutProvider.GetDependency() + .GetManyByUserIdAsync(user.Id) + .Returns(Task.FromResult>(new List + { + new Device { Identifier = deviceIdInRepo } + })); + + sutProvider.GetDependency().TwoFactorAuth.EmailOnNewDeviceLogin.Returns(true); + + Assert.False(await sutProvider.Sut.Needs2FABecauseNewDeviceAsync(user, deviceIdToCheck, "password")); + } + + [Theory, CustomAutoData(typeof(SutProviderCustomization))] + public void CanEditDeviceVerificationSettings_ReturnsTrue(SutProvider sutProvider, User user) + { + user.EmailVerified = true; + user.TwoFactorProviders = null; + + sutProvider.GetDependency().TwoFactorAuth.EmailOnNewDeviceLogin.Returns(true); + + Assert.True(sutProvider.Sut.CanEditDeviceVerificationSettings(user)); + } + + [Theory, CustomAutoData(typeof(SutProviderCustomization))] + public void CanEditDeviceVerificationSettings_ReturnsFalse_When_GlobalSettings_2FA_EmailOnNewDeviceLogin_Is_Disabled(SutProvider sutProvider, User user) + { + user.EmailVerified = true; + user.TwoFactorProviders = null; + + sutProvider.GetDependency().TwoFactorAuth.EmailOnNewDeviceLogin.Returns(false); + + Assert.False(sutProvider.Sut.CanEditDeviceVerificationSettings(user)); + } + + [Theory, CustomAutoData(typeof(SutProviderCustomization))] + public void CanEditDeviceVerificationSettings_ReturnsFalse_When_Email_Is_Not_Verified(SutProvider sutProvider, User user) + { + user.EmailVerified = false; + user.TwoFactorProviders = null; + + sutProvider.GetDependency().TwoFactorAuth.EmailOnNewDeviceLogin.Returns(true); + + Assert.False(sutProvider.Sut.CanEditDeviceVerificationSettings(user)); + } + + [Theory, CustomAutoData(typeof(SutProviderCustomization))] + public void CanEditDeviceVerificationSettings_ReturnsFalse_When_User_Uses_Key_Connector(SutProvider sutProvider, User user) + { + user.EmailVerified = true; + user.TwoFactorProviders = null; + user.UsesKeyConnector = true; + + sutProvider.GetDependency().TwoFactorAuth.EmailOnNewDeviceLogin.Returns(true); + + Assert.False(sutProvider.Sut.CanEditDeviceVerificationSettings(user)); + } + + [Theory, CustomAutoData(typeof(SutProviderCustomization))] + public void CanEditDeviceVerificationSettings_ReturnsFalse_When_User_Has_A_2FA_Already_Set_Up(SutProvider sutProvider, User user) + { + user.EmailVerified = true; + user.SetTwoFactorProviders(new Dictionary + { + [TwoFactorProviderType.Email] = new TwoFactorProvider + { + MetaData = new Dictionary { ["Email"] = "asdfasf" }, + Enabled = true + } + }); + + sutProvider.GetDependency().TwoFactorAuth.EmailOnNewDeviceLogin.Returns(true); + + Assert.False(sutProvider.Sut.CanEditDeviceVerificationSettings(user)); + } } } diff --git a/test/Core.Test/Utilities/ClaimsExtensionsTests.cs b/test/Core.Test/Utilities/ClaimsExtensionsTests.cs new file mode 100644 index 000000000..bb888f253 --- /dev/null +++ b/test/Core.Test/Utilities/ClaimsExtensionsTests.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Security.Claims; +using Bit.Core.Utilities; +using Xunit; + +namespace Bit.Core.Test.Utilities +{ + public class ClaimsExtensionsTests + { + [Fact] + public void HasSSOIdP_Returns_True_When_The_Claims_Has_One_Of_Type_IdP_And_Value_Sso() + { + var claims = new List { new Claim("idp", "sso") }; + Assert.True(claims.HasSsoIdP()); + } + + [Fact] + public void HasSSOIdP_Returns_False_When_The_Claims_Has_One_Of_Type_IdP_And_Value_Is_Not_Sso() + { + var claims = new List { new Claim("idp", "asdfasfd") }; + Assert.False(claims.HasSsoIdP()); + } + + [Fact] + public void HasSSOIdP_Returns_False_When_The_Claims_Has_No_One_Of_Type_IdP() + { + var claims = new List { new Claim("qweqweq", "sso") }; + Assert.False(claims.HasSsoIdP()); + } + + [Fact] + public void HasSSOIdP_Returns_False_When_The_Claims_Are_Empty() + { + var claims = new List(); + Assert.False(claims.HasSsoIdP()); + } + } +} diff --git a/util/Migrator/DbScripts/2022-05-24_00_DeviceUnknownVerification.sql b/util/Migrator/DbScripts/2022-05-24_00_DeviceUnknownVerification.sql new file mode 100644 index 000000000..4e0592217 --- /dev/null +++ b/util/Migrator/DbScripts/2022-05-24_00_DeviceUnknownVerification.sql @@ -0,0 +1,245 @@ +-- Table: User (UnknownDeviceVerificationEnabled) +IF COL_LENGTH('[dbo].[User]', 'UnknownDeviceVerificationEnabled') IS NULL +BEGIN + ALTER TABLE + [dbo].[User] + ADD + [UnknownDeviceVerificationEnabled] BIT NOT NULL CONSTRAINT D_User_UnknownDeviceVerificationEnabled DEFAULT 1 +END +GO + +-- View: User +IF EXISTS(SELECT * FROM sys.views WHERE [Name] = 'UserView') +BEGIN + DROP VIEW [dbo].[UserView] +END +GO + +CREATE VIEW [dbo].[UserView] +AS +SELECT + * +FROM + [dbo].[User] +GO + +-- Stored Procedure: User_Create +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), + @ForcePasswordReset BIT = 0, + @UsesKeyConnector BIT = 0, + @FailedLoginCount INT = 0, + @LastFailedLoginDate DATETIME2(7), + @UnknownDeviceVerificationEnabled BIT = 1 +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], + [ForcePasswordReset], + [UsesKeyConnector], + [FailedLoginCount], + [LastFailedLoginDate], + [UnknownDeviceVerificationEnabled] + ) + 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, + @ForcePasswordReset, + @UsesKeyConnector, + @FailedLoginCount, + @LastFailedLoginDate, + @UnknownDeviceVerificationEnabled + ) +END +GO + +-- Stored Procedure: User_Update +IF OBJECT_ID('[dbo].[User_Update]') IS NOT NULL +BEGIN + DROP PROCEDURE [dbo].[User_Update] +END +GO + +CREATE PROCEDURE [dbo].[User_Update] + @Id UNIQUEIDENTIFIER, + @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), + @ForcePasswordReset BIT = 0, + @UsesKeyConnector BIT = 0, + @FailedLoginCount INT, + @LastFailedLoginDate DATETIME2(7), + @UnknownDeviceVerificationEnabled BIT NULL +AS +BEGIN + SET NOCOUNT ON + + UPDATE + [dbo].[User] + SET + [Name] = @Name, + [Email] = @Email, + [EmailVerified] = @EmailVerified, + [MasterPassword] = @MasterPassword, + [MasterPasswordHint] = @MasterPasswordHint, + [Culture] = @Culture, + [SecurityStamp] = @SecurityStamp, + [TwoFactorProviders] = @TwoFactorProviders, + [TwoFactorRecoveryCode] = @TwoFactorRecoveryCode, + [EquivalentDomains] = @EquivalentDomains, + [ExcludedGlobalEquivalentDomains] = @ExcludedGlobalEquivalentDomains, + [AccountRevisionDate] = @AccountRevisionDate, + [Key] = @Key, + [PublicKey] = @PublicKey, + [PrivateKey] = @PrivateKey, + [Premium] = @Premium, + [PremiumExpirationDate] = @PremiumExpirationDate, + [RenewalReminderDate] = @RenewalReminderDate, + [Storage] = @Storage, + [MaxStorageGb] = @MaxStorageGb, + [Gateway] = @Gateway, + [GatewayCustomerId] = @GatewayCustomerId, + [GatewaySubscriptionId] = @GatewaySubscriptionId, + [ReferenceData] = @ReferenceData, + [LicenseKey] = @LicenseKey, + [Kdf] = @Kdf, + [KdfIterations] = @KdfIterations, + [CreationDate] = @CreationDate, + [RevisionDate] = @RevisionDate, + [ApiKey] = @ApiKey, + [ForcePasswordReset] = @ForcePasswordReset, + [UsesKeyConnector] = @UsesKeyConnector, + [FailedLoginCount] = @FailedLoginCount, + [LastFailedLoginDate] = @LastFailedLoginDate, + [UnknownDeviceVerificationEnabled] = @UnknownDeviceVerificationEnabled + WHERE + [Id] = @Id +END +GO + diff --git a/util/MySqlMigrations/Migrations/20220524171600_DeviceUnknownVerification.Designer.cs b/util/MySqlMigrations/Migrations/20220524171600_DeviceUnknownVerification.Designer.cs new file mode 100644 index 000000000..955f60018 --- /dev/null +++ b/util/MySqlMigrations/Migrations/20220524171600_DeviceUnknownVerification.Designer.cs @@ -0,0 +1,1591 @@ +// +using System; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Bit.MySqlMigrations.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20220524171600_DeviceUnknownVerification")] + partial class DeviceUnknownVerification + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("Relational:MaxIdentifierLength", 64) + .HasAnnotation("ProductVersion", "5.0.12"); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Attachments") + .HasColumnType("longtext"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("DeletedDate") + .HasColumnType("datetime(6)"); + + b.Property("Favorites") + .HasColumnType("longtext"); + + b.Property("Folders") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Reprompt") + .HasColumnType("tinyint unsigned"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Cipher"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("CipherId") + .HasColumnType("char(36)"); + + b.HasKey("CollectionId", "CipherId"); + + b.HasIndex("CipherId"); + + b.ToTable("CollectionCipher"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("GroupId") + .HasColumnType("char(36)"); + + b.Property("HidePasswords") + .HasColumnType("tinyint(1)"); + + b.Property("ReadOnly") + .HasColumnType("tinyint(1)"); + + b.HasKey("CollectionId", "GroupId"); + + b.HasIndex("GroupId"); + + b.ToTable("CollectionGroups"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("OrganizationUserId") + .HasColumnType("char(36)"); + + b.Property("HidePasswords") + .HasColumnType("tinyint(1)"); + + b.Property("ReadOnly") + .HasColumnType("tinyint(1)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("PushToken") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Device"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("GranteeId") + .HasColumnType("char(36)"); + + b.Property("GrantorId") + .HasColumnType("char(36)"); + + b.Property("KeyEncrypted") + .HasColumnType("longtext"); + + b.Property("LastNotificationDate") + .HasColumnType("datetime(6)"); + + b.Property("RecoveryInitiatedDate") + .HasColumnType("datetime(6)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("tinyint unsigned"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("WaitTimeDays") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("GranteeId"); + + b.HasIndex("GrantorId"); + + b.ToTable("EmergencyAccess"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Event", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ActingUserId") + .HasColumnType("char(36)"); + + b.Property("CipherId") + .HasColumnType("char(36)"); + + b.Property("CollectionId") + .HasColumnType("char(36)"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("DeviceType") + .HasColumnType("tinyint unsigned"); + + b.Property("GroupId") + .HasColumnType("char(36)"); + + b.Property("InstallationId") + .HasColumnType("char(36)"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("OrganizationUserId") + .HasColumnType("char(36)"); + + b.Property("PolicyId") + .HasColumnType("char(36)"); + + b.Property("ProviderId") + .HasColumnType("char(36)"); + + b.Property("ProviderOrganizationId") + .HasColumnType("char(36)"); + + b.Property("ProviderUserId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("Event"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Folder"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Grant", b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ConsumedDate") + .HasColumnType("datetime(6)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ExpirationDate") + .HasColumnType("datetime(6)"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("Key"); + + b.ToTable("Grant"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccessAll") + .HasColumnType("tinyint(1)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.Property("GroupId") + .HasColumnType("char(36)"); + + b.Property("OrganizationUserId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + b.ToTable("GroupUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Installation", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Key") + .HasMaxLength(150) + .HasColumnType("varchar(150)"); + + b.HasKey("Id"); + + b.ToTable("Installation"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("BillingEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("BusinessAddress1") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("BusinessAddress2") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("BusinessAddress3") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("BusinessCountry") + .HasMaxLength(2) + .HasColumnType("varchar(2)"); + + b.Property("BusinessName") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("BusinessTaxNumber") + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("ExpirationDate") + .HasColumnType("datetime(6)"); + + b.Property("Gateway") + .HasColumnType("tinyint unsigned"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("MaxAutoscaleSeats") + .HasColumnType("int"); + + b.Property("MaxCollections") + .HasColumnType("smallint"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("OwnersNotifiedOfAutoscaling") + .HasColumnType("datetime(6)"); + + b.Property("Plan") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("PlanType") + .HasColumnType("tinyint unsigned"); + + b.Property("PrivateKey") + .HasColumnType("longtext"); + + b.Property("PublicKey") + .HasColumnType("longtext"); + + b.Property("ReferenceData") + .HasColumnType("longtext"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Seats") + .HasColumnType("int"); + + b.Property("SelfHost") + .HasColumnType("tinyint(1)"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("longtext"); + + b.Property("Use2fa") + .HasColumnType("tinyint(1)"); + + b.Property("UseApi") + .HasColumnType("tinyint(1)"); + + b.Property("UseDirectory") + .HasColumnType("tinyint(1)"); + + b.Property("UseEvents") + .HasColumnType("tinyint(1)"); + + b.Property("UseGroups") + .HasColumnType("tinyint(1)"); + + b.Property("UseKeyConnector") + .HasColumnType("tinyint(1)"); + + b.Property("UsePolicies") + .HasColumnType("tinyint(1)"); + + b.Property("UseResetPassword") + .HasColumnType("tinyint(1)"); + + b.Property("UseSso") + .HasColumnType("tinyint(1)"); + + b.Property("UseTotp") + .HasColumnType("tinyint(1)"); + + b.Property("UsersGetPremium") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ApiKey") + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationApiKey"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Config") + .HasColumnType("longtext"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationConnection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("FriendlyName") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("LastSyncDate") + .HasColumnType("datetime(6)"); + + b.Property("OfferedToEmail") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("PlanSponsorshipType") + .HasColumnType("tinyint unsigned"); + + b.Property("SponsoredOrganizationId") + .HasColumnType("char(36)"); + + b.Property("SponsoringOrganizationId") + .HasColumnType("char(36)"); + + b.Property("SponsoringOrganizationUserId") + .HasColumnType("char(36)"); + + b.Property("ToDelete") + .HasColumnType("tinyint(1)"); + + b.Property("ValidUntil") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("SponsoredOrganizationId"); + + b.HasIndex("SponsoringOrganizationId"); + + b.ToTable("OrganizationSponsorship"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccessAll") + .HasColumnType("tinyint(1)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Permissions") + .HasColumnType("longtext"); + + b.Property("ResetPasswordKey") + .HasColumnType("longtext"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("tinyint unsigned"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Policy"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Provider", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("BillingEmail") + .HasColumnType("longtext"); + + b.Property("BusinessAddress1") + .HasColumnType("longtext"); + + b.Property("BusinessAddress2") + .HasColumnType("longtext"); + + b.Property("BusinessAddress3") + .HasColumnType("longtext"); + + b.Property("BusinessCountry") + .HasColumnType("longtext"); + + b.Property("BusinessName") + .HasColumnType("longtext"); + + b.Property("BusinessTaxNumber") + .HasColumnType("longtext"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("tinyint unsigned"); + + b.Property("UseEvents") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderOrganization", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("ProviderId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Settings") + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("ProviderId"); + + b.ToTable("ProviderOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderUser", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasColumnType("longtext"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("Permissions") + .HasColumnType("longtext"); + + b.Property("ProviderId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("tinyint unsigned"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ProviderId"); + + b.HasIndex("UserId"); + + b.ToTable("ProviderUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccessCount") + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("DeletionDate") + .HasColumnType("datetime(6)"); + + b.Property("Disabled") + .HasColumnType("tinyint(1)"); + + b.Property("ExpirationDate") + .HasColumnType("datetime(6)"); + + b.Property("HideEmail") + .HasColumnType("tinyint(1)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("MaxAccessCount") + .HasColumnType("int"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Password") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Send"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("SsoConfig"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("ExternalId") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("SsoUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.TaxRate", b => + { + b.Property("Id") + .HasMaxLength(40) + .HasColumnType("varchar(40)"); + + b.Property("Active") + .HasColumnType("tinyint(1)"); + + b.Property("Country") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("PostalCode") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.Property("Rate") + .HasColumnType("decimal(65,30)"); + + b.Property("State") + .HasMaxLength(2) + .HasColumnType("varchar(2)"); + + b.HasKey("Id"); + + b.ToTable("TaxRate"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("Amount") + .HasColumnType("decimal(65,30)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Details") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("Gateway") + .HasColumnType("tinyint unsigned"); + + b.Property("GatewayId") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("PaymentMethodType") + .HasColumnType("tinyint unsigned"); + + b.Property("Refunded") + .HasColumnType("tinyint(1)"); + + b.Property("RefundedAmount") + .HasColumnType("decimal(65,30)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Transaction"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccountRevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Culture") + .HasMaxLength(10) + .HasColumnType("varchar(10)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("EmailVerified") + .HasColumnType("tinyint(1)"); + + b.Property("EquivalentDomains") + .HasColumnType("longtext"); + + b.Property("ExcludedGlobalEquivalentDomains") + .HasColumnType("longtext"); + + b.Property("FailedLoginCount") + .HasColumnType("int"); + + b.Property("ForcePasswordReset") + .HasColumnType("tinyint(1)"); + + b.Property("Gateway") + .HasColumnType("tinyint unsigned"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Kdf") + .HasColumnType("tinyint unsigned"); + + b.Property("KdfIterations") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("LastFailedLoginDate") + .HasColumnType("datetime(6)"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("MasterPassword") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("MasterPasswordHint") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Premium") + .HasColumnType("tinyint(1)"); + + b.Property("PremiumExpirationDate") + .HasColumnType("datetime(6)"); + + b.Property("PrivateKey") + .HasColumnType("longtext"); + + b.Property("PublicKey") + .HasColumnType("longtext"); + + b.Property("ReferenceData") + .HasColumnType("longtext"); + + b.Property("RenewalReminderDate") + .HasColumnType("datetime(6)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("longtext"); + + b.Property("TwoFactorRecoveryCode") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.Property("UnknownDeviceVerificationEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UsesKeyConnector") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Ciphers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Ciphers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Cipher", "Cipher") + .WithMany("CollectionCiphers") + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionCiphers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionGroups") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionUsers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("CollectionUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("CollectionUsers") + .HasForeignKey("UserId"); + + b.Navigation("Collection"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantee") + .WithMany() + .HasForeignKey("GranteeId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantor") + .WithMany() + .HasForeignKey("GrantorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grantee"); + + b.Navigation("Grantor"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Groups") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany("GroupUsers") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("GroupUsers") + .HasForeignKey("UserId"); + + b.Navigation("Group"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("ApiKeys") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Connections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoredOrganization") + .WithMany() + .HasForeignKey("SponsoredOrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoringOrganization") + .WithMany() + .HasForeignKey("SponsoringOrganizationId"); + + b.Navigation("SponsoredOrganization"); + + b.Navigation("SponsoringOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("OrganizationUsers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("OrganizationUsers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Policies") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderOrganization", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Provider"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoConfig", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoConfigs") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoUsers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("SsoUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Transactions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Navigation("CollectionCiphers"); + + b.Navigation("CollectionGroups"); + + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("Ciphers"); + + b.Navigation("Connections"); + + b.Navigation("Groups"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("Policies"); + + b.Navigation("SsoConfigs"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("CollectionUsers"); + + b.Navigation("Folders"); + + b.Navigation("GroupUsers"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/MySqlMigrations/Migrations/20220524171600_DeviceUnknownVerification.cs b/util/MySqlMigrations/Migrations/20220524171600_DeviceUnknownVerification.cs new file mode 100644 index 000000000..23017d4da --- /dev/null +++ b/util/MySqlMigrations/Migrations/20220524171600_DeviceUnknownVerification.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Bit.MySqlMigrations.Migrations +{ + public partial class DeviceUnknownVerification : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UnknownDeviceVerificationEnabled", + table: "User", + type: "tinyint(1)", + nullable: false, + defaultValue: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UnknownDeviceVerificationEnabled", + table: "User"); + } + } +} diff --git a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs index 316229042..fe49ca4ab 100644 --- a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -1192,6 +1192,9 @@ namespace Bit.MySqlMigrations.Migrations .HasMaxLength(32) .HasColumnType("varchar(32)"); + b.Property("UnknownDeviceVerificationEnabled") + .HasColumnType("tinyint(1)"); + b.Property("UsesKeyConnector") .HasColumnType("tinyint(1)"); diff --git a/util/MySqlMigrations/Scripts/2022-05-24_00_DeviceUnknownVerification.sql b/util/MySqlMigrations/Scripts/2022-05-24_00_DeviceUnknownVerification.sql new file mode 100644 index 000000000..fb11052cc --- /dev/null +++ b/util/MySqlMigrations/Scripts/2022-05-24_00_DeviceUnknownVerification.sql @@ -0,0 +1,8 @@ +START TRANSACTION; + +ALTER TABLE `User` ADD `UnknownDeviceVerificationEnabled` tinyint(1) NOT NULL DEFAULT 1; + +INSERT INTO `__EFMigrationsHistory` (`MigrationId`, `ProductVersion`) +VALUES ('20220524171600_DeviceUnknownVerification', '5.0.12'); + +COMMIT; \ No newline at end of file diff --git a/util/PostgresMigrations/Migrations/20220524170740_DeviceUnknownVerification.Designer.cs b/util/PostgresMigrations/Migrations/20220524170740_DeviceUnknownVerification.Designer.cs new file mode 100644 index 000000000..27b0eeec9 --- /dev/null +++ b/util/PostgresMigrations/Migrations/20220524170740_DeviceUnknownVerification.Designer.cs @@ -0,0 +1,1599 @@ +// +using System; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +namespace Bit.PostgresMigrations.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20220524170740_DeviceUnknownVerification")] + partial class DeviceUnknownVerification + { + 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.12") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Attachments") + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("DeletedDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Favorites") + .HasColumnType("text"); + + b.Property("Folders") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Reprompt") + .HasColumnType("smallint"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Cipher"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("CipherId") + .HasColumnType("uuid"); + + b.HasKey("CollectionId", "CipherId"); + + b.HasIndex("CipherId"); + + b.ToTable("CollectionCipher"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("HidePasswords") + .HasColumnType("boolean"); + + b.Property("ReadOnly") + .HasColumnType("boolean"); + + b.HasKey("CollectionId", "GroupId"); + + b.HasIndex("GroupId"); + + b.ToTable("CollectionGroups"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("OrganizationUserId") + .HasColumnType("uuid"); + + b.Property("HidePasswords") + .HasColumnType("boolean"); + + b.Property("ReadOnly") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PushToken") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Device"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("GranteeId") + .HasColumnType("uuid"); + + b.Property("GrantorId") + .HasColumnType("uuid"); + + b.Property("KeyEncrypted") + .HasColumnType("text"); + + b.Property("LastNotificationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RecoveryInitiatedDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("WaitTimeDays") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GranteeId"); + + b.HasIndex("GrantorId"); + + b.ToTable("EmergencyAccess"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Event", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ActingUserId") + .HasColumnType("uuid"); + + b.Property("CipherId") + .HasColumnType("uuid"); + + b.Property("CollectionId") + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("timestamp without time zone"); + + b.Property("DeviceType") + .HasColumnType("smallint"); + + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("InstallationId") + .HasColumnType("uuid"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("OrganizationUserId") + .HasColumnType("uuid"); + + b.Property("PolicyId") + .HasColumnType("uuid"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("ProviderOrganizationId") + .HasColumnType("uuid"); + + b.Property("ProviderUserId") + .HasColumnType("uuid"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("Event"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Folder"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Grant", b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ConsumedDate") + .HasColumnType("timestamp without time zone"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.HasKey("Key"); + + b.ToTable("Grant"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessAll") + .HasColumnType("boolean"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("OrganizationUserId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + b.ToTable("GroupUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Installation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("Key") + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.HasKey("Id"); + + b.ToTable("Installation"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("BillingEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("BusinessAddress1") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BusinessAddress2") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BusinessAddress3") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BusinessCountry") + .HasMaxLength(2) + .HasColumnType("character varying(2)"); + + b.Property("BusinessName") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("BusinessTaxNumber") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Gateway") + .HasColumnType("smallint"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .UseCollation("postgresIndetermanisticCollation"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("MaxAutoscaleSeats") + .HasColumnType("integer"); + + b.Property("MaxCollections") + .HasColumnType("smallint"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("OwnersNotifiedOfAutoscaling") + .HasColumnType("timestamp without time zone"); + + b.Property("Plan") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PlanType") + .HasColumnType("smallint"); + + b.Property("PrivateKey") + .HasColumnType("text"); + + b.Property("PublicKey") + .HasColumnType("text"); + + b.Property("ReferenceData") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Seats") + .HasColumnType("integer"); + + b.Property("SelfHost") + .HasColumnType("boolean"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("text"); + + b.Property("Use2fa") + .HasColumnType("boolean"); + + b.Property("UseApi") + .HasColumnType("boolean"); + + b.Property("UseDirectory") + .HasColumnType("boolean"); + + b.Property("UseEvents") + .HasColumnType("boolean"); + + b.Property("UseGroups") + .HasColumnType("boolean"); + + b.Property("UseKeyConnector") + .HasColumnType("boolean"); + + b.Property("UsePolicies") + .HasColumnType("boolean"); + + b.Property("UseResetPassword") + .HasColumnType("boolean"); + + b.Property("UseSso") + .HasColumnType("boolean"); + + b.Property("UseTotp") + .HasColumnType("boolean"); + + b.Property("UsersGetPremium") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ApiKey") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationApiKey"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Config") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationConnection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("FriendlyName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("LastSyncDate") + .HasColumnType("timestamp without time zone"); + + b.Property("OfferedToEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PlanSponsorshipType") + .HasColumnType("smallint"); + + b.Property("SponsoredOrganizationId") + .HasColumnType("uuid"); + + b.Property("SponsoringOrganizationId") + .HasColumnType("uuid"); + + b.Property("SponsoringOrganizationUserId") + .HasColumnType("uuid"); + + b.Property("ToDelete") + .HasColumnType("boolean"); + + b.Property("ValidUntil") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("SponsoredOrganizationId"); + + b.HasIndex("SponsoringOrganizationId"); + + b.ToTable("OrganizationSponsorship"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessAll") + .HasColumnType("boolean"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("ResetPasswordKey") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Policy"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Provider", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("BillingEmail") + .HasColumnType("text"); + + b.Property("BusinessAddress1") + .HasColumnType("text"); + + b.Property("BusinessAddress2") + .HasColumnType("text"); + + b.Property("BusinessAddress3") + .HasColumnType("text"); + + b.Property("BusinessCountry") + .HasColumnType("text"); + + b.Property("BusinessName") + .HasColumnType("text"); + + b.Property("BusinessTaxNumber") + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("UseEvents") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderOrganization", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("ProviderId"); + + b.ToTable("ProviderOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("Permissions") + .HasColumnType("text"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ProviderId"); + + b.HasIndex("UserId"); + + b.ToTable("ProviderUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessCount") + .HasColumnType("integer"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("DeletionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Disabled") + .HasColumnType("boolean"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("HideEmail") + .HasColumnType("boolean"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("MaxAccessCount") + .HasColumnType("integer"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Password") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Send"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("SsoConfig"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasAnnotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ExternalId") + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .UseCollation("postgresIndetermanisticCollation"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("SsoUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.TaxRate", b => + { + b.Property("Id") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("Active") + .HasColumnType("boolean"); + + b.Property("Country") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("PostalCode") + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("Rate") + .HasColumnType("numeric"); + + b.Property("State") + .HasMaxLength(2) + .HasColumnType("character varying(2)"); + + b.HasKey("Id"); + + b.ToTable("TaxRate"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Details") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Gateway") + .HasColumnType("smallint"); + + b.Property("GatewayId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("PaymentMethodType") + .HasColumnType("smallint"); + + b.Property("Refunded") + .HasColumnType("boolean"); + + b.Property("RefundedAmount") + .HasColumnType("numeric"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Transaction"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountRevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("CreationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("Culture") + .HasMaxLength(10) + .HasColumnType("character varying(10)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .UseCollation("postgresIndetermanisticCollation"); + + b.Property("EmailVerified") + .HasColumnType("boolean"); + + b.Property("EquivalentDomains") + .HasColumnType("text"); + + b.Property("ExcludedGlobalEquivalentDomains") + .HasColumnType("text"); + + b.Property("FailedLoginCount") + .HasColumnType("integer"); + + b.Property("ForcePasswordReset") + .HasColumnType("boolean"); + + b.Property("Gateway") + .HasColumnType("smallint"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Kdf") + .HasColumnType("smallint"); + + b.Property("KdfIterations") + .HasColumnType("integer"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("LastFailedLoginDate") + .HasColumnType("timestamp without time zone"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("MasterPassword") + .HasMaxLength(300) + .HasColumnType("character varying(300)"); + + b.Property("MasterPasswordHint") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Premium") + .HasColumnType("boolean"); + + b.Property("PremiumExpirationDate") + .HasColumnType("timestamp without time zone"); + + b.Property("PrivateKey") + .HasColumnType("text"); + + b.Property("PublicKey") + .HasColumnType("text"); + + b.Property("ReferenceData") + .HasColumnType("text"); + + b.Property("RenewalReminderDate") + .HasColumnType("timestamp without time zone"); + + b.Property("RevisionDate") + .HasColumnType("timestamp without time zone"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("text"); + + b.Property("TwoFactorRecoveryCode") + .HasMaxLength(32) + .HasColumnType("character varying(32)"); + + b.Property("UnknownDeviceVerificationEnabled") + .HasColumnType("boolean"); + + b.Property("UsesKeyConnector") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Ciphers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Ciphers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Cipher", "Cipher") + .WithMany("CollectionCiphers") + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionCiphers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionGroups") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionUsers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("CollectionUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("CollectionUsers") + .HasForeignKey("UserId"); + + b.Navigation("Collection"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantee") + .WithMany() + .HasForeignKey("GranteeId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantor") + .WithMany() + .HasForeignKey("GrantorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grantee"); + + b.Navigation("Grantor"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Groups") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany("GroupUsers") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("GroupUsers") + .HasForeignKey("UserId"); + + b.Navigation("Group"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("ApiKeys") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Connections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoredOrganization") + .WithMany() + .HasForeignKey("SponsoredOrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoringOrganization") + .WithMany() + .HasForeignKey("SponsoringOrganizationId"); + + b.Navigation("SponsoredOrganization"); + + b.Navigation("SponsoringOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("OrganizationUsers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("OrganizationUsers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Policies") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderOrganization", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Provider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Provider"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoConfig", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoConfigs") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoUsers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("SsoUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Transactions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Navigation("CollectionCiphers"); + + b.Navigation("CollectionGroups"); + + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("Ciphers"); + + b.Navigation("Connections"); + + b.Navigation("Groups"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("Policies"); + + b.Navigation("SsoConfigs"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("CollectionUsers"); + + b.Navigation("Folders"); + + b.Navigation("GroupUsers"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/PostgresMigrations/Migrations/20220524170740_DeviceUnknownVerification.cs b/util/PostgresMigrations/Migrations/20220524170740_DeviceUnknownVerification.cs new file mode 100644 index 000000000..880c65908 --- /dev/null +++ b/util/PostgresMigrations/Migrations/20220524170740_DeviceUnknownVerification.cs @@ -0,0 +1,24 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Bit.PostgresMigrations.Migrations +{ + public partial class DeviceUnknownVerification : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UnknownDeviceVerificationEnabled", + table: "User", + type: "boolean", + nullable: false, + defaultValue: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UnknownDeviceVerificationEnabled", + table: "User"); + } + } +} diff --git a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs index b4b6a076e..818dcffd5 100644 --- a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -1200,6 +1200,9 @@ namespace Bit.PostgresMigrations.Migrations .HasMaxLength(32) .HasColumnType("character varying(32)"); + b.Property("UnknownDeviceVerificationEnabled") + .HasColumnType("boolean"); + b.Property("UsesKeyConnector") .HasColumnType("boolean"); diff --git a/util/PostgresMigrations/Scripts/2022-05-24_00_DeviceUnknownVerification.psql b/util/PostgresMigrations/Scripts/2022-05-24_00_DeviceUnknownVerification.psql new file mode 100644 index 000000000..dbe25b304 --- /dev/null +++ b/util/PostgresMigrations/Scripts/2022-05-24_00_DeviceUnknownVerification.psql @@ -0,0 +1,8 @@ +START TRANSACTION; + +ALTER TABLE "User" ADD "UnknownDeviceVerificationEnabled" boolean NOT NULL DEFAULT 1; + +INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion") +VALUES ('20220524170740_DeviceUnknownVerification', '5.0.12'); + +COMMIT; \ No newline at end of file