From bb3a9daf9883353fa942a17ba5d8c2b1f642960b Mon Sep 17 00:00:00 2001 From: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> Date: Wed, 21 Jun 2023 13:16:06 -0500 Subject: [PATCH 01/13] [SM-678] ClientSecret migration (#2943) * Init ClientSecret migration * Fix unit tests * Move to src/Sql/dbo_future * Formatting changes * Update migration date for next release * Swap to just executing sp_refreshview * Fix formatting * Add EF Migrations * Rename to ClientSecretHash * Fix unit test * EF column rename * Batch the migration * Fix formatting * Add deprecation notice to property * Move data migration * Swap to CREATE OR ALTER --- .../AccessTokens/CreateAccessTokenCommand.cs | 21 +- .../AccessTokenCreationResponseModel.cs | 16 +- .../Interfaces/ICreateAccessTokenCommand.cs | 3 +- src/Core/SecretsManager/Entities/ApiKey.cs | 4 +- .../Models/Data/ApiKeyClientSecretDetails.cs | 9 + .../Models/Data/ApiKeyDetails.cs | 4 +- src/Identity/IdentityServer/ClientStore.cs | 7 +- .../ApiKey/ApiKey_Create.sql | 11 +- src/Sql/SecretsManager/dbo/Tables/ApiKey.sql | 21 +- .../Stored Procedures/ApiKey_Create.sql | 42 + src/Sql/dbo_future/Tables/ApiKey.sql | 18 + .../ServiceAccountsControllerTests.cs | 12 +- .../2023-05-16_00_ClientSecretHash.sql | 72 + ...05-16_00_ClientSecretHashDataMigration.sql | 42 + .../2023-06-FutureMigration.sql | 65 + ...0230523223530_ClientSecretHash.Designer.cs | 2190 ++++++++++++++++ .../20230523223530_ClientSecretHash.cs | 38 + .../DatabaseContextModelSnapshot.cs | 6 +- ...0230523223526_ClientSecretHash.Designer.cs | 2201 +++++++++++++++++ .../20230523223526_ClientSecretHash.cs | 36 + .../DatabaseContextModelSnapshot.cs | 6 +- ...0230523223522_ClientSecretHash.Designer.cs | 2188 ++++++++++++++++ .../20230523223522_ClientSecretHash.cs | 36 + .../DatabaseContextModelSnapshot.cs | 4 +- 24 files changed, 7011 insertions(+), 41 deletions(-) create mode 100644 src/Core/SecretsManager/Models/Data/ApiKeyClientSecretDetails.cs create mode 100644 src/Sql/dbo_future/Stored Procedures/ApiKey_Create.sql create mode 100644 src/Sql/dbo_future/Tables/ApiKey.sql create mode 100644 util/Migrator/DbScripts/2023-05-16_00_ClientSecretHash.sql create mode 100644 util/Migrator/DbScripts_data_migration/2023-05-16_00_ClientSecretHashDataMigration.sql create mode 100644 util/Migrator/DbScripts_future/2023-06-FutureMigration.sql create mode 100644 util/MySqlMigrations/Migrations/20230523223530_ClientSecretHash.Designer.cs create mode 100644 util/MySqlMigrations/Migrations/20230523223530_ClientSecretHash.cs create mode 100644 util/PostgresMigrations/Migrations/20230523223526_ClientSecretHash.Designer.cs create mode 100644 util/PostgresMigrations/Migrations/20230523223526_ClientSecretHash.cs create mode 100644 util/SqliteMigrations/Migrations/20230523223522_ClientSecretHash.Designer.cs create mode 100644 util/SqliteMigrations/Migrations/20230523223522_ClientSecretHash.cs diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessTokens/CreateAccessTokenCommand.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessTokens/CreateAccessTokenCommand.cs index f6af908fb2..2771986fda 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessTokens/CreateAccessTokenCommand.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/Commands/AccessTokens/CreateAccessTokenCommand.cs @@ -1,6 +1,9 @@ -using Bit.Core.Exceptions; +using System.Security.Cryptography; +using System.Text; +using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Commands.AccessTokens.Interfaces; using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Models.Data; using Bit.Core.SecretsManager.Repositories; using Bit.Core.Utilities; @@ -16,14 +19,24 @@ public class CreateAccessTokenCommand : ICreateAccessTokenCommand _apiKeyRepository = apiKeyRepository; } - public async Task CreateAsync(ApiKey apiKey) + public async Task CreateAsync(ApiKey apiKey) { if (apiKey.ServiceAccountId == null) { throw new BadRequestException(); } - apiKey.ClientSecret = CoreHelpers.SecureRandomString(_clientSecretMaxLength); - return await _apiKeyRepository.CreateAsync(apiKey); + var clientSecret = CoreHelpers.SecureRandomString(_clientSecretMaxLength); + apiKey.ClientSecretHash = GetHash(clientSecret); + var result = await _apiKeyRepository.CreateAsync(apiKey); + return new ApiKeyClientSecretDetails { ApiKey = result, ClientSecret = clientSecret }; + } + + private static string GetHash(string input) + { + using var sha = SHA256.Create(); + var bytes = Encoding.UTF8.GetBytes(input); + var hash = sha.ComputeHash(bytes); + return Convert.ToBase64String(hash); } } diff --git a/src/Api/SecretsManager/Models/Response/AccessTokenCreationResponseModel.cs b/src/Api/SecretsManager/Models/Response/AccessTokenCreationResponseModel.cs index 609ab4ebd9..69846995b6 100644 --- a/src/Api/SecretsManager/Models/Response/AccessTokenCreationResponseModel.cs +++ b/src/Api/SecretsManager/Models/Response/AccessTokenCreationResponseModel.cs @@ -1,6 +1,6 @@ #nullable enable using Bit.Core.Models.Api; -using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Models.Data; namespace Bit.Api.SecretsManager.Models.Response; @@ -8,14 +8,14 @@ public class AccessTokenCreationResponseModel : ResponseModel { private const string _objectName = "accessTokenCreation"; - public AccessTokenCreationResponseModel(ApiKey apiKey) : base(_objectName) + public AccessTokenCreationResponseModel(ApiKeyClientSecretDetails details) : base(_objectName) { - Id = apiKey.Id; - Name = apiKey.Name; - ClientSecret = apiKey.ClientSecret; - ExpireAt = apiKey.ExpireAt; - CreationDate = apiKey.CreationDate; - RevisionDate = apiKey.RevisionDate; + Id = details.ApiKey.Id; + Name = details.ApiKey.Name; + ExpireAt = details.ApiKey.ExpireAt; + CreationDate = details.ApiKey.CreationDate; + RevisionDate = details.ApiKey.RevisionDate; + ClientSecret = details.ClientSecret; } public AccessTokenCreationResponseModel() : base(_objectName) diff --git a/src/Core/SecretsManager/Commands/AccessTokens/Interfaces/ICreateAccessTokenCommand.cs b/src/Core/SecretsManager/Commands/AccessTokens/Interfaces/ICreateAccessTokenCommand.cs index 2d05f8ca95..c2579df92e 100644 --- a/src/Core/SecretsManager/Commands/AccessTokens/Interfaces/ICreateAccessTokenCommand.cs +++ b/src/Core/SecretsManager/Commands/AccessTokens/Interfaces/ICreateAccessTokenCommand.cs @@ -1,8 +1,9 @@ using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Models.Data; namespace Bit.Core.SecretsManager.Commands.AccessTokens.Interfaces; public interface ICreateAccessTokenCommand { - Task CreateAsync(ApiKey apiKey); + Task CreateAsync(ApiKey apiKey); } diff --git a/src/Core/SecretsManager/Entities/ApiKey.cs b/src/Core/SecretsManager/Entities/ApiKey.cs index 0e6d2a18ec..2f9c5b48c2 100644 --- a/src/Core/SecretsManager/Entities/ApiKey.cs +++ b/src/Core/SecretsManager/Entities/ApiKey.cs @@ -10,8 +10,8 @@ public class ApiKey : ITableObject public Guid? ServiceAccountId { get; set; } [MaxLength(200)] public string Name { get; set; } - [MaxLength(30)] - public string ClientSecret { get; set; } + [MaxLength(128)] + public string ClientSecretHash { get; set; } [MaxLength(4000)] public string Scope { get; set; } [MaxLength(4000)] diff --git a/src/Core/SecretsManager/Models/Data/ApiKeyClientSecretDetails.cs b/src/Core/SecretsManager/Models/Data/ApiKeyClientSecretDetails.cs new file mode 100644 index 0000000000..bcf84942b5 --- /dev/null +++ b/src/Core/SecretsManager/Models/Data/ApiKeyClientSecretDetails.cs @@ -0,0 +1,9 @@ +using Bit.Core.SecretsManager.Entities; + +namespace Bit.Core.SecretsManager.Models.Data; + +public class ApiKeyClientSecretDetails +{ + public ApiKey ApiKey { get; set; } + public string ClientSecret { get; set; } +} diff --git a/src/Core/SecretsManager/Models/Data/ApiKeyDetails.cs b/src/Core/SecretsManager/Models/Data/ApiKeyDetails.cs index b09496eb18..2c8c3d4692 100644 --- a/src/Core/SecretsManager/Models/Data/ApiKeyDetails.cs +++ b/src/Core/SecretsManager/Models/Data/ApiKeyDetails.cs @@ -4,6 +4,8 @@ namespace Bit.Core.SecretsManager.Models.Data; public class ApiKeyDetails : ApiKey { + public string ClientSecret { get; set; } // Deprecated as of 2023-05-17 + protected ApiKeyDetails() { } protected ApiKeyDetails(ApiKey apiKey) @@ -11,7 +13,7 @@ public class ApiKeyDetails : ApiKey Id = apiKey.Id; ServiceAccountId = apiKey.ServiceAccountId; Name = apiKey.Name; - ClientSecret = apiKey.ClientSecret; + ClientSecretHash = apiKey.ClientSecretHash; Scope = apiKey.Scope; EncryptedPayload = apiKey.EncryptedPayload; Key = apiKey.Key; diff --git a/src/Identity/IdentityServer/ClientStore.cs b/src/Identity/IdentityServer/ClientStore.cs index c9b1595d66..f7987b9baf 100644 --- a/src/Identity/IdentityServer/ClientStore.cs +++ b/src/Identity/IdentityServer/ClientStore.cs @@ -107,11 +107,16 @@ public class ClientStore : IClientStore break; } + if (string.IsNullOrEmpty(apiKey.ClientSecretHash)) + { + apiKey.ClientSecretHash = apiKey.ClientSecret.Sha256(); + } + var client = new Client { ClientId = clientId, RequireClientSecret = true, - ClientSecrets = { new Secret(apiKey.ClientSecret.Sha256()) }, + ClientSecrets = { new Secret(apiKey.ClientSecretHash) }, AllowedScopes = apiKey.GetScopes(), AllowedGrantTypes = GrantTypes.ClientCredentials, AccessTokenLifetime = 3600 * 1, diff --git a/src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_Create.sql b/src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_Create.sql index 57d983a438..e72316ef49 100644 --- a/src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_Create.sql +++ b/src/Sql/SecretsManager/dbo/Stored Procedures/ApiKey/ApiKey_Create.sql @@ -2,7 +2,8 @@ CREATE PROCEDURE [dbo].[ApiKey_Create] @Id UNIQUEIDENTIFIER OUTPUT, @ServiceAccountId UNIQUEIDENTIFIER, @Name VARCHAR(200), - @ClientSecret VARCHAR(30), + @ClientSecret VARCHAR(30) = 'migrated', -- Deprecated as of 2023-05-17 + @ClientSecretHash VARCHAR(128) = NULL, @Scope NVARCHAR(4000), @EncryptedPayload NVARCHAR(4000), @Key VARCHAR(MAX), @@ -13,12 +14,19 @@ AS BEGIN SET NOCOUNT ON + IF (@ClientSecretHash IS NULL) + BEGIN + DECLARE @hb VARBINARY(128) = HASHBYTES('SHA2_256', @ClientSecret); + SET @ClientSecretHash = CAST(N'' as xml).value('xs:base64Binary(sql:variable("@hb"))', 'VARCHAR(128)'); + END + INSERT INTO [dbo].[ApiKey] ( [Id], [ServiceAccountId], [Name], [ClientSecret], + [ClientSecretHash], [Scope], [EncryptedPayload], [Key], @@ -32,6 +40,7 @@ BEGIN @ServiceAccountId, @Name, @ClientSecret, + @ClientSecretHash, @Scope, @EncryptedPayload, @Key, diff --git a/src/Sql/SecretsManager/dbo/Tables/ApiKey.sql b/src/Sql/SecretsManager/dbo/Tables/ApiKey.sql index 506da9c10b..5761d45e48 100644 --- a/src/Sql/SecretsManager/dbo/Tables/ApiKey.sql +++ b/src/Sql/SecretsManager/dbo/Tables/ApiKey.sql @@ -1,14 +1,15 @@ CREATE TABLE [dbo].[ApiKey] ( - [Id] UNIQUEIDENTIFIER, - [ServiceAccountId] UNIQUEIDENTIFIER NULL, - [Name] VARCHAR(200) NOT NULL, - [ClientSecret] VARCHAR(30) NOT NULL, - [Scope] NVARCHAR (4000) NOT NULL, - [EncryptedPayload] NVARCHAR (4000) NOT NULL, - [Key] VARCHAR (MAX) NOT NULL, - [ExpireAt] DATETIME2(7) NULL, - [CreationDate] DATETIME2(7) NOT NULL, - [RevisionDate] DATETIME2(7) NOT NULL, + [Id] UNIQUEIDENTIFIER, + [ServiceAccountId] UNIQUEIDENTIFIER NULL, + [Name] VARCHAR(200) NOT NULL, + [ClientSecret] VARCHAR(30) NOT NULL, + [ClientSecretHash] VARCHAR(128) NULL, + [Scope] NVARCHAR (4000) NOT NULL, + [EncryptedPayload] NVARCHAR (4000) NOT NULL, + [Key] VARCHAR (MAX) NOT NULL, + [ExpireAt] DATETIME2(7) NULL, + [CreationDate] DATETIME2(7) NOT NULL, + [RevisionDate] DATETIME2(7) NOT NULL, CONSTRAINT [PK_ApiKey] PRIMARY KEY CLUSTERED ([Id] ASC), CONSTRAINT [FK_ApiKey_ServiceAccountId] FOREIGN KEY ([ServiceAccountId]) REFERENCES [dbo].[ServiceAccount] ([Id]) ); diff --git a/src/Sql/dbo_future/Stored Procedures/ApiKey_Create.sql b/src/Sql/dbo_future/Stored Procedures/ApiKey_Create.sql new file mode 100644 index 0000000000..241881efdd --- /dev/null +++ b/src/Sql/dbo_future/Stored Procedures/ApiKey_Create.sql @@ -0,0 +1,42 @@ +CREATE PROCEDURE [dbo].[ApiKey_Create] + @Id UNIQUEIDENTIFIER OUTPUT, + @ServiceAccountId UNIQUEIDENTIFIER, + @Name VARCHAR(200), + @ClientSecretHash VARCHAR(128), + @Scope NVARCHAR(4000), + @EncryptedPayload NVARCHAR(4000), + @Key VARCHAR(MAX), + @ExpireAt DATETIME2(7), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7) +AS +BEGIN + SET NOCOUNT ON + + INSERT INTO [dbo].[ApiKey] + ( + [Id], + [ServiceAccountId], + [Name], + [ClientSecretHash], + [Scope], + [EncryptedPayload], + [Key], + [ExpireAt], + [CreationDate], + [RevisionDate] + ) + VALUES + ( + @Id, + @ServiceAccountId, + @Name, + @ClientSecretHash, + @Scope, + @EncryptedPayload, + @Key, + @ExpireAt, + @CreationDate, + @RevisionDate + ) +END diff --git a/src/Sql/dbo_future/Tables/ApiKey.sql b/src/Sql/dbo_future/Tables/ApiKey.sql new file mode 100644 index 0000000000..70400d5ed4 --- /dev/null +++ b/src/Sql/dbo_future/Tables/ApiKey.sql @@ -0,0 +1,18 @@ +CREATE TABLE [dbo].[ApiKey] ( + [Id] UNIQUEIDENTIFIER, + [ServiceAccountId] UNIQUEIDENTIFIER NULL, + [Name] VARCHAR(200) NOT NULL, + [ClientSecretHash] VARCHAR(128) NULL, + [Scope] NVARCHAR (4000) NOT NULL, + [EncryptedPayload] NVARCHAR (4000) NOT NULL, + [Key] VARCHAR (MAX) NOT NULL, + [ExpireAt] DATETIME2(7) NULL, + [CreationDate] DATETIME2(7) NOT NULL, + [RevisionDate] DATETIME2(7) NOT NULL, + CONSTRAINT [PK_ApiKey] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_ApiKey_ServiceAccountId] FOREIGN KEY ([ServiceAccountId]) REFERENCES [dbo].[ServiceAccount] ([Id]) +); + +GO +CREATE NONCLUSTERED INDEX [IX_ApiKey_ServiceAccountId] + ON [dbo].[ApiKey]([ServiceAccountId] ASC); diff --git a/test/Api.Test/SecretsManager/Controllers/ServiceAccountsControllerTests.cs b/test/Api.Test/SecretsManager/Controllers/ServiceAccountsControllerTests.cs index f267f36b4f..2b5095384b 100644 --- a/test/Api.Test/SecretsManager/Controllers/ServiceAccountsControllerTests.cs +++ b/test/Api.Test/SecretsManager/Controllers/ServiceAccountsControllerTests.cs @@ -7,6 +7,7 @@ using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Commands.AccessTokens.Interfaces; using Bit.Core.SecretsManager.Commands.ServiceAccounts.Interfaces; using Bit.Core.SecretsManager.Entities; +using Bit.Core.SecretsManager.Models.Data; using Bit.Core.SecretsManager.Repositories; using Bit.Core.Services; using Bit.Test.Common.AutoFixture; @@ -144,7 +145,7 @@ public class ServiceAccountsControllerTests [Theory] [BitAutoData] public async void CreateAccessToken_NoAccess_Throws(SutProvider sutProvider, - AccessTokenCreateRequestModel data, ServiceAccount serviceAccount) + AccessTokenCreateRequestModel data, ServiceAccount serviceAccount, string mockClientSecret) { sutProvider.GetDependency().GetByIdAsync(serviceAccount.Id).Returns(serviceAccount); sutProvider.GetDependency() @@ -152,8 +153,9 @@ public class ServiceAccountsControllerTests Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Failed()); var resultAccessToken = data.ToApiKey(serviceAccount.Id); - sutProvider.GetDependency().CreateAsync(default) - .ReturnsForAnyArgs(resultAccessToken); + sutProvider.GetDependency() + .CreateAsync(default) + .ReturnsForAnyArgs(new ApiKeyClientSecretDetails { ApiKey = resultAccessToken, ClientSecret = mockClientSecret }); await Assert.ThrowsAsync(() => sutProvider.Sut.CreateAccessTokenAsync(serviceAccount.Id, data)); @@ -164,7 +166,7 @@ public class ServiceAccountsControllerTests [Theory] [BitAutoData] public async void CreateAccessToken_Success(SutProvider sutProvider, - AccessTokenCreateRequestModel data, ServiceAccount serviceAccount) + AccessTokenCreateRequestModel data, ServiceAccount serviceAccount, string mockClientSecret) { sutProvider.GetDependency().GetByIdAsync(serviceAccount.Id).Returns(serviceAccount); sutProvider.GetDependency() @@ -173,7 +175,7 @@ public class ServiceAccountsControllerTests var resultAccessToken = data.ToApiKey(serviceAccount.Id); sutProvider.GetDependency().CreateAsync(default) - .ReturnsForAnyArgs(resultAccessToken); + .ReturnsForAnyArgs(new ApiKeyClientSecretDetails { ApiKey = resultAccessToken, ClientSecret = mockClientSecret }); await sutProvider.Sut.CreateAccessTokenAsync(serviceAccount.Id, data); await sutProvider.GetDependency().Received(1) diff --git a/util/Migrator/DbScripts/2023-05-16_00_ClientSecretHash.sql b/util/Migrator/DbScripts/2023-05-16_00_ClientSecretHash.sql new file mode 100644 index 0000000000..1a4fa902bf --- /dev/null +++ b/util/Migrator/DbScripts/2023-05-16_00_ClientSecretHash.sql @@ -0,0 +1,72 @@ +IF COL_LENGTH('[dbo].[ApiKey]', 'ClientSecretHash') IS NULL +BEGIN + ALTER TABLE [dbo].[ApiKey] + ADD [ClientSecretHash] VARCHAR(128); +END +GO + +-- Refresh views +IF OBJECT_ID('[dbo].[ApiKeyDetailsView]') IS NOT NULL + BEGIN + EXECUTE sp_refreshview N'[dbo].[ApiKeyDetailsView]'; + END +GO + +IF OBJECT_ID('[dbo].[ApiKeyView]') IS NOT NULL + BEGIN + EXECUTE sp_refreshview N'[dbo].[ApiKeyView]'; + END +GO + +CREATE OR ALTER PROCEDURE [dbo].[ApiKey_Create] + @Id UNIQUEIDENTIFIER OUTPUT, + @ServiceAccountId UNIQUEIDENTIFIER, + @Name VARCHAR(200), + @ClientSecret VARCHAR(30) = 'migrated', -- Deprecated as of 2023-05-17 + @ClientSecretHash VARCHAR(128) = NULL, + @Scope NVARCHAR(4000), + @EncryptedPayload NVARCHAR(4000), + @Key VARCHAR(MAX), + @ExpireAt DATETIME2(7), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7) +AS +BEGIN + SET NOCOUNT ON + + IF (@ClientSecretHash IS NULL) + BEGIN + DECLARE @hb VARBINARY(128) = HASHBYTES('SHA2_256', @ClientSecret); + SET @ClientSecretHash = CAST(N'' as xml).value('xs:base64Binary(sql:variable("@hb"))', 'VARCHAR(128)'); + END + + INSERT INTO [dbo].[ApiKey] + ( + [Id], + [ServiceAccountId], + [Name], + [ClientSecret], + [ClientSecretHash], + [Scope], + [EncryptedPayload], + [Key], + [ExpireAt], + [CreationDate], + [RevisionDate] + ) + VALUES + ( + @Id, + @ServiceAccountId, + @Name, + @ClientSecret, + @ClientSecretHash, + @Scope, + @EncryptedPayload, + @Key, + @ExpireAt, + @CreationDate, + @RevisionDate + ) +END +GO diff --git a/util/Migrator/DbScripts_data_migration/2023-05-16_00_ClientSecretHashDataMigration.sql b/util/Migrator/DbScripts_data_migration/2023-05-16_00_ClientSecretHashDataMigration.sql new file mode 100644 index 0000000000..5d8261f930 --- /dev/null +++ b/util/Migrator/DbScripts_data_migration/2023-05-16_00_ClientSecretHashDataMigration.sql @@ -0,0 +1,42 @@ +/* +This is the data migration script for the client secret hash updates. +The initial migration util/Migrator/DbScripts/2023-05-16_00_ClientSecretHash.sql should be run prior. +The final migration is in util/Migrator/DbScripts_future/2023-06-FutureMigration.sql. +*/ +IF COL_LENGTH('[dbo].[ApiKey]', 'ClientSecretHash') IS NOT NULL AND COL_LENGTH('[dbo].[ApiKey]', 'ClientSecret') IS NOT NULL +BEGIN + + -- Add index + IF NOT EXISTS(SELECT name FROM sys.indexes WHERE name = 'IX_ApiKey_ClientSecretHash') + BEGIN + CREATE NONCLUSTERED INDEX [IX_ApiKey_ClientSecretHash] + ON [dbo].[ApiKey]([ClientSecretHash] ASC) + WITH (ONLINE = ON) + END + + -- Data Migration + DECLARE @BatchSize INT = 10000 + WHILE @BatchSize > 0 + BEGIN + BEGIN TRANSACTION Migrate_ClientSecretHash + + UPDATE TOP(@BatchSize) [dbo].[ApiKey] + SET ClientSecretHash = ( + SELECT CAST(N'' AS XML).value('xs:base64Binary(sql:column("HASH"))', 'VARCHAR(128)') + FROM ( + SELECT HASHBYTES('SHA2_256', [ClientSecret]) AS HASH + ) SRC + ) + WHERE [ClientSecretHash] IS NULL + + SET @BatchSize = @@ROWCOUNT + + COMMIT TRANSACTION Migrate_ClientSecretHash + END + + -- Drop index + DROP INDEX IF EXISTS [IX_ApiKey_ClientSecretHash] + ON [dbo].[ApiKey]; + +END +GO diff --git a/util/Migrator/DbScripts_future/2023-06-FutureMigration.sql b/util/Migrator/DbScripts_future/2023-06-FutureMigration.sql new file mode 100644 index 0000000000..273c4625f1 --- /dev/null +++ b/util/Migrator/DbScripts_future/2023-06-FutureMigration.sql @@ -0,0 +1,65 @@ +-- Remove Column +IF COL_LENGTH('[dbo].[ApiKey]', 'ClientSecret') IS NOT NULL +BEGIN + ALTER TABLE + [dbo].[ApiKey] + DROP COLUMN + [ClientSecret] +END +GO + +-- Refresh views +IF OBJECT_ID('[dbo].[ApiKeyDetailsView]') IS NOT NULL + BEGIN + EXECUTE sp_refreshview N'[dbo].[ApiKeyDetailsView]'; + END +GO + +IF OBJECT_ID('[dbo].[ApiKeyView]') IS NOT NULL + BEGIN + EXECUTE sp_refreshview N'[dbo].[ApiKeyView]'; + END +GO + +CREATE OR ALTER PROCEDURE [dbo].[ApiKey_Create] + @Id UNIQUEIDENTIFIER OUTPUT, + @ServiceAccountId UNIQUEIDENTIFIER, + @Name VARCHAR(200), + @ClientSecretHash VARCHAR(128), + @Scope NVARCHAR(4000), + @EncryptedPayload NVARCHAR(4000), + @Key VARCHAR(MAX), + @ExpireAt DATETIME2(7), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7) +AS +BEGIN + SET NOCOUNT ON + + INSERT INTO [dbo].[ApiKey] + ( + [Id], + [ServiceAccountId], + [Name], + [ClientSecretHash], + [Scope], + [EncryptedPayload], + [Key], + [ExpireAt], + [CreationDate], + [RevisionDate] + ) + VALUES + ( + @Id, + @ServiceAccountId, + @Name, + @ClientSecretHash, + @Scope, + @EncryptedPayload, + @Key, + @ExpireAt, + @CreationDate, + @RevisionDate + ) +END diff --git a/util/MySqlMigrations/Migrations/20230523223530_ClientSecretHash.Designer.cs b/util/MySqlMigrations/Migrations/20230523223530_ClientSecretHash.Designer.cs new file mode 100644 index 0000000000..fb24afa59d --- /dev/null +++ b/util/MySqlMigrations/Migrations/20230523223530_ClientSecretHash.Designer.cs @@ -0,0 +1,2190 @@ +// +using System; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Bit.MySqlMigrations.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20230523223530_ClientSecretHash")] + partial class ClientSecretHash + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.12") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccessCode") + .HasMaxLength(25) + .HasColumnType("varchar(25)"); + + b.Property("Approved") + .HasColumnType("tinyint(1)"); + + b.Property("AuthenticationDate") + .HasColumnType("datetime(6)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("MasterPasswordHash") + .HasColumnType("longtext"); + + b.Property("PublicKey") + .HasColumnType("longtext"); + + b.Property("RequestDeviceIdentifier") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("RequestDeviceType") + .HasColumnType("tinyint unsigned"); + + b.Property("RequestIpAddress") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("ResponseDate") + .HasColumnType("datetime(6)"); + + b.Property("ResponseDeviceId") + .HasColumnType("char(36)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ResponseDeviceId"); + + b.HasIndex("UserId"); + + b.ToTable("AuthRequest", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.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", (string)null); + }); + + 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", (string)null); + }); + + 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", (string)null); + }); + + 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.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + 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", (string)null); + }); + + 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("DomainName") + .HasColumnType("longtext"); + + 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("SecretId") + .HasColumnType("char(36)"); + + b.Property("ServiceAccountId") + .HasColumnType("char(36)"); + + b.Property("SystemUser") + .HasColumnType("tinyint unsigned"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("Event", (string)null); + }); + + 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.Property("GroupId") + .HasColumnType("char(36)"); + + b.Property("OrganizationUserId") + .HasColumnType("char(36)"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("GroupUser", (string)null); + }); + + 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", (string)null); + }); + + 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("Status") + .HasColumnType("tinyint unsigned"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("longtext"); + + b.Property("Use2fa") + .HasColumnType("tinyint(1)"); + + b.Property("UseApi") + .HasColumnType("tinyint(1)"); + + b.Property("UseCustomPermissions") + .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("UseScim") + .HasColumnType("tinyint(1)"); + + b.Property("UseSecretsManager") + .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", (string)null); + }); + + 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", (string)null); + }); + + 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationDomain", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("DomainName") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("JobRunCount") + .HasColumnType("int"); + + b.Property("LastCheckedDate") + .HasColumnType("datetime(6)"); + + b.Property("NextRunDate") + .HasColumnType("datetime(6)"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("Txt") + .HasColumnType("longtext"); + + b.Property("VerifiedDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationDomain", (string)null); + }); + + 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("AccessAll") + .HasColumnType("tinyint(1)"); + + b.Property("AccessSecretsManager") + .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("smallint"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("OrganizationUser", (string)null); + }); + + 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Provider", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("BillingEmail") + .HasColumnType("longtext"); + + b.Property("BillingPhone") + .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("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UseEvents") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Provider", (string)null); + }); + + 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", (string)null); + }); + + 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", (string)null); + }); + + 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", (string)null); + }); + + 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", (string)null); + }); + + 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", (string)null); + }); + + 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("AvatarColor") + .HasMaxLength(7) + .HasColumnType("varchar(7)"); + + 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("KdfMemory") + .HasColumnType("int"); + + b.Property("KdfParallelism") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("LastEmailChangeDate") + .HasColumnType("datetime(6)"); + + b.Property("LastFailedLoginDate") + .HasColumnType("datetime(6)"); + + b.Property("LastKdfChangeDate") + .HasColumnType("datetime(6)"); + + b.Property("LastKeyRotationDate") + .HasColumnType("datetime(6)"); + + b.Property("LastPasswordChangeDate") + .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("UsesKeyConnector") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Read") + .HasColumnType("tinyint(1)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Write") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.ToTable("AccessPolicy", (string)null); + + b.HasDiscriminator("Discriminator").HasValue("AccessPolicy"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClientSecretHash") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("EncryptedPayload") + .HasMaxLength(4000) + .HasColumnType("varchar(4000)"); + + b.Property("ExpireAt") + .HasColumnType("datetime(6)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Scope") + .HasMaxLength(4000) + .HasColumnType("varchar(4000)"); + + b.Property("ServiceAccountId") + .HasColumnType("char(36)"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("ServiceAccountId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("DeletedDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Project", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("DeletedDate") + .HasColumnType("datetime(6)"); + + b.Property("Key") + .HasColumnType("longtext"); + + b.Property("Note") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .HasColumnType("longtext"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Secret", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("OrganizationId") + .HasColumnType("char(36)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ServiceAccount", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.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", (string)null); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.Property("ProjectsId") + .HasColumnType("char(36)"); + + b.Property("SecretsId") + .HasColumnType("char(36)"); + + b.HasKey("ProjectsId", "SecretsId"); + + b.HasIndex("SecretsId"); + + b.ToTable("ProjectSecret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedProjectId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedProjectId"); + + b.Property("ServiceAccountId") + .HasColumnType("char(36)") + .HasColumnName("ServiceAccountId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("ServiceAccountId"); + + b.HasDiscriminator().HasValue("service_account_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedProjectId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("char(36)") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Device", "ResponseDevice") + .WithMany() + .HasForeignKey("ResponseDeviceId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ResponseDevice"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.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.Auth.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.Auth.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.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Collections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.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.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.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("GroupUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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.OrganizationDomain", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Domains") + .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.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.SecretsManager.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.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.Vault.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedProject"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedProject"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("OrganizationUser"); + }); + + 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("Collections"); + + b.Navigation("Connections"); + + b.Navigation("Domains"); + + 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"); + + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("Folders"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/MySqlMigrations/Migrations/20230523223530_ClientSecretHash.cs b/util/MySqlMigrations/Migrations/20230523223530_ClientSecretHash.cs new file mode 100644 index 0000000000..289b6e1405 --- /dev/null +++ b/util/MySqlMigrations/Migrations/20230523223530_ClientSecretHash.cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Bit.MySqlMigrations.Migrations; + +public partial class ClientSecretHash : Migration +{ + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ClientSecret", + table: "ApiKey"); + + migrationBuilder.AddColumn( + name: "ClientSecretHash", + table: "ApiKey", + type: "varchar(128)", + maxLength: 128, + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ClientSecretHash", + table: "ApiKey"); + + migrationBuilder.AddColumn( + name: "ClientSecret", + table: "ApiKey", + type: "varchar(30)", + maxLength: 30, + nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"); + } +} diff --git a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs index e900c24fa3..95a769229f 100644 --- a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -1335,9 +1335,9 @@ namespace Bit.MySqlMigrations.Migrations b.Property("Id") .HasColumnType("char(36)"); - b.Property("ClientSecret") - .HasMaxLength(30) - .HasColumnType("varchar(30)"); + b.Property("ClientSecretHash") + .HasMaxLength(128) + .HasColumnType("varchar(128)"); b.Property("CreationDate") .HasColumnType("datetime(6)"); diff --git a/util/PostgresMigrations/Migrations/20230523223526_ClientSecretHash.Designer.cs b/util/PostgresMigrations/Migrations/20230523223526_ClientSecretHash.Designer.cs new file mode 100644 index 0000000000..ad04ff59be --- /dev/null +++ b/util/PostgresMigrations/Migrations/20230523223526_ClientSecretHash.Designer.cs @@ -0,0 +1,2201 @@ +// +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; + +#nullable disable + +namespace Bit.PostgresMigrations.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20230523223526_ClientSecretHash")] + partial class ClientSecretHash + { + 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("ProductVersion", "6.0.12") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessCode") + .HasMaxLength(25) + .HasColumnType("character varying(25)"); + + b.Property("Approved") + .HasColumnType("boolean"); + + b.Property("AuthenticationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("MasterPasswordHash") + .HasColumnType("text"); + + b.Property("PublicKey") + .HasColumnType("text"); + + b.Property("RequestDeviceIdentifier") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("RequestDeviceType") + .HasColumnType("smallint"); + + b.Property("RequestIpAddress") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("ResponseDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ResponseDeviceId") + .HasColumnType("uuid"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ResponseDeviceId"); + + b.HasIndex("UserId"); + + b.ToTable("AuthRequest", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.EmergencyAccess", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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 with time zone"); + + b.Property("RecoveryInitiatedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.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 with time zone"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("SsoConfig", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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 with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Collection", (string)null); + }); + + 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", (string)null); + }); + + 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.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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 with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Device", (string)null); + }); + + 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 with time zone"); + + b.Property("DeviceType") + .HasColumnType("smallint"); + + b.Property("DomainName") + .HasColumnType("text"); + + 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("SecretId") + .HasColumnType("uuid"); + + b.Property("ServiceAccountId") + .HasColumnType("uuid"); + + b.Property("SystemUser") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessAll") + .HasColumnType("boolean"); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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 with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Group", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.Property("GroupId") + .HasColumnType("uuid"); + + b.Property("OrganizationUserId") + .HasColumnType("uuid"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("GroupUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Installation", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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", (string)null); + }); + + 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 with time zone"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with 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 with 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 with time zone"); + + b.Property("Seats") + .HasColumnType("integer"); + + b.Property("SelfHost") + .HasColumnType("boolean"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("text"); + + b.Property("Use2fa") + .HasColumnType("boolean"); + + b.Property("UseApi") + .HasColumnType("boolean"); + + b.Property("UseCustomPermissions") + .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("UseScim") + .HasColumnType("boolean"); + + b.Property("UseSecretsManager") + .HasColumnType("boolean"); + + b.Property("UseSso") + .HasColumnType("boolean"); + + b.Property("UseTotp") + .HasColumnType("boolean"); + + b.Property("UsersGetPremium") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("Organization", (string)null); + }); + + 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 with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationApiKey", (string)null); + }); + + 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationDomain", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DomainName") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("JobRunCount") + .HasColumnType("integer"); + + b.Property("LastCheckedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("NextRunDate") + .HasColumnType("timestamp with time zone"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("Txt") + .HasColumnType("text"); + + b.Property("VerifiedDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationDomain", (string)null); + }); + + 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 with 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 with time zone"); + + b.HasKey("Id"); + + b.HasIndex("SponsoredOrganizationId"); + + b.HasIndex("SponsoringOrganizationId"); + + b.ToTable("OrganizationSponsorship", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessAll") + .HasColumnType("boolean"); + + b.Property("AccessSecretsManager") + .HasColumnType("boolean"); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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 with 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Policy", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Provider", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("BillingEmail") + .HasColumnType("text"); + + b.Property("BillingPhone") + .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 with time zone"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UseEvents") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("Provider", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderOrganization", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("ProviderId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Settings") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("ProviderId"); + + b.ToTable("ProviderOrganization", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderUser", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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 with 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccessCount") + .HasColumnType("integer"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("DeletionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Disabled") + .HasColumnType("boolean"); + + b.Property("ExpirationDate") + .HasColumnType("timestamp with 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 with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Send", (string)null); + }); + + 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("numeric"); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("AccountRevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("AvatarColor") + .HasMaxLength(7) + .HasColumnType("character varying(7)"); + + b.Property("CreationDate") + .HasColumnType("timestamp with 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("KdfMemory") + .HasColumnType("integer"); + + b.Property("KdfParallelism") + .HasColumnType("integer"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("LastEmailChangeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastFailedLoginDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastKdfChangeDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastKeyRotationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("LastPasswordChangeDate") + .HasColumnType("timestamp with 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 with time zone"); + + b.Property("PrivateKey") + .HasColumnType("text"); + + b.Property("PublicKey") + .HasColumnType("text"); + + b.Property("ReferenceData") + .HasColumnType("text"); + + b.Property("RenewalReminderDate") + .HasColumnType("timestamp with time zone"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with 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("UsesKeyConnector") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("Read") + .HasColumnType("boolean"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Write") + .HasColumnType("boolean"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.ToTable("AccessPolicy", (string)null); + + b.HasDiscriminator("Discriminator").HasValue("AccessPolicy"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientSecretHash") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("EncryptedPayload") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("ExpireAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Scope") + .HasMaxLength(4000) + .HasColumnType("character varying(4000)"); + + b.Property("ServiceAccountId") + .HasColumnType("uuid"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("ServiceAccountId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Project", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("DeletedDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Key") + .HasColumnType("text"); + + b.Property("Note") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Secret", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("OrganizationId") + .HasColumnType("uuid"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ServiceAccount", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("Attachments") + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Data") + .HasColumnType("text"); + + b.Property("DeletedDate") + .HasColumnType("timestamp with 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 with time zone"); + + b.Property("Type") + .HasColumnType("smallint"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Cipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Folder", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("RevisionDate") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Folder", (string)null); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.Property("ProjectsId") + .HasColumnType("uuid"); + + b.Property("SecretsId") + .HasColumnType("uuid"); + + b.HasKey("ProjectsId", "SecretsId"); + + b.HasIndex("SecretsId"); + + b.ToTable("ProjectSecret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedProjectId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedProjectId"); + + b.Property("ServiceAccountId") + .HasColumnType("uuid") + .HasColumnName("ServiceAccountId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("ServiceAccountId"); + + b.HasDiscriminator().HasValue("service_account_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedProjectId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Device", "ResponseDevice") + .WithMany() + .HasForeignKey("ResponseDeviceId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ResponseDevice"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.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.Auth.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.Auth.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.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Collections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.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.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.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("GroupUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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.OrganizationDomain", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Domains") + .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.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.SecretsManager.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.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.Vault.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedProject"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedProject"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("OrganizationUser"); + }); + + 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("Collections"); + + b.Navigation("Connections"); + + b.Navigation("Domains"); + + 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"); + + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("Folders"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/PostgresMigrations/Migrations/20230523223526_ClientSecretHash.cs b/util/PostgresMigrations/Migrations/20230523223526_ClientSecretHash.cs new file mode 100644 index 0000000000..8259b76dc2 --- /dev/null +++ b/util/PostgresMigrations/Migrations/20230523223526_ClientSecretHash.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Bit.PostgresMigrations.Migrations; + +public partial class ClientSecretHash : Migration +{ + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ClientSecret", + table: "ApiKey"); + + migrationBuilder.AddColumn( + name: "ClientSecretHash", + table: "ApiKey", + type: "character varying(128)", + maxLength: 128, + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ClientSecretHash", + table: "ApiKey"); + + migrationBuilder.AddColumn( + name: "ClientSecret", + table: "ApiKey", + type: "character varying(30)", + maxLength: 30, + nullable: true); + } +} diff --git a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs index 0d190a2805..c070e19106 100644 --- a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -1346,9 +1346,9 @@ namespace Bit.PostgresMigrations.Migrations b.Property("Id") .HasColumnType("uuid"); - b.Property("ClientSecret") - .HasMaxLength(30) - .HasColumnType("character varying(30)"); + b.Property("ClientSecretHash") + .HasMaxLength(128) + .HasColumnType("character varying(128)"); b.Property("CreationDate") .HasColumnType("timestamp with time zone"); diff --git a/util/SqliteMigrations/Migrations/20230523223522_ClientSecretHash.Designer.cs b/util/SqliteMigrations/Migrations/20230523223522_ClientSecretHash.Designer.cs new file mode 100644 index 0000000000..ab5211061b --- /dev/null +++ b/util/SqliteMigrations/Migrations/20230523223522_ClientSecretHash.Designer.cs @@ -0,0 +1,2188 @@ +// +using System; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Bit.SqliteMigrations.Migrations +{ + [DbContext(typeof(DatabaseContext))] + [Migration("20230523223522_ClientSecretHash")] + partial class ClientSecretHash + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.12"); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessCode") + .HasMaxLength(25) + .HasColumnType("TEXT"); + + b.Property("Approved") + .HasColumnType("INTEGER"); + + b.Property("AuthenticationDate") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("MasterPasswordHash") + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .HasColumnType("TEXT"); + + b.Property("RequestDeviceIdentifier") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("RequestDeviceType") + .HasColumnType("INTEGER"); + + b.Property("RequestIpAddress") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("ResponseDate") + .HasColumnType("TEXT"); + + b.Property("ResponseDeviceId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ResponseDeviceId"); + + b.HasIndex("UserId"); + + b.ToTable("AuthRequest", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.EmergencyAccess", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("GranteeId") + .HasColumnType("TEXT"); + + b.Property("GrantorId") + .HasColumnType("TEXT"); + + b.Property("KeyEncrypted") + .HasColumnType("TEXT"); + + b.Property("LastNotificationDate") + .HasColumnType("TEXT"); + + b.Property("RecoveryInitiatedDate") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("WaitTimeDays") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GranteeId"); + + b.HasIndex("GrantorId"); + + b.ToTable("EmergencyAccess", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.Grant", b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ConsumedDate") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ExpirationDate") + .HasColumnType("TEXT"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.HasKey("Key"); + + b.ToTable("Grant", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("SsoConfig", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.SsoUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("ExternalId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("SsoUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Collection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("CipherId") + .HasColumnType("TEXT"); + + b.HasKey("CollectionId", "CipherId"); + + b.HasIndex("CipherId"); + + b.ToTable("CollectionCipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("GroupId") + .HasColumnType("TEXT"); + + b.Property("HidePasswords") + .HasColumnType("INTEGER"); + + b.Property("ReadOnly") + .HasColumnType("INTEGER"); + + b.HasKey("CollectionId", "GroupId"); + + b.HasIndex("GroupId"); + + b.ToTable("CollectionGroups"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("OrganizationUserId") + .HasColumnType("TEXT"); + + b.Property("HidePasswords") + .HasColumnType("INTEGER"); + + b.Property("ReadOnly") + .HasColumnType("INTEGER"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PushToken") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Device", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Event", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ActingUserId") + .HasColumnType("TEXT"); + + b.Property("CipherId") + .HasColumnType("TEXT"); + + b.Property("CollectionId") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("DeviceType") + .HasColumnType("INTEGER"); + + b.Property("DomainName") + .HasColumnType("TEXT"); + + b.Property("GroupId") + .HasColumnType("TEXT"); + + b.Property("InstallationId") + .HasColumnType("TEXT"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("OrganizationUserId") + .HasColumnType("TEXT"); + + b.Property("PolicyId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("ProviderOrganizationId") + .HasColumnType("TEXT"); + + b.Property("ProviderUserId") + .HasColumnType("TEXT"); + + b.Property("SecretId") + .HasColumnType("TEXT"); + + b.Property("ServiceAccountId") + .HasColumnType("TEXT"); + + b.Property("SystemUser") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessAll") + .HasColumnType("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Group", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.Property("GroupId") + .HasColumnType("TEXT"); + + b.Property("OrganizationUserId") + .HasColumnType("TEXT"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.ToTable("GroupUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Installation", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasMaxLength(150) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Installation", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BillingEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("BusinessAddress1") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("BusinessAddress2") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("BusinessAddress3") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("BusinessCountry") + .HasMaxLength(2) + .HasColumnType("TEXT"); + + b.Property("BusinessName") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("BusinessTaxNumber") + .HasMaxLength(30) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("ExpirationDate") + .HasColumnType("TEXT"); + + b.Property("Gateway") + .HasColumnType("INTEGER"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("MaxAutoscaleSeats") + .HasColumnType("INTEGER"); + + b.Property("MaxCollections") + .HasColumnType("INTEGER"); + + b.Property("MaxStorageGb") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("OwnersNotifiedOfAutoscaling") + .HasColumnType("TEXT"); + + b.Property("Plan") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PlanType") + .HasColumnType("INTEGER"); + + b.Property("PrivateKey") + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .HasColumnType("TEXT"); + + b.Property("ReferenceData") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Seats") + .HasColumnType("INTEGER"); + + b.Property("SelfHost") + .HasColumnType("INTEGER"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Storage") + .HasColumnType("INTEGER"); + + b.Property("TwoFactorProviders") + .HasColumnType("TEXT"); + + b.Property("Use2fa") + .HasColumnType("INTEGER"); + + b.Property("UseApi") + .HasColumnType("INTEGER"); + + b.Property("UseCustomPermissions") + .HasColumnType("INTEGER"); + + b.Property("UseDirectory") + .HasColumnType("INTEGER"); + + b.Property("UseEvents") + .HasColumnType("INTEGER"); + + b.Property("UseGroups") + .HasColumnType("INTEGER"); + + b.Property("UseKeyConnector") + .HasColumnType("INTEGER"); + + b.Property("UsePolicies") + .HasColumnType("INTEGER"); + + b.Property("UseResetPassword") + .HasColumnType("INTEGER"); + + b.Property("UseScim") + .HasColumnType("INTEGER"); + + b.Property("UseSecretsManager") + .HasColumnType("INTEGER"); + + b.Property("UseSso") + .HasColumnType("INTEGER"); + + b.Property("UseTotp") + .HasColumnType("INTEGER"); + + b.Property("UsersGetPremium") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Organization", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ApiKey") + .HasMaxLength(30) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Config") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationConnection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationDomain", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("DomainName") + .HasMaxLength(255) + .HasColumnType("TEXT"); + + b.Property("JobRunCount") + .HasColumnType("INTEGER"); + + b.Property("LastCheckedDate") + .HasColumnType("TEXT"); + + b.Property("NextRunDate") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Txt") + .HasColumnType("TEXT"); + + b.Property("VerifiedDate") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationDomain", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("FriendlyName") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("LastSyncDate") + .HasColumnType("TEXT"); + + b.Property("OfferedToEmail") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("PlanSponsorshipType") + .HasColumnType("INTEGER"); + + b.Property("SponsoredOrganizationId") + .HasColumnType("TEXT"); + + b.Property("SponsoringOrganizationId") + .HasColumnType("TEXT"); + + b.Property("SponsoringOrganizationUserId") + .HasColumnType("TEXT"); + + b.Property("ToDelete") + .HasColumnType("INTEGER"); + + b.Property("ValidUntil") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("SponsoredOrganizationId"); + + b.HasIndex("SponsoringOrganizationId"); + + b.ToTable("OrganizationSponsorship", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessAll") + .HasColumnType("INTEGER"); + + b.Property("AccessSecretsManager") + .HasColumnType("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Permissions") + .HasColumnType("TEXT"); + + b.Property("ResetPasswordKey") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("OrganizationUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Policy", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Provider", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BillingEmail") + .HasColumnType("TEXT"); + + b.Property("BillingPhone") + .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("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UseEvents") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Provider", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderOrganization", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Settings") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("ProviderId"); + + b.ToTable("ProviderOrganization", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderUser", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Email") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("Permissions") + .HasColumnType("TEXT"); + + b.Property("ProviderId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ProviderId"); + + b.HasIndex("UserId"); + + b.ToTable("ProviderUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccessCount") + .HasColumnType("INTEGER"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("DeletionDate") + .HasColumnType("TEXT"); + + b.Property("Disabled") + .HasColumnType("INTEGER"); + + b.Property("ExpirationDate") + .HasColumnType("TEXT"); + + b.Property("HideEmail") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("MaxAccessCount") + .HasColumnType("INTEGER"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Password") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Send", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.TaxRate", b => + { + b.Property("Id") + .HasMaxLength(40) + .HasColumnType("TEXT"); + + b.Property("Active") + .HasColumnType("INTEGER"); + + b.Property("Country") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("PostalCode") + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.Property("Rate") + .HasColumnType("TEXT"); + + b.Property("State") + .HasMaxLength(2) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TaxRate", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Amount") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Details") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Gateway") + .HasColumnType("INTEGER"); + + b.Property("GatewayId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("PaymentMethodType") + .HasColumnType("INTEGER"); + + b.Property("Refunded") + .HasColumnType("INTEGER"); + + b.Property("RefundedAmount") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Transaction", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("AccountRevisionDate") + .HasColumnType("TEXT"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("TEXT"); + + b.Property("AvatarColor") + .HasMaxLength(7) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Culture") + .HasMaxLength(10) + .HasColumnType("TEXT"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.Property("EmailVerified") + .HasColumnType("INTEGER"); + + b.Property("EquivalentDomains") + .HasColumnType("TEXT"); + + b.Property("ExcludedGlobalEquivalentDomains") + .HasColumnType("TEXT"); + + b.Property("FailedLoginCount") + .HasColumnType("INTEGER"); + + b.Property("ForcePasswordReset") + .HasColumnType("INTEGER"); + + b.Property("Gateway") + .HasColumnType("INTEGER"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Kdf") + .HasColumnType("INTEGER"); + + b.Property("KdfIterations") + .HasColumnType("INTEGER"); + + b.Property("KdfMemory") + .HasColumnType("INTEGER"); + + b.Property("KdfParallelism") + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("LastEmailChangeDate") + .HasColumnType("TEXT"); + + b.Property("LastFailedLoginDate") + .HasColumnType("TEXT"); + + b.Property("LastKdfChangeDate") + .HasColumnType("TEXT"); + + b.Property("LastKeyRotationDate") + .HasColumnType("TEXT"); + + b.Property("LastPasswordChangeDate") + .HasColumnType("TEXT"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("MasterPassword") + .HasMaxLength(300) + .HasColumnType("TEXT"); + + b.Property("MasterPasswordHint") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("MaxStorageGb") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Premium") + .HasColumnType("INTEGER"); + + b.Property("PremiumExpirationDate") + .HasColumnType("TEXT"); + + b.Property("PrivateKey") + .HasColumnType("TEXT"); + + b.Property("PublicKey") + .HasColumnType("TEXT"); + + b.Property("ReferenceData") + .HasColumnType("TEXT"); + + b.Property("RenewalReminderDate") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("Storage") + .HasColumnType("INTEGER"); + + b.Property("TwoFactorProviders") + .HasColumnType("TEXT"); + + b.Property("TwoFactorRecoveryCode") + .HasMaxLength(32) + .HasColumnType("TEXT"); + + b.Property("UsesKeyConnector") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Read") + .HasColumnType("INTEGER"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Write") + .HasColumnType("INTEGER"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.ToTable("AccessPolicy", (string)null); + + b.HasDiscriminator("Discriminator").HasValue("AccessPolicy"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ClientSecretHash") + .HasMaxLength(128) + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("EncryptedPayload") + .HasMaxLength(4000) + .HasColumnType("TEXT"); + + b.Property("ExpireAt") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Scope") + .HasMaxLength(4000) + .HasColumnType("TEXT"); + + b.Property("ServiceAccountId") + .HasColumnType("TEXT"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("ServiceAccountId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("DeletedDate") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Project", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("DeletedDate") + .HasColumnType("TEXT"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("DeletedDate") + .HasAnnotation("SqlServer:Clustered", false); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("Secret", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.HasKey("Id") + .HasAnnotation("SqlServer:Clustered", true); + + b.HasIndex("OrganizationId") + .HasAnnotation("SqlServer:Clustered", false); + + b.ToTable("ServiceAccount", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("Attachments") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Data") + .HasColumnType("TEXT"); + + b.Property("DeletedDate") + .HasColumnType("TEXT"); + + b.Property("Favorites") + .HasColumnType("TEXT"); + + b.Property("Folders") + .HasColumnType("TEXT"); + + b.Property("OrganizationId") + .HasColumnType("TEXT"); + + b.Property("Reprompt") + .HasColumnType("INTEGER"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Cipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Folder", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Folder", (string)null); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.Property("ProjectsId") + .HasColumnType("TEXT"); + + b.Property("SecretsId") + .HasColumnType("TEXT"); + + b.HasKey("ProjectsId", "SecretsId"); + + b.HasIndex("SecretsId"); + + b.ToTable("ProjectSecret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedProjectId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("GroupId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GroupId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("GroupId"); + + b.HasDiscriminator().HasValue("group_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedProjectId"); + + b.Property("ServiceAccountId") + .HasColumnType("TEXT") + .HasColumnName("ServiceAccountId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("ServiceAccountId"); + + b.HasDiscriminator().HasValue("service_account_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedProjectId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedProjectId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedProjectId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_project"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.SecretsManager.Models.AccessPolicy"); + + b.Property("GrantedServiceAccountId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("GrantedServiceAccountId"); + + b.Property("OrganizationUserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("TEXT") + .HasColumnName("OrganizationUserId"); + + b.HasIndex("GrantedServiceAccountId"); + + b.HasIndex("OrganizationUserId"); + + b.HasDiscriminator().HasValue("user_service_account"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.Models.AuthRequest", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Device", "ResponseDevice") + .WithMany() + .HasForeignKey("ResponseDeviceId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ResponseDevice"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Auth.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.Auth.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.Auth.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.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Collections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Vault.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.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.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("GroupUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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.OrganizationDomain", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Domains") + .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.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.SecretsManager.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.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.Vault.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedProject"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("GroupAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", "GrantedProject") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedProject"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany("UserAccessPolicies") + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("OrganizationUser"); + }); + + 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("Collections"); + + b.Navigation("Connections"); + + b.Navigation("Domains"); + + 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"); + + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("Folders"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.SecretsManager.Models.ServiceAccount", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Vault.Models.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/SqliteMigrations/Migrations/20230523223522_ClientSecretHash.cs b/util/SqliteMigrations/Migrations/20230523223522_ClientSecretHash.cs new file mode 100644 index 0000000000..ea207b4d43 --- /dev/null +++ b/util/SqliteMigrations/Migrations/20230523223522_ClientSecretHash.cs @@ -0,0 +1,36 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Bit.SqliteMigrations.Migrations; + +public partial class ClientSecretHash : Migration +{ + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ClientSecret", + table: "ApiKey"); + + migrationBuilder.AddColumn( + name: "ClientSecretHash", + table: "ApiKey", + type: "TEXT", + maxLength: 128, + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ClientSecretHash", + table: "ApiKey"); + + migrationBuilder.AddColumn( + name: "ClientSecret", + table: "ApiKey", + type: "TEXT", + maxLength: 30, + nullable: true); + } +} diff --git a/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs index 81d292ef0f..076610ae31 100644 --- a/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -1333,8 +1333,8 @@ namespace Bit.SqliteMigrations.Migrations b.Property("Id") .HasColumnType("TEXT"); - b.Property("ClientSecret") - .HasMaxLength(30) + b.Property("ClientSecretHash") + .HasMaxLength(128) .HasColumnType("TEXT"); b.Property("CreationDate") From a4dc10c777ef5a6ac14bfb068097350e7c90ffe8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 21 Jun 2023 17:37:42 -0400 Subject: [PATCH 02/13] Bumped version to 2023.5.1 (#3035) Co-authored-by: bitwarden-devops-bot <106330231+bitwarden-devops-bot@users.noreply.github.com> --- Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 42e2935167..3e18ea953b 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,7 +3,7 @@ net6.0 - 2023.5.0 + 2023.5.1 Bit.$(MSBuildProjectName) true enable From 926d9bb5f20c42c3e82a65fa5f8ec2de907d8e10 Mon Sep 17 00:00:00 2001 From: Thomas Rittson <31796059+eliykat@users.noreply.github.com> Date: Thu, 22 Jun 2023 15:06:03 +1000 Subject: [PATCH 03/13] Run dbo_future migrations for OAVR v2 cleanup and PolicyService refactor (#3005) --- .../dbo/Functions/PolicyApplicableToUser.sql | 44 ---------------- .../Collection_CreateWithGroups.sql | 41 --------------- .../Collection_ReadWithGroupsById.sql | 17 ------- .../Collection_ReadWithGroupsByIdUserId.sql | 18 ------- .../Collection_UpdateWithGroups.sql | 51 ------------------- .../Policy_CountByTypeApplicableToUser.sql | 11 ---- .../Policy_ReadByTypeApplicableToUser.sql | 11 ---- ...3-06-07_00_DropUnusedCollectionSprocs.sql} | 0 .../2023-06-07_01_DropUnusedPolicySprocs.sql} | 0 9 files changed, 193 deletions(-) delete mode 100644 src/Sql/dbo/Functions/PolicyApplicableToUser.sql delete mode 100644 src/Sql/dbo/Stored Procedures/Collection_CreateWithGroups.sql delete mode 100644 src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsById.sql delete mode 100644 src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsByIdUserId.sql delete mode 100644 src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql delete mode 100644 src/Sql/dbo/Stored Procedures/Policy_CountByTypeApplicableToUser.sql delete mode 100644 src/Sql/dbo/Stored Procedures/Policy_ReadByTypeApplicableToUser.sql rename util/Migrator/{DbScripts_future/2022-11-FutureMigration.sql => DbScripts/2023-06-07_00_DropUnusedCollectionSprocs.sql} (100%) rename util/Migrator/{DbScripts_future/2023-03-FutureMigration.sql => DbScripts/2023-06-07_01_DropUnusedPolicySprocs.sql} (100%) diff --git a/src/Sql/dbo/Functions/PolicyApplicableToUser.sql b/src/Sql/dbo/Functions/PolicyApplicableToUser.sql deleted file mode 100644 index 9118360d71..0000000000 --- a/src/Sql/dbo/Functions/PolicyApplicableToUser.sql +++ /dev/null @@ -1,44 +0,0 @@ -CREATE FUNCTION [dbo].[PolicyApplicableToUser] -( - @UserId UNIQUEIDENTIFIER, - @PolicyType TINYINT, - @MinimumStatus SMALLINT -) -RETURNS TABLE -AS RETURN -SELECT - P.* -FROM - [dbo].[PolicyView] P -INNER JOIN - [dbo].[OrganizationUserView] OU ON P.[OrganizationId] = OU.[OrganizationId] -LEFT JOIN - (SELECT - PU.UserId, - PO.OrganizationId - FROM - [dbo].[ProviderUserView] PU - INNER JOIN - [ProviderOrganizationView] PO ON PO.[ProviderId] = PU.[ProviderId]) PUPO - ON PUPO.UserId = OU.UserId - AND PUPO.OrganizationId = P.OrganizationId -WHERE - ( - ( - OU.[Status] != 0 -- OrgUsers who have accepted their invite and are linked to a UserId - AND OU.[UserId] = @UserId - ) - OR ( - OU.[Status] = 0 -- 'Invited' OrgUsers are not linked to a UserId yet, so we have to look up their email - AND OU.[Email] IN (SELECT U.Email FROM [dbo].[UserView] U WHERE U.Id = @UserId) - ) - ) - AND P.[Type] = @PolicyType - AND P.[Enabled] = 1 - AND OU.[Status] >= @MinimumStatus - AND OU.[Type] >= 2 -- Not an owner (0) or admin (1) - AND ( -- Can't manage policies - OU.[Permissions] IS NULL - OR COALESCE(JSON_VALUE(OU.[Permissions], '$.managePolicies'), 'false') = 'false' - ) - AND PUPO.[UserId] IS NULL -- Not a provider diff --git a/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroups.sql b/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroups.sql deleted file mode 100644 index c577e1f02a..0000000000 --- a/src/Sql/dbo/Stored Procedures/Collection_CreateWithGroups.sql +++ /dev/null @@ -1,41 +0,0 @@ -CREATE PROCEDURE [dbo].[Collection_CreateWithGroups] - @Id UNIQUEIDENTIFIER, - @OrganizationId UNIQUEIDENTIFIER, - @Name VARCHAR(MAX), - @ExternalId NVARCHAR(300), - @CreationDate DATETIME2(7), - @RevisionDate DATETIME2(7), - @Groups AS [dbo].[SelectionReadOnlyArray] READONLY -AS -BEGIN - SET NOCOUNT ON - - EXEC [dbo].[Collection_Create] @Id, @OrganizationId, @Name, @ExternalId, @CreationDate, @RevisionDate - - ;WITH [AvailableGroupsCTE] AS( - SELECT - [Id] - FROM - [dbo].[Group] - WHERE - [OrganizationId] = @OrganizationId - ) - INSERT INTO [dbo].[CollectionGroup] - ( - [CollectionId], - [GroupId], - [ReadOnly], - [HidePasswords] - ) - SELECT - @Id, - [Id], - [ReadOnly], - [HidePasswords] - FROM - @Groups - WHERE - [Id] IN (SELECT [Id] FROM [AvailableGroupsCTE]) - - EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @OrganizationId -END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsById.sql b/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsById.sql deleted file mode 100644 index 4230dca985..0000000000 --- a/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsById.sql +++ /dev/null @@ -1,17 +0,0 @@ -CREATE PROCEDURE [dbo].[Collection_ReadWithGroupsById] - @Id UNIQUEIDENTIFIER -AS -BEGIN - SET NOCOUNT ON - - EXEC [dbo].[Collection_ReadById] @Id - - SELECT - [GroupId] [Id], - [ReadOnly], - [HidePasswords] - FROM - [dbo].[CollectionGroup] - WHERE - [CollectionId] = @Id -END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsByIdUserId.sql b/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsByIdUserId.sql deleted file mode 100644 index 7d30e777bd..0000000000 --- a/src/Sql/dbo/Stored Procedures/Collection_ReadWithGroupsByIdUserId.sql +++ /dev/null @@ -1,18 +0,0 @@ -CREATE PROCEDURE [dbo].[Collection_ReadWithGroupsByIdUserId] - @Id UNIQUEIDENTIFIER, - @UserId UNIQUEIDENTIFIER -AS -BEGIN - SET NOCOUNT ON - - EXEC [dbo].[Collection_ReadByIdUserId] @Id, @UserId - - SELECT - [GroupId] [Id], - [ReadOnly], - [HidePasswords] - FROM - [dbo].[CollectionGroup] - WHERE - [CollectionId] = @Id -END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql b/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql deleted file mode 100644 index b0bfba442b..0000000000 --- a/src/Sql/dbo/Stored Procedures/Collection_UpdateWithGroups.sql +++ /dev/null @@ -1,51 +0,0 @@ -CREATE PROCEDURE [dbo].[Collection_UpdateWithGroups] - @Id UNIQUEIDENTIFIER, - @OrganizationId UNIQUEIDENTIFIER, - @Name VARCHAR(MAX), - @ExternalId NVARCHAR(300), - @CreationDate DATETIME2(7), - @RevisionDate DATETIME2(7), - @Groups AS [dbo].[SelectionReadOnlyArray] READONLY -AS -BEGIN - SET NOCOUNT ON - - EXEC [dbo].[Collection_Update] @Id, @OrganizationId, @Name, @ExternalId, @CreationDate, @RevisionDate - - ;WITH [AvailableGroupsCTE] AS( - SELECT - Id - FROM - [dbo].[Group] - WHERE - OrganizationId = @OrganizationId - ) - MERGE - [dbo].[CollectionGroup] AS [Target] - USING - @Groups AS [Source] - ON - [Target].[CollectionId] = @Id - AND [Target].[GroupId] = [Source].[Id] - WHEN NOT MATCHED BY TARGET - AND [Source].[Id] IN (SELECT [Id] FROM [AvailableGroupsCTE]) THEN - INSERT VALUES - ( - @Id, - [Source].[Id], - [Source].[ReadOnly], - [Source].[HidePasswords] - ) - WHEN MATCHED AND ( - [Target].[ReadOnly] != [Source].[ReadOnly] - OR [Target].[HidePasswords] != [Source].[HidePasswords] - ) THEN - UPDATE SET [Target].[ReadOnly] = [Source].[ReadOnly], - [Target].[HidePasswords] = [Source].[HidePasswords] - WHEN NOT MATCHED BY SOURCE - AND [Target].[CollectionId] = @Id THEN - DELETE - ; - - EXEC [dbo].[User_BumpAccountRevisionDateByCollectionId] @Id, @OrganizationId -END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Policy_CountByTypeApplicableToUser.sql b/src/Sql/dbo/Stored Procedures/Policy_CountByTypeApplicableToUser.sql deleted file mode 100644 index 3577c0e3de..0000000000 --- a/src/Sql/dbo/Stored Procedures/Policy_CountByTypeApplicableToUser.sql +++ /dev/null @@ -1,11 +0,0 @@ -CREATE PROCEDURE [dbo].[Policy_CountByTypeApplicableToUser] - @UserId UNIQUEIDENTIFIER, - @PolicyType TINYINT, - @MinimumStatus SMALLINT -AS -BEGIN - SET NOCOUNT ON - - SELECT COUNT(1) - FROM [dbo].[PolicyApplicableToUser](@UserId, @PolicyType, @MinimumStatus) -END diff --git a/src/Sql/dbo/Stored Procedures/Policy_ReadByTypeApplicableToUser.sql b/src/Sql/dbo/Stored Procedures/Policy_ReadByTypeApplicableToUser.sql deleted file mode 100644 index 5f215f99d4..0000000000 --- a/src/Sql/dbo/Stored Procedures/Policy_ReadByTypeApplicableToUser.sql +++ /dev/null @@ -1,11 +0,0 @@ -CREATE PROCEDURE [dbo].[Policy_ReadByTypeApplicableToUser] - @UserId UNIQUEIDENTIFIER, - @PolicyType TINYINT, - @MinimumStatus SMALLINT -AS -BEGIN - SET NOCOUNT ON - - SELECT * - FROM [dbo].[PolicyApplicableToUser](@UserId, @PolicyType, @MinimumStatus) -END diff --git a/util/Migrator/DbScripts_future/2022-11-FutureMigration.sql b/util/Migrator/DbScripts/2023-06-07_00_DropUnusedCollectionSprocs.sql similarity index 100% rename from util/Migrator/DbScripts_future/2022-11-FutureMigration.sql rename to util/Migrator/DbScripts/2023-06-07_00_DropUnusedCollectionSprocs.sql diff --git a/util/Migrator/DbScripts_future/2023-03-FutureMigration.sql b/util/Migrator/DbScripts/2023-06-07_01_DropUnusedPolicySprocs.sql similarity index 100% rename from util/Migrator/DbScripts_future/2023-03-FutureMigration.sql rename to util/Migrator/DbScripts/2023-06-07_01_DropUnusedPolicySprocs.sql From a6ffadf086273b916a6bbb6a8131a50739f7006d Mon Sep 17 00:00:00 2001 From: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com> Date: Thu, 22 Jun 2023 20:27:59 -0400 Subject: [PATCH 04/13] PM-2731 - DevicesController.cs - Add new method GetExistenceByTypes (#3039) * PM-2731 - DevicesController.cs - Add new method HasDevicesOfTypes to accept an array of DeviceType values and return a boolean if the authN user has at least a device of one of the given types. * Dotnet format to pass lint rules * PM-2731 - Update naming of HasDevicesOfTypes to be GetExistenceByTypes for increased clarity per PR feedback. * PM-2731-Make GetExistenceByTypes route singular * Update src/Api/Controllers/DevicesController.cs to use var Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com> --------- Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com> --- src/Api/Controllers/DevicesController.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Api/Controllers/DevicesController.cs b/src/Api/Controllers/DevicesController.cs index 7559bff9bc..88d0e5c7a3 100644 --- a/src/Api/Controllers/DevicesController.cs +++ b/src/Api/Controllers/DevicesController.cs @@ -1,6 +1,7 @@ using Bit.Api.Models.Request; using Bit.Api.Models.Response; using Bit.Core.Entities; +using Bit.Core.Enums; using Bit.Core.Exceptions; using Bit.Core.Repositories; using Bit.Core.Services; @@ -65,6 +66,15 @@ public class DevicesController : Controller return new ListResponseModel(responses); } + [HttpPost("exist-by-types")] + public async Task> GetExistenceByTypes([FromBody] DeviceType[] deviceTypes) + { + var userId = _userService.GetProperUserId(User).Value; + var devices = await _deviceRepository.GetManyByUserIdAsync(userId); + var userHasDeviceOfTypes = devices.Any(d => deviceTypes.Contains(d.Type)); + return Ok(userHasDeviceOfTypes); + } + [HttpPost("")] public async Task Post([FromBody] DeviceRequestModel model) { From 3522d8b084d95df068f4b1c4784118194ce0826b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 23 Jun 2023 09:23:47 +0200 Subject: [PATCH 05/13] [DEVOPS-1204] Migrate unified & it's build pipeline to self-host repo (#2988) * Remove build self host workflow * Remove docker-unified folder * Add trigger for self host build in separate repo * Change branch * Fix --- .github/workflows/build-self-host.yml | 188 ------------ .github/workflows/build.yml | 33 ++ docker-unified/.env.example | 3 - docker-unified/Dockerfile | 283 ------------------ docker-unified/docker-compose.yml | 56 ---- docker-unified/entrypoint.sh | 108 ------- docker-unified/hbs/app-id.hbs | 15 - docker-unified/hbs/config.yaml | 7 - docker-unified/hbs/nginx-config.hbs | 196 ------------ docker-unified/nginx/logrotate.sh | 15 - docker-unified/nginx/mime.types | 138 --------- docker-unified/nginx/nginx.conf | 147 --------- docker-unified/nginx/proxy.conf | 27 -- .../nginx/security-headers-ssl.conf | 2 - docker-unified/nginx/security-headers.conf | 3 - docker-unified/settings.env | 69 ----- docker-unified/supervisord/admin.ini | 9 - docker-unified/supervisord/api.ini | 9 - docker-unified/supervisord/events.ini | 9 - docker-unified/supervisord/icons.ini | 9 - docker-unified/supervisord/identity.ini | 10 - docker-unified/supervisord/nginx.ini | 7 - docker-unified/supervisord/notifications.ini | 9 - docker-unified/supervisord/scim.ini | 9 - docker-unified/supervisord/sso.ini | 9 - docker-unified/supervisord/supervisord.conf | 15 - 26 files changed, 33 insertions(+), 1352 deletions(-) delete mode 100644 .github/workflows/build-self-host.yml delete mode 100644 docker-unified/.env.example delete mode 100644 docker-unified/Dockerfile delete mode 100644 docker-unified/docker-compose.yml delete mode 100755 docker-unified/entrypoint.sh delete mode 100644 docker-unified/hbs/app-id.hbs delete mode 100644 docker-unified/hbs/config.yaml delete mode 100644 docker-unified/hbs/nginx-config.hbs delete mode 100644 docker-unified/nginx/logrotate.sh delete mode 100644 docker-unified/nginx/mime.types delete mode 100644 docker-unified/nginx/nginx.conf delete mode 100644 docker-unified/nginx/proxy.conf delete mode 100644 docker-unified/nginx/security-headers-ssl.conf delete mode 100644 docker-unified/nginx/security-headers.conf delete mode 100644 docker-unified/settings.env delete mode 100644 docker-unified/supervisord/admin.ini delete mode 100644 docker-unified/supervisord/api.ini delete mode 100644 docker-unified/supervisord/events.ini delete mode 100644 docker-unified/supervisord/icons.ini delete mode 100644 docker-unified/supervisord/identity.ini delete mode 100644 docker-unified/supervisord/nginx.ini delete mode 100644 docker-unified/supervisord/notifications.ini delete mode 100644 docker-unified/supervisord/scim.ini delete mode 100644 docker-unified/supervisord/sso.ini delete mode 100644 docker-unified/supervisord/supervisord.conf diff --git a/.github/workflows/build-self-host.yml b/.github/workflows/build-self-host.yml deleted file mode 100644 index 989c605b11..0000000000 --- a/.github/workflows/build-self-host.yml +++ /dev/null @@ -1,188 +0,0 @@ ---- -name: Build Self-Host - -on: - push: - branches-ignore: - - "l10n_master" - - "gh-pages" - paths-ignore: - - ".github/workflows/**" - workflow_dispatch: - pull_request: - branches-ignore: - - "l10n_master" - - "gh-pages" - paths: - - ".github/workflows/build-self-host.yml" - -jobs: - build-docker: - name: Build Docker image - runs-on: ubuntu-22.04 - steps: - - name: Checkout repo - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 - - - name: Check Branch to Publish - env: - PUBLISH_BRANCHES: "master,rc,hotfix-rc" - id: publish-branch-check - run: | - IFS="," read -a publish_branches <<< $PUBLISH_BRANCHES - - if [[ " ${publish_branches[*]} " =~ " ${GITHUB_REF:11} " ]]; then - echo "is_publish_branch=true" >> $GITHUB_ENV - else - echo "is_publish_branch=false" >> $GITHUB_ENV - fi - - ########## Set up Docker ########## - - name: Set up QEMU emulators - uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0 - - ########## Login to Docker registries ########## - - name: Login to Azure - QA Subscription - uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 - with: - creds: ${{ secrets.AZURE_QA_KV_CREDENTIALS }} - - - name: Login to Azure ACR - run: az acr login -n bitwardenqa - - - name: Login to Azure - Prod Subscription - uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 - with: - creds: ${{ secrets.AZURE_PROD_KV_CREDENTIALS }} - - - name: Login to Azure ACR - run: az acr login -n bitwardenprod - - - name: Login to Azure - CI Subscription - uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 - with: - creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - - - name: Retrieve github PAT secrets - id: retrieve-secret-pat - uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b - with: - keyvault: "bitwarden-ci" - secrets: "github-pat-bitwarden-devops-bot-repo-scope" - - - name: Retrieve secrets - if: ${{ env.is_publish_branch == 'true' }} - id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b - with: - keyvault: "bitwarden-ci" - secrets: "docker-password, - docker-username, - dct-delegate-2-repo-passphrase, - dct-delegate-2-key" - - - name: Log into Docker - if: ${{ env.is_publish_branch == 'true' }} - env: - DOCKER_USERNAME: ${{ steps.retrieve-secrets.outputs.docker-username }} - DOCKER_PASSWORD: ${{ steps.retrieve-secrets.outputs.docker-password }} - run: echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin - - - name: Setup Docker Trust - if: ${{ env.is_publish_branch == 'true' }} - env: - DCT_DELEGATION_KEY_ID: "c9bde8ec820701516491e5e03d3a6354e7bd66d05fa3df2b0062f68b116dc59c" - DCT_DELEGATE_KEY: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-key }} - DCT_REPO_PASSPHRASE: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-repo-passphrase }} - run: | - mkdir -p ~/.docker/trust/private - echo "$DCT_DELEGATE_KEY" > ~/.docker/trust/private/$DCT_DELEGATION_KEY_ID.key - echo "DOCKER_CONTENT_TRUST=1" >> $GITHUB_ENV - echo "DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=$DCT_REPO_PASSPHRASE" >> $GITHUB_ENV - - ########## Generate image tag and build Docker image ########## - - name: Generate Docker image tag - id: tag - run: | - IMAGE_TAG=$(echo "${GITHUB_REF:11}" | sed "s#/#-#g") # slash safe branch name - if [[ "$IMAGE_TAG" == "master" ]]; then - IMAGE_TAG=dev - elif [[ "$IMAGE_TAG" == "rc" ]] || [[ "$IMAGE_TAG" == "hotfix-rc" ]]; then - IMAGE_TAG=beta - fi - - echo "image_tag=$IMAGE_TAG" >> $GITHUB_OUTPUT - - - name: Generate tag list - id: tag-list - env: - IMAGE_TAG: ${{ steps.tag.outputs.image_tag }} - run: | - if [ "$IMAGE_TAG" = "dev" ] || [ "$IMAGE_TAG" = "beta" ]; then - echo "tags=bitwardenqa.azurecr.io/self-host:${IMAGE_TAG},bitwardenprod.azurecr.io/self-host:${IMAGE_TAG},bitwarden/self-host:${IMAGE_TAG}" >> $GITHUB_OUTPUT - else - echo "tags=bitwardenqa.azurecr.io/self-host:${IMAGE_TAG},bitwardenprod.azurecr.io/self-host:${IMAGE_TAG}" >> $GITHUB_OUTPUT - fi - - - name: Build Docker image - uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671 # v3.2.0 - with: - context: . - file: docker-unified/Dockerfile - platforms: | - linux/amd64, - linux/arm/v7, - linux/arm64/v8 - push: true - tags: ${{ steps.tag-list.outputs.tags }} - secrets: | - "GH_PAT=${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }}" - - - name: Log out of Docker and disable Docker Notary - if: ${{ env.is_publish_branch == 'true' }} - run: | - docker logout - echo "DOCKER_CONTENT_TRUST=0" >> $GITHUB_ENV - - check-failures: - name: Check for failures - if: always() - runs-on: ubuntu-22.04 - needs: build-docker - steps: - - name: Check if any job failed - if: | - github.ref == 'refs/heads/master' - || github.ref == 'refs/heads/rc' - || github.ref == 'refs/heads/hotfix-rc' - env: - BUILD_DOCKER_STATUS: ${{ needs.build-docker.result }} - run: | - if [ "$BUILD_DOCKER_STATUS" = "failure" ]; then - exit 1 - fi - - - name: Login to Azure - CI subscription - uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 - if: failure() - with: - creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - - - name: Retrieve secrets - id: retrieve-secrets - uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b - if: failure() - with: - keyvault: "bitwarden-ci" - secrets: "devops-alerts-slack-webhook-url" - - - name: Notify Slack on failure - uses: act10ns/slack@ed1309ab9862e57e9e583e51c7889486b9a00b0f # v2.0.0 - if: failure() - env: - SLACK_WEBHOOK_URL: ${{ steps.retrieve-secrets.outputs.devops-alerts-slack-webhook-url }} - with: - status: ${{ job.status }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf55ceab0e..32856df6ef 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -528,6 +528,39 @@ jobs: path: util/MsSqlMigratorUtility/obj/build-output/publish/MsSqlMigratorUtility if-no-files-found: error + trigger-self-host-build: + name: Trigger self-host build + runs-on: ubuntu-22.04 + needs: + - build-docker + steps: + - name: Login to Azure - CI Subscription + uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 + with: + creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + + - name: Retrieve github PAT secrets + id: retrieve-secret-pat + uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b + with: + keyvault: "bitwarden-ci" + secrets: "github-pat-bitwarden-devops-bot-repo-scope" + + - name: Trigger self-host build + uses: actions/github-script@v6 + with: + github-token: ${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }} + script: | + await github.rest.actions.createWorkflowDispatch({ + owner: 'bitwarden', + repo: 'self-host', + workflow_id: 'build-self-host.yml', + ref: 'DEVOPS-1204-Migrate_Build_pipeline_to_self-host_repo', + inputs: { + server_branch: '${{ github.ref }}' + } + }) + check-failures: name: Check for failures if: always() diff --git a/docker-unified/.env.example b/docker-unified/.env.example deleted file mode 100644 index 06a987dc1c..0000000000 --- a/docker-unified/.env.example +++ /dev/null @@ -1,3 +0,0 @@ -COMPOSE_PROJECT_NAME=bitwarden -REGISTRY=bitwarden -TAG=dev diff --git a/docker-unified/Dockerfile b/docker-unified/Dockerfile deleted file mode 100644 index a01a3d397d..0000000000 --- a/docker-unified/Dockerfile +++ /dev/null @@ -1,283 +0,0 @@ -# syntax = docker/dockerfile:1.2 -############################################### -# Build stage # -############################################### -FROM --platform=$BUILDPLATFORM debian AS web-setup - -# Add packages -RUN apt-get update && apt-get install -y \ - curl \ - jq \ - unzip \ - && rm -rf /var/lib/apt/lists/* - -WORKDIR /tmp - -# Download tags from 'clients' repository -RUN --mount=type=secret,id=GH_PAT,target=/etc/secrets/GH_PAT if [ -e "/etc/secrets/GH_PAT" ]; then \ -curl --header "Authorization: token $(cat /etc/secrets/GH_PAT)" \ - https://api.github.com/repos/bitwarden/clients/git/refs/tags --output tags.json ; else \ - curl https://api.github.com/repos/bitwarden/clients/git/refs/tags --output tags.json ; fi - -RUN cat tags.json - -# Grab last tag/release of the 'web' client -RUN cat tags.json | jq -r 'last(.[] | select(.ref|test("refs/tags/web-v[0-9]{4}.[0-9]{1,2}.[0-9]+"))) | .ref | split("/")[2]' > tag.txt - -# Extract the version of the 'web' client -RUN cat tag.txt | grep -o -E "[0-9]{4}\.[0-9]{1,2}\.[0-9]+" > version.txt - -# Download the built release artifact for the 'web' client -RUN TAG=$(cat tag.txt) \ - && VERSION=$(cat version.txt) \ - && curl -L https://github.com/bitwarden/clients/releases/download/$TAG/web-$VERSION-selfhosted-COMMERCIAL.zip -O - -# Unzip the 'web' client to /tmp/build -RUN VERSION=$(cat version.txt) \ - && unzip web-$VERSION-selfhosted-COMMERCIAL.zip - -############################################### -# Build stage # -############################################### -FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:6.0 AS dotnet-build - -# Docker buildx supplies the value for this arg -ARG TARGETPLATFORM - -# Determine proper runtime value for .NET -# We put the value in a file to be read by later layers. -RUN if [ "$TARGETPLATFORM" = "linux/amd64" ]; then \ - RID=linux-x64 ; \ - elif [ "$TARGETPLATFORM" = "linux/arm64" ]; then \ - RID=linux-arm64 ; \ - elif [ "$TARGETPLATFORM" = "linux/arm/v7" ]; then \ - RID=linux-arm ; \ - fi \ - && echo "RID=$RID" > /tmp/rid.txt - -# Add packages -RUN apt-get update && apt-get install -y \ - npm \ - && rm -rf /var/lib/apt/lists/* - -RUN npm install -g gulp - -# Copy csproj files as distinct layers -WORKDIR /source -COPY src/Admin/*.csproj ./src/Admin/ -COPY src/Api/*.csproj ./src/Api/ -COPY src/Events/*.csproj ./src/Events/ -COPY src/Icons/*.csproj ./src/Icons/ -COPY src/Identity/*.csproj ./src/Identity/ -COPY src/Notifications/*.csproj ./src/Notifications/ -COPY bitwarden_license/src/Sso/*.csproj ./bitwarden_license/src/Sso/ -COPY bitwarden_license/src/Scim/*.csproj ./bitwarden_license/src/Scim/ -COPY src/Core/*.csproj ./src/Core/ -COPY src/Infrastructure.Dapper/*.csproj ./src/Infrastructure.Dapper/ -COPY src/Infrastructure.EntityFramework/*.csproj ./src/Infrastructure.EntityFramework/ -COPY src/SharedWeb/*.csproj ./src/SharedWeb/ -COPY util/Migrator/*.csproj ./util/Migrator/ -COPY util/MySqlMigrations/*.csproj ./util/MySqlMigrations/ -COPY util/PostgresMigrations/*.csproj ./util/PostgresMigrations/ -COPY util/SqliteMigrations/*.csproj ./util/SqliteMigrations/ -COPY bitwarden_license/src/Commercial.Core/*.csproj ./bitwarden_license/src/Commercial.Core/ -COPY bitwarden_license/src/Commercial.Infrastructure.EntityFramework/*.csproj ./bitwarden_license/src/Commercial.Infrastructure.EntityFramework/ -COPY Directory.Build.props . - -# Restore Admin project dependencies and tools -WORKDIR /source/src/Admin -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Api project dependencies and tools -WORKDIR /source/src/Api -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Events project dependencies and tools -WORKDIR /source/src/Events -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Icons project dependencies and tools -WORKDIR /source/src/Icons -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Identity project dependencies and tools -WORKDIR /source/src/Identity -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Notifications project dependencies and tools -WORKDIR /source/src/Notifications -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Sso project dependencies and tools -WORKDIR /source/bitwarden_license/src/Sso -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Restore Scim project dependencies and tools -WORKDIR /source/bitwarden_license/src/Scim -RUN . /tmp/rid.txt && dotnet restore -r $RID - -# Copy required project files -WORKDIR /source -COPY src/Admin/. ./src/Admin/ -COPY src/Api/. ./src/Api/ -COPY src/Events/. ./src/Events/ -COPY src/Icons/. ./src/Icons/ -COPY src/Identity/. ./src/Identity/ -COPY src/Notifications/. ./src/Notifications/ -COPY bitwarden_license/src/Sso/. ./bitwarden_license/src/Sso/ -COPY bitwarden_license/src/Scim/. ./bitwarden_license/src/Scim/ -COPY src/Core/. ./src/Core/ -COPY src/Infrastructure.Dapper/. ./src/Infrastructure.Dapper/ -COPY src/Infrastructure.EntityFramework/. ./src/Infrastructure.EntityFramework/ -COPY src/SharedWeb/. ./src/SharedWeb/ -COPY util/Migrator/. ./util/Migrator/ -COPY util/MySqlMigrations/. ./util/MySqlMigrations/ -COPY util/PostgresMigrations/. ./util/PostgresMigrations/ -COPY util/SqliteMigrations/. ./util/SqliteMigrations/ -COPY util/EfShared/. ./util/EfShared/ -COPY bitwarden_license/src/Commercial.Core/. ./bitwarden_license/src/Commercial.Core/ -COPY bitwarden_license/src/Commercial.Infrastructure.EntityFramework/. ./bitwarden_license/src/Commercial.Infrastructure.EntityFramework/ -COPY .git/. ./.git/ - -# Build Admin app -WORKDIR /source/src/Admin -RUN npm install -RUN gulp --gulpfile "gulpfile.js" build -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Admin --no-restore --no-self-contained -r $RID - -# Build Api app -WORKDIR /source/src/Api -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Api --no-restore --no-self-contained -r $RID - -# Build Events app -WORKDIR /source/src/Events -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Events --no-restore --no-self-contained -r $RID - -# Build Icons app -WORKDIR /source/src/Icons -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Icons --no-restore --no-self-contained -r $RID - -# Build Identity app -WORKDIR /source/src/Identity -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Identity --no-restore --no-self-contained -r $RID - -# Build Notifications app -WORKDIR /source/src/Notifications -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Notifications --no-restore --no-self-contained -r $RID - -# Build Sso app -WORKDIR /source/bitwarden_license/src/Sso -RUN npm install -RUN gulp --gulpfile "gulpfile.js" build -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Sso --no-restore --no-self-contained -r $RID - -# Build Scim app -WORKDIR /source/bitwarden_license/src/Scim -RUN . /tmp/rid.txt && dotnet publish -c release -o /app/Scim --no-restore --no-self-contained -r $RID - -############################################### -# App stage # -############################################### -FROM mcr.microsoft.com/dotnet/aspnet:6.0 -ARG TARGETPLATFORM -LABEL com.bitwarden.product="bitwarden" -LABEL com.bitwarden.project="unified" -ENV ASPNETCORE_ENVIRONMENT=Production -ENV BW_ENABLE_ADMIN=true -ENV BW_ENABLE_API=true -ENV BW_ENABLE_EVENTS=false -ENV BW_ENABLE_ICONS=true -ENV BW_ENABLE_IDENTITY=true -ENV BW_ENABLE_NOTIFICATIONS=true -ENV BW_ENABLE_SCIM=false -ENV BW_ENABLE_SSO=false -ENV BW_DB_FILE="/etc/bitwarden/vault.db" -ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false -ENV globalSettings__selfHosted="true" -ENV globalSettings__unifiedDeployment="true" -ENV globalSettings__pushRelayBaseUri="https://push.bitwarden.com" -ENV globalSettings__baseServiceUri__internalAdmin="http://localhost:5000" -ENV globalSettings__baseServiceUri__internalApi="http://localhost:5001" -ENV globalSettings__baseServiceUri__internalEvents="http://localhost:5003" -ENV globalSettings__baseServiceUri__internalIcons="http://localhost:5004" -ENV globalSettings__baseServiceUri__internalIdentity="http://localhost:5005" -ENV globalSettings__baseServiceUri__internalNotifications="http://localhost:5006" -ENV globalSettings__baseServiceUri__internalSso="http://localhost:5007" -ENV globalSettings__baseServiceUri__internalScim="http://localhost:5002" -ENV globalSettings__baseServiceUri__internalVault="http://localhost:8080" -ENV globalSettings__identityServer__certificatePassword="default_cert_password" -ENV globalSettings__dataProtection__directory="/etc/bitwarden/data-protection" -ENV globalSettings__attachment__baseDirectory="/etc/bitwarden/attachments" -ENV globalSettings__send__baseDirectory="/etc/bitwarden/attachments/send" -ENV globalSettings__licenseDirectory="/etc/bitwarden/licenses" -ENV globalSettings__logDirectoryByProject="false" -ENV globalSettings__logRollBySizeLimit="1073741824" - -# Add packages -RUN apt-get update && apt-get install -y \ - curl \ - nginx \ - openssl \ - supervisor \ - tzdata \ - unzip \ - && rm -rf /var/lib/apt/lists/* - -# Create required directories -RUN mkdir -p /etc/bitwarden/attachments/send -RUN mkdir -p /etc/bitwarden/data-protection -RUN mkdir -p /etc/bitwarden/licenses -RUN mkdir -p /etc/bitwarden/logs -RUN mkdir -p /etc/supervisor -RUN mkdir -p /etc/supervisor.d -RUN mkdir -p /var/log/bitwarden -RUN mkdir -p /var/log/nginx/logs -RUN mkdir -p /etc/nginx/http.d -RUN mkdir -p /var/run/nginx -RUN mkdir -p /var/lib/nginx/tmp -RUN touch /var/run/nginx/nginx.pid -RUN mkdir -p /app - -# Copy all apps from dotnet-build stage -WORKDIR /app -COPY --from=dotnet-build /app ./ - -# Copy Web files from web-setup stage -COPY --from=web-setup /tmp/build /app/Web - -# Set up supervisord -COPY docker-unified/supervisord/*.ini /etc/supervisor.d/ -COPY docker-unified/supervisord/supervisord.conf /etc/supervisor/supervisord.conf -RUN rm -f /etc/supervisord.conf - -# Set up nginx -COPY docker-unified/nginx/nginx.conf /etc/nginx -COPY docker-unified/nginx/proxy.conf /etc/nginx -COPY docker-unified/nginx/mime.types /etc/nginx -COPY docker-unified/nginx/security-headers.conf /etc/nginx -COPY docker-unified/nginx/security-headers-ssl.conf /etc/nginx -COPY docker-unified/nginx/logrotate.sh / -RUN chmod +x /logrotate.sh - -# Copy configuration templates -COPY docker-unified/hbs/nginx-config.hbs /etc/hbs/ -COPY docker-unified/hbs/app-id.hbs /etc/hbs/ -COPY docker-unified/hbs/config.yaml /etc/hbs/ - -# Download hbs tool for generating final configurations -RUN if [ "$TARGETPLATFORM" = "linux/amd64" ] ; then curl -L --output hbs.zip https://github.com/bitwarden/Handlebars.conf/releases/download/v1.3.0/hbs_linux-x64_dotnet.zip; fi -RUN if [ "$TARGETPLATFORM" = "linux/arm/v7" ] ; then curl -L --output hbs.zip https://github.com/bitwarden/Handlebars.conf/releases/download/v1.3.0/hbs_linux-armv7_dotnet.zip; fi -RUN if [ "$TARGETPLATFORM" = "linux/arm64" ] ; then curl -L --output hbs.zip https://github.com/bitwarden/Handlebars.conf/releases/download/v1.3.0/hbs_linux-arm64_dotnet.zip; fi - -# Extract hbs -RUN unzip hbs.zip -d /usr/local/bin && rm hbs.zip -RUN chmod +x /usr/local/bin/hbs - -# Copy entrypoint script and make it executable -COPY docker-unified/entrypoint.sh /entrypoint.sh -RUN chmod +x /entrypoint.sh - -VOLUME ["/etc/bitwarden"] - -WORKDIR /app -ENTRYPOINT ["/entrypoint.sh"] diff --git a/docker-unified/docker-compose.yml b/docker-unified/docker-compose.yml deleted file mode 100644 index 25e3bcd038..0000000000 --- a/docker-unified/docker-compose.yml +++ /dev/null @@ -1,56 +0,0 @@ ---- -version: "3.8" - -services: - bitwarden: - depends_on: - - db - env_file: - - settings.env - image: ${REGISTRY:-bitwarden}/self-host:${TAG:-beta} - restart: always - ports: - - "80:8080" - - "443:8443" - volumes: - - bitwarden:/etc/bitwarden - - logs:/var/log/bitwarden - - # MariaDB Example - db: - environment: - MARIADB_USER: "bitwarden" - MARIADB_PASSWORD: "super_strong_password" - MARIADB_DATABASE: "bitwarden_vault" - MARIADB_RANDOM_ROOT_PASSWORD: "true" - image: mariadb:10 - restart: always - volumes: - - data:/var/lib/mysql - - # PostgreSQL Example - # db: - # environment: - # POSTGRES_USER: "bitwarden" - # POSTGRES_PASSWORD: "super_strong_password" - # POSTGRES_DB: "bitwarden_vault" - # image: postgres:14 - # restart: always - # volumes: - # - data:/var/lib/postgresql/data - - # MS SQL Server Example - # Docs: https://learn.microsoft.com/en-us/sql/linux/sql-server-linux-docker-container-deployment - # db: - # environment: - # MSSQL_SA_PASSWORD: "super_strong_password" - # ACCEPT_EULA: Y - # image: mcr.microsoft.com/mssql/server:2019-latest - # restart: always - # volumes: - # - data:/var/opt/mssql - -volumes: - bitwarden: - logs: - data: diff --git a/docker-unified/entrypoint.sh b/docker-unified/entrypoint.sh deleted file mode 100755 index a04337c6a7..0000000000 --- a/docker-unified/entrypoint.sh +++ /dev/null @@ -1,108 +0,0 @@ -#!/bin/bash - -# Set up user group -PGID="${PGID:-1000}" -addgroup --gid $PGID bitwarden - -# Set up user -PUID="${PUID:-1000}" -adduser --no-create-home --shell /bin/bash --disabled-password --uid $PUID --gid $PGID --gecos "" bitwarden - -# Translate environment variables for application settings -VAULT_SERVICE_URI=https://$BW_DOMAIN -MYSQL_CONNECTION_STRING="server=$BW_DB_SERVER;port=${BW_DB_PORT:-3306};database=$BW_DB_DATABASE;user=$BW_DB_USERNAME;password=$BW_DB_PASSWORD" -POSTGRESQL_CONNECTION_STRING="Host=$BW_DB_SERVER;Port=${BW_DB_PORT:-5432};Database=$BW_DB_DATABASE;Username=$BW_DB_USERNAME;Password=$BW_DB_PASSWORD" -SQLSERVER_CONNECTION_STRING="Server=$BW_DB_SERVER,${BW_DB_PORT:-1433};Database=$BW_DB_DATABASE;User Id=$BW_DB_USERNAME;Password=$BW_DB_PASSWORD;Encrypt=True;TrustServerCertificate=True" -SQLITE_CONNECTION_STRING="Data Source=$BW_DB_FILE;" -INTERNAL_IDENTITY_KEY=$(openssl rand -hex 30) -OIDC_IDENTITY_CLIENT_KEY=$(openssl rand -hex 30) -DUO_AKEY=$(openssl rand -hex 30) - -export globalSettings__baseServiceUri__vault=${globalSettings__baseServiceUri__vault:-$VAULT_SERVICE_URI} -export globalSettings__installation__id=$BW_INSTALLATION_ID -export globalSettings__installation__key=$BW_INSTALLATION_KEY -export globalSettings__internalIdentityKey=${globalSettings__internalIdentityKey:-$INTERNAL_IDENTITY_KEY} -export globalSettings__oidcIdentityClientKey=${globalSettings__oidcIdentityClientKey:-$OIDC_IDENTITY_CLIENT_KEY} -export globalSettings__duo__aKey=${globalSettings__duo__aKey:-$DUO_AKEY} - -export globalSettings__databaseProvider=$BW_DB_PROVIDER -export globalSettings__mysql__connectionString=${globalSettings__mysql__connectionString:-$MYSQL_CONNECTION_STRING} -export globalSettings__postgreSql__connectionString=${globalSettings__postgreSql__connectionString:-$POSTGRESQL_CONNECTION_STRING} -export globalSettings__sqlServer__connectionString=${globalSettings__sqlServer__connectionString:-$SQLSERVER_CONNECTION_STRING} -export globalSettings__sqlite__connectionString=${globalSettings__sqlite__connectionString:-$SQLITE_CONNECTION_STRING} - -if [ "$BW_ENABLE_SSL" = "true" ]; then - export globalSettings__baseServiceUri__internalVault=https://localhost:${BW_PORT_HTTPS:-8443} -else - export globalSettings__baseServiceUri__internalVault=http://localhost:${BW_PORT_HTTP:-8080} -fi - -# Generate Identity certificate -if [ ! -f /etc/bitwarden/identity.pfx ]; then - openssl req \ - -x509 \ - -newkey rsa:4096 \ - -sha256 \ - -nodes \ - -keyout /etc/bitwarden/identity.key \ - -out /etc/bitwarden/identity.crt \ - -subj "/CN=Bitwarden IdentityServer" \ - -days 36500 - - openssl pkcs12 \ - -export \ - -out /etc/bitwarden/identity.pfx \ - -inkey /etc/bitwarden/identity.key \ - -in /etc/bitwarden/identity.crt \ - -passout pass:$globalSettings__identityServer__certificatePassword - - rm /etc/bitwarden/identity.crt - rm /etc/bitwarden/identity.key -fi - -cp /etc/bitwarden/identity.pfx /app/Identity/identity.pfx -cp /etc/bitwarden/identity.pfx /app/Sso/identity.pfx - -# Generate SSL certificates -if [ "$BW_ENABLE_SSL" = "true" -a ! -f /etc/bitwarden/${BW_SSL_KEY:-ssl.key} ]; then - openssl req \ - -x509 \ - -newkey rsa:4096 \ - -sha256 \ - -nodes \ - -days 36500 \ - -keyout /etc/bitwarden/${BW_SSL_KEY:-ssl.key} \ - -out /etc/bitwarden/${BW_SSL_CERT:-ssl.crt} \ - -reqexts SAN \ - -extensions SAN \ - -config <(cat /usr/lib/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:${BW_DOMAIN:-localhost}\nbasicConstraints=CA:true")) \ - -subj "/C=US/ST=California/L=Santa Barbara/O=Bitwarden Inc./OU=Bitwarden/CN=${BW_DOMAIN:-localhost}" -fi - -# Launch a loop to rotate nginx logs on a daily basis -/bin/sh -c "/logrotate.sh loop >/dev/null 2>&1 &" - -/usr/local/bin/hbs - -# Enable/Disable services -sed -i "s/autostart=true/autostart=${BW_ENABLE_ADMIN}/" /etc/supervisor.d/admin.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_API}/" /etc/supervisor.d/api.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_EVENTS}/" /etc/supervisor.d/events.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_ICONS}/" /etc/supervisor.d/icons.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_IDENTITY}/" /etc/supervisor.d/identity.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_NOTIFICATIONS}/" /etc/supervisor.d/notifications.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_SCIM}/" /etc/supervisor.d/scim.ini -sed -i "s/autostart=true/autostart=${BW_ENABLE_SSO}/" /etc/supervisor.d/sso.ini - -chown -R $PUID:$PGID \ - /app \ - /etc/bitwarden \ - /etc/nginx/http.d \ - /etc/supervisor \ - /etc/supervisor.d \ - /var/lib/nginx \ - /var/log \ - /var/run/nginx \ - /run - -exec setpriv --reuid=$PUID --regid=$PGID --init-groups /usr/bin/supervisord \ No newline at end of file diff --git a/docker-unified/hbs/app-id.hbs b/docker-unified/hbs/app-id.hbs deleted file mode 100644 index eed8768b49..0000000000 --- a/docker-unified/hbs/app-id.hbs +++ /dev/null @@ -1,15 +0,0 @@ -{ - "trustedFacets": [ - { - "version": { - "major": 1, - "minor": 0 - }, - "ids": [ - "{{{String.Coalesce env.globalSettings__baseServiceUri__vault "https://localhost"}}}", - "ios:bundle-id:com.8bit.bitwarden", - "android:apk-key-hash:dUGFzUzf3lmHSLBDBIv+WaFyZMI" - ] - } - ] -} diff --git a/docker-unified/hbs/config.yaml b/docker-unified/hbs/config.yaml deleted file mode 100644 index 2dc04a6584..0000000000 --- a/docker-unified/hbs/config.yaml +++ /dev/null @@ -1,7 +0,0 @@ -helper_categories: - - String -templates: - - src: /etc/hbs/app-id.hbs - dest: /app/Web/app-id.json - - src: /etc/hbs/nginx-config.hbs - dest: /etc/nginx/http.d/bitwarden.conf \ No newline at end of file diff --git a/docker-unified/hbs/nginx-config.hbs b/docker-unified/hbs/nginx-config.hbs deleted file mode 100644 index 2e998d878f..0000000000 --- a/docker-unified/hbs/nginx-config.hbs +++ /dev/null @@ -1,196 +0,0 @@ -server { - listen {{{String.Coalesce env.BW_PORT_HTTP "8080"}}} default_server; - #listen [::]:{{{String.Coalesce env.BW_PORT_HTTP "8080"}}} default_server; - server_name {{{String.Coalesce env.BW_DOMAIN "localhost"}}}; -{{#if (String.Equal env.BW_ENABLE_SSL "true")}} - - return 301 https://{{{String.Coalesce env.BW_DOMAIN "localhost"}}}:{{{String.Coalesce env.BW_PORT_HTTPS "8443"}}}$request_uri; -} - -server { - listen {{{String.Coalesce env.BW_PORT_HTTPS "8443"}}} ssl http2; - #listen [::]:{{{String.Coalesce env.BW_PORT_HTTPS "8443"}}} ssl http2; - server_name {{{String.Coalesce env.BW_DOMAIN "localhost"}}}; - - ssl_certificate /etc/bitwarden/{{{String.Coalesce env.BW_SSL_CERT "ssl.crt"}}}; - ssl_certificate_key /etc/bitwarden/{{{String.Coalesce env.BW_SSL_KEY "ssl.key"}}}; - ssl_session_timeout 30m; - ssl_session_cache shared:SSL:20m; - ssl_session_tickets off; -{{#if (String.Equal env.BW_ENABLE_SSL_DH "true")}} - - # Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits - ssl_dhparam /etc/bitwarden/{{{String.Coalesce env.BW_SSL_DH_CERT "dh.pem"}}}; -{{/if}} - - ssl_protocols {{{String.Coalesce env.BW_SSL_PROTOCOLS "TLSv1.2"}}}; - ssl_ciphers "{{{String.Coalesce env.BW_SSL_CIPHERS "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"}}}"; - # Enables server-side protection from BEAST attacks - ssl_prefer_server_ciphers on; -{{#if (String.Equal env.BW_ENABLE_SSL_CA "true")}} - - # OCSP Stapling --- - # Fetch OCSP records from URL in ssl_certificate and cache them - ssl_stapling on; - ssl_stapling_verify on; - - # Verify chain of trust of OCSP response using Root CA and Intermediate certs - ssl_trusted_certificate /etc/bitwarden/{{{String.Coalesce env.BW_SSL_CA_CERT "ca.crt"}}}; - resolver 1.1.1.1 1.0.0.1 9.9.9.9 149.112.112.112 valid=300s; -{{/if}} - - include /etc/nginx/security-headers-ssl.conf; -{{/if}} - include /etc/nginx/security-headers.conf; -{{#if (String.IsNotNullOrWhitespace env.BW_REAL_IPS)}} - -{{#each (String.Split env.BW_REAL_IPS ",")}} - set_real_ip_from {{{String.Trim .}}}; -{{/each}} - real_ip_header X-Forwarded-For; - real_ip_recursive on; -{{/if}} - - location / { - root /app/Web; -{{#if (String.Equal env.BW_ENABLE_SSL "true")}} - include /etc/nginx/security-headers-ssl.conf; -{{/if}} - include /etc/nginx/security-headers.conf; - add_header Content-Security-Policy "{{{String.Coalesce env.BW_CSP "default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://haveibeenpwned.com; child-src 'self' https://*.duosecurity.com https://*.duofederal.com; frame-src 'self' https://*.duosecurity.com https://*.duofederal.com; connect-src 'self' https://api.pwnedpasswords.com https://api.2fa.directory; object-src 'self' blob:;"}}}"; - add_header X-Frame-Options SAMEORIGIN; - add_header X-Robots-Tag "noindex, nofollow"; - } - - location /alive { - default_type text/plain; - return 200 $date_gmt; - } - - location = /app-id.json { - root /app/Web; -{{#if (String.Equal env.BW_ENABLE_SSL "true")}} - include /etc/nginx/security-headers-ssl.conf; -{{/if}} - include /etc/nginx/security-headers.conf; - proxy_hide_header Content-Type; - add_header Content-Type $fido_content_type; - } - - location = /duo-connector.html { - root /app/Web; - } - - location = /webauthn-connector.html { - root /app/Web; - } - - location = /webauthn-fallback-connector.html { - root /app/Web; - } - - location = /sso-connector.html { - root /app/Web; - } - - location = /captcha-connector.html { - root /app/Web; - } - - location = /captcha-mobile-connector.html { - root /app/Web; - } - - location /attachments/ { - alias /etc/bitwarden/attachments/; - } -{{#if (String.Equal env.BW_ENABLE_API "true")}} - - location /api/ { - proxy_pass http://localhost:5001/; - } -{{/if}} -{{#if (String.Equal env.BW_ENABLE_ICONS "true")}} - - location /icons/ { -{{#if (String.Equal env.BW_ICONS_PROXY_TO_CLOUD "true")}} - proxy_pass https://icons.bitwarden.net/; - proxy_set_header Host icons.bitwarden.net; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_ssl_server_name on; -{{else}} - proxy_pass http://localhost:5004/; -{{/if}} - } -{{/if}} -{{#if (String.Equal env.BW_ENABLE_NOTIFICATIONS "true")}} - - location /notifications/ { - proxy_pass http://localhost:5006/; - } - - location /notifications/hub { - proxy_pass http://localhost:5006/hub; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $http_connection; - } - - location /notifications/anonymous-hub { - proxy_pass http://localhost:5006/anonymous-hub; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $http_connection; - } - -{{/if}} -{{#if (String.Equal env.BW_ENABLE_EVENTS "true")}} - - location /events/ { - proxy_pass http://localhost:5003/; - } -{{/if}} -{{#if (String.Equal env.BW_ENABLE_SSO "true")}} - - location /sso { - proxy_pass http://localhost:5007; -{{#if (String.Equal env.BW_ENABLE_SSL "true")}} - include /etc/nginx/security-headers-ssl.conf; -{{/if}} - include /etc/nginx/security-headers.conf; - add_header X-Frame-Options SAMEORIGIN; - } -{{/if}} -{{#if (String.Equal env.BW_ENABLE_IDENTITY "true")}} - - location /identity { - proxy_pass http://localhost:5005; -{{#if (String.Equal env.BW_ENABLE_SSL "true")}} - include /etc/nginx/security-headers-ssl.conf; -{{/if}} - include /etc/nginx/security-headers.conf; - add_header X-Frame-Options SAMEORIGIN; - } -{{/if}} -{{#if (String.Equal env.BW_ENABLE_ADMIN "true")}} - - location /admin { - proxy_pass http://localhost:5000; -{{#if (String.Equal env.BW_ENABLE_SSL "true")}} - include /etc/nginx/security-headers-ssl.conf; -{{/if}} - include /etc/nginx/security-headers.conf; - add_header X-Frame-Options SAMEORIGIN; - } -{{/if}} -{{#if (String.Equal env.BW_ENABLE_SCIM "true")}} - - location /scim/ { - proxy_pass http://localhost:5002/; - } -{{/if}} -{{#if (String.Equal env.BW_ENABLE_KEY_CONNECTOR "true")}} - - location /key-connector/ { - proxy_pass {{{env.BW_KEY_CONNECTOR_INTERNAL_URL}}}/; - } -{{/if}} -} diff --git a/docker-unified/nginx/logrotate.sh b/docker-unified/nginx/logrotate.sh deleted file mode 100644 index d86c79c5db..0000000000 --- a/docker-unified/nginx/logrotate.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/sh - -while true -do - [ "$1" = "loop" ] && sleep $((24 * 3600 - (`date +%_H` * 3600 + `date +%_M` * 60 + `date +%_S`))) - ts=$(date +%Y%m%d_%H%M%S) - mv /var/log/nginx/access.log /var/log/nginx/access.$ts.log - mv /var/log/nginx/error.log /var/log/nginx/error.$ts.log - kill -USR1 `cat /var/run/nginx/nginx.pid` - sleep 1 - gzip /var/log/nginx/access.$ts.log - gzip /var/log/nginx/error.$ts.log - find /var/log/nginx/ -name "*.gz" -mtime +32 -delete - [ "$1" != "loop" ] && break -done diff --git a/docker-unified/nginx/mime.types b/docker-unified/nginx/mime.types deleted file mode 100644 index 7c3b1e7386..0000000000 --- a/docker-unified/nginx/mime.types +++ /dev/null @@ -1,138 +0,0 @@ -types { - - # Data interchange - - application/atom+xml atom; - application/json json map topojson; - application/ld+json jsonld; - application/rss+xml rss; - application/vnd.geo+json geojson; - application/xml rdf xml; - - - # JavaScript - - # Normalize to standard type. - # https://tools.ietf.org/html/rfc4329#section-7.2 - application/javascript js; - - - # Manifest files - - application/manifest+json webmanifest; - application/x-web-app-manifest+json webapp; - text/cache-manifest appcache; - - - # Media files - - audio/midi mid midi kar; - audio/mp4 aac f4a f4b m4a; - audio/mpeg mp3; - audio/ogg oga ogg opus; - audio/x-realaudio ra; - audio/x-wav wav; - image/bmp bmp; - image/gif gif; - image/jpeg jpeg jpg; - image/jxr jxr hdp wdp; - image/png png; - image/svg+xml svg svgz; - image/tiff tif tiff; - image/vnd.wap.wbmp wbmp; - image/webp webp; - image/x-jng jng; - video/3gpp 3gp 3gpp; - video/mp4 f4p f4v m4v mp4; - video/mpeg mpeg mpg; - video/ogg ogv; - video/quicktime mov; - video/webm webm; - video/x-flv flv; - video/x-mng mng; - video/x-ms-asf asf asx; - video/x-ms-wmv wmv; - video/x-msvideo avi; - - # Serving `.ico` image files with a different media type - # prevents Internet Explorer from displaying then as images: - # https://github.com/h5bp/html5-boilerplate/commit/37b5fec090d00f38de64b591bcddcb205aadf8ee - - image/x-icon cur ico; - - - # Microsoft Office - - application/msword doc; - application/vnd.ms-excel xls; - application/vnd.ms-powerpoint ppt; - application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; - application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; - - - # Web fonts - - application/font-woff woff; - application/font-woff2 woff2; - application/vnd.ms-fontobject eot; - - # Browsers usually ignore the font media types and simply sniff - # the bytes to figure out the font type. - # https://mimesniff.spec.whatwg.org/#matching-a-font-type-pattern - # - # However, Blink and WebKit based browsers will show a warning - # in the console if the following font types are served with any - # other media types. - - application/x-font-ttf ttc ttf; - font/opentype otf; - - - # Other - - application/java-archive ear jar war; - application/mac-binhex40 hqx; - application/octet-stream bin deb dll dmg exe img iso msi msm msp safariextz; - application/pdf pdf; - application/postscript ai eps ps; - application/rtf rtf; - application/vnd.google-earth.kml+xml kml; - application/vnd.google-earth.kmz kmz; - application/vnd.wap.wmlc wmlc; - application/x-7z-compressed 7z; - application/x-bb-appworld bbaw; - application/x-bittorrent torrent; - application/x-chrome-extension crx; - application/x-cocoa cco; - application/x-java-archive-diff jardiff; - application/x-java-jnlp-file jnlp; - application/x-makeself run; - application/x-opera-extension oex; - application/x-perl pl pm; - application/x-pilot pdb prc; - application/x-rar-compressed rar; - application/x-redhat-package-manager rpm; - application/x-sea sea; - application/x-shockwave-flash swf; - application/x-stuffit sit; - application/x-tcl tcl tk; - application/x-x509-ca-cert crt der pem; - application/x-xpinstall xpi; - application/xhtml+xml xhtml; - application/xslt+xml xsl; - application/zip zip; - text/css css; - text/csv csv; - text/html htm html shtml; - text/markdown md; - text/mathml mml; - text/plain txt; - text/vcard vcard vcf; - text/vnd.rim.location.xloc xloc; - text/vnd.sun.j2me.app-descriptor jad; - text/vnd.wap.wml wml; - text/vtt vtt; - text/x-component htc; - -} diff --git a/docker-unified/nginx/nginx.conf b/docker-unified/nginx/nginx.conf deleted file mode 100644 index 93445e8a21..0000000000 --- a/docker-unified/nginx/nginx.conf +++ /dev/null @@ -1,147 +0,0 @@ -# nginx Configuration File -# http://wiki.nginx.org/Configuration - -daemon off; - -# Run as a less privileged user for security reasons. -# user www www; - -# How many worker threads to run; -# "auto" sets it to the number of CPU cores available in the system, and -# offers the best performance. Don't set it higher than the number of CPU -# cores if changing this parameter. - -# The maximum number of connections for Nginx is calculated by: -# max_clients = worker_processes * worker_connections -worker_processes auto; - -# Maximum open file descriptors per process; -# should be > worker_connections. -worker_rlimit_nofile 8192; - -events { - # When you need > 8000 * cpu_cores connections, you start optimizing your OS, - # and this is probably the point at which you hire people who are smarter than - # you, as this is *a lot* of requests. - worker_connections 8000; -} - -# Default error log file -# (this is only used when you don't override error_log on a server{} level) -error_log /var/log/nginx/error.log warn; -pid /var/run/nginx/nginx.pid; - -http { - # Include proxy and server configuration. - include /etc/nginx/proxy.conf; - include /etc/nginx/http.d/bitwarden.conf; - - # Hide nginx version information. - server_tokens off; - - # Define the MIME types for files. - include /etc/nginx/mime.types; - default_type application/octet-stream; - - # Update charset_types to match updated mime.types. - # text/html is always included by charset module. - # Default: text/html text/xml text/plain text/vnd.wap.wml application/javascript application/rss+xml - charset_types - text/css - text/plain - text/vnd.wap.wml - application/javascript - application/json - application/rss+xml - application/xml; - - # Format to use in log files - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - # Default log file - # (this is only used when you don't override access_log on a server{} level) - access_log /var/log/nginx/access.log main; - - # How long to allow each connection to stay idle; longer values are better - # for each individual client, particularly for SSL, but means that worker - # connections are tied up longer. (Default: 65) - keepalive_timeout 20; - - # Speed up file transfers by using sendfile() to copy directly - # between descriptors rather than using read()/write(). - # For performance reasons, on FreeBSD systems w/ ZFS - # this option should be disabled as ZFS's ARC caches - # frequently used files in RAM by default. - sendfile on; - - # Tell Nginx not to send out partial frames; this increases throughput - # since TCP frames are filled up before being sent out. (adds TCP_CORK) - tcp_nopush on; - - - # Compression - - # Enable Gzip compressed. - gzip on; - - # Compression level (1-9). - # 5 is a perfect compromise between size and cpu usage, offering about - # 75% reduction for most ascii files (almost identical to level 9). - gzip_comp_level 5; - - # Don't compress anything that's already small and unlikely to shrink much - # if at all (the default is 20 bytes, which is bad as that usually leads to - # larger files after gzipping). - gzip_min_length 256; - - # Compress data even for clients that are connecting to us via proxies, - # identified by the "Via" header (required for CloudFront). - gzip_proxied any; - - # Tell proxies to cache both the gzipped and regular version of a resource - # whenever the client's Accept-Encoding capabilities header varies; - # Avoids the issue where a non-gzip capable client (which is extremely rare - # today) would display gibberish if their proxy gave them the gzipped version. - gzip_vary on; - - # Compress all output labeled with one of the following MIME-types. - gzip_types - application/atom+xml - application/javascript - application/json - application/ld+json - application/manifest+json - application/rss+xml - application/vnd.geo+json - application/vnd.ms-fontobject - application/x-font-ttf - application/x-web-app-manifest+json - application/xhtml+xml - application/xml - font/opentype - image/bmp - image/svg+xml - image/x-icon - text/cache-manifest - text/css - text/plain - text/vcard - text/vnd.rim.location.xloc - text/vtt - text/x-component - text/x-cross-domain-policy; - # text/html is always compressed by HttpGzipModule - - # This should be turned on if you are going to have pre-compressed copies (.gz) of - # static files available. If not it should be left off as it will cause extra I/O - # for the check. It is best if you enable this in a location{} block for - # a specific directory, or on an individual server{} level. - # gzip_static on; - - # Content type for FIDO U2F facets - map $uri $fido_content_type { - default "application/fido.trusted-apps+json"; - } -} diff --git a/docker-unified/nginx/proxy.conf b/docker-unified/nginx/proxy.conf deleted file mode 100644 index a56be66368..0000000000 --- a/docker-unified/nginx/proxy.conf +++ /dev/null @@ -1,27 +0,0 @@ -proxy_redirect off; - -map $http_host $upstream_host { - default "$host"; - ~. "$http_host"; -} -proxy_set_header Host $upstream_host; - -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - -map $http_x_forwarded_proto $upstream_scheme { - default "$scheme"; - ~. "$http_x_forwarded_proto"; -} -proxy_set_header X-Url-Scheme $upstream_scheme; -proxy_set_header X-Forwarded-Proto $upstream_scheme; - -client_max_body_size 505m; -client_body_buffer_size 128k; -proxy_connect_timeout 90; -proxy_send_timeout 90; -proxy_read_timeout 90; -proxy_buffer_size 128k; -proxy_buffers 4 256k; -proxy_busy_buffers_size 256k; -large_client_header_buffers 4 32k; diff --git a/docker-unified/nginx/security-headers-ssl.conf b/docker-unified/nginx/security-headers-ssl.conf deleted file mode 100644 index d94e835c4e..0000000000 --- a/docker-unified/nginx/security-headers-ssl.conf +++ /dev/null @@ -1,2 +0,0 @@ -# This will enforce HTTP browsing into HTTPS and avoid ssl stripping attack. 6 months age -add_header Strict-Transport-Security max-age=15768000; \ No newline at end of file diff --git a/docker-unified/nginx/security-headers.conf b/docker-unified/nginx/security-headers.conf deleted file mode 100644 index c23d1b497e..0000000000 --- a/docker-unified/nginx/security-headers.conf +++ /dev/null @@ -1,3 +0,0 @@ -add_header Referrer-Policy same-origin; -add_header X-Content-Type-Options nosniff; -add_header X-XSS-Protection "1; mode=block"; \ No newline at end of file diff --git a/docker-unified/settings.env b/docker-unified/settings.env deleted file mode 100644 index d86baa6c25..0000000000 --- a/docker-unified/settings.env +++ /dev/null @@ -1,69 +0,0 @@ -##################### -# Required Settings # -##################### - -# Server hostname -BW_DOMAIN=bitwarden.yourdomain.com - -# Database -# Available providers are sqlserver, postgresql, mysql/mariadb, or sqlite -BW_DB_PROVIDER=mysql -BW_DB_SERVER=db -BW_DB_DATABASE=bitwarden_vault -BW_DB_USERNAME=bitwarden -BW_DB_PASSWORD=super_strong_password - -# Installation information -# Get your ID and key from https://bitwarden.com/host/ -BW_INSTALLATION_ID=00000000-0000-0000-0000-000000000000 -BW_INSTALLATION_KEY=xxxxxxxxxxxx - -##################### -# Optional Settings # -##################### -# Learn more here: https://bitwarden.com/help/environment-variables/ - -# Container user ID/group ID -#PUID=1000 -#PGID=1000 - -# Webserver ports -#BW_PORT_HTTP=8080 -#BW_PORT_HTTPS=8443 - -# SSL -#BW_ENABLE_SSL=true -#BW_ENABLE_SSL_CA=true -#BW_SSL_CERT=ssl.crt -#BW_SSL_KEY=ssl.key -#BW_SSL_CA_CERT=ca.crt - -# Services -# Some services, namely for enterprise use cases, are disabled by default. Defaults shown below. -#BW_ENABLE_ADMIN=true -#BW_ENABLE_API=true -#BW_ENABLE_EVENTS=false -#BW_ENABLE_ICONS=true -#BW_ENABLE_IDENTITY=true -#BW_ENABLE_NOTIFICATIONS=true -#BW_ENABLE_SCIM=false -#BW_ENABLE_SSO=false - -#BW_ICONS_PROXY_TO_CLOUD=false - -# Mail -#globalSettings__mail__replyToEmail=noreply@$BW_DOMAIN -#globalSettings__mail__smtp__host=smtphost.example.com -#globalSettings__mail__smtp__port=587 -#globalSettings__mail__smtp__ssl=false -#globalSettings__mail__smtp__username=smtpusername -#globalSettings__mail__smtp__password=smtppassword - -# Yubikey -#globalSettings__yubico__clientId=REPLACE -#globalSettings__yubico__key=REPLACE - -# Other -#globalSettings__disableUserRegistration=false -#globalSettings__hibpApiKey=REPLACE -#adminSettings__admins=admin1@email.com,admin2@email.com diff --git a/docker-unified/supervisord/admin.ini b/docker-unified/supervisord/admin.ini deleted file mode 100644 index 113da5e997..0000000000 --- a/docker-unified/supervisord/admin.ini +++ /dev/null @@ -1,9 +0,0 @@ -[program:admin] -autostart=true -autorestart=true -command=/usr/bin/dotnet "Admin.dll" -directory=/app/Admin -environment=ASPNETCORE_URLS="http://+:5000" -redirect_stderr=true -startsecs=15 -stdout_logfile=/var/log/bitwarden/admin.log diff --git a/docker-unified/supervisord/api.ini b/docker-unified/supervisord/api.ini deleted file mode 100644 index 410e1d8b87..0000000000 --- a/docker-unified/supervisord/api.ini +++ /dev/null @@ -1,9 +0,0 @@ -[program:api] -autostart=true -autorestart=true -command=/usr/bin/dotnet "Api.dll" -directory=/app/Api -environment=ASPNETCORE_URLS="http://+:5001" -redirect_stderr=true -startsecs=15 -stdout_logfile=/var/log/bitwarden/api.log diff --git a/docker-unified/supervisord/events.ini b/docker-unified/supervisord/events.ini deleted file mode 100644 index 32093d2d1c..0000000000 --- a/docker-unified/supervisord/events.ini +++ /dev/null @@ -1,9 +0,0 @@ -[program:events] -autostart=true -autorestart=true -command=/usr/bin/dotnet "Events.dll" -directory=/app/Events -environment=ASPNETCORE_URLS="http://+:5003" -redirect_stderr=true -startsecs=15 -stdout_logfile=/var/log/bitwarden/events.log diff --git a/docker-unified/supervisord/icons.ini b/docker-unified/supervisord/icons.ini deleted file mode 100644 index 36489e8bb2..0000000000 --- a/docker-unified/supervisord/icons.ini +++ /dev/null @@ -1,9 +0,0 @@ -[program:icons] -autostart=true -autorestart=true -command=/usr/bin/dotnet "Icons.dll" -directory=/app/Icons -environment=ASPNETCORE_URLS="http://+:5004" -redirect_stderr=true -startsecs=15 -stdout_logfile=/var/log/bitwarden/icons.log diff --git a/docker-unified/supervisord/identity.ini b/docker-unified/supervisord/identity.ini deleted file mode 100644 index 4b1600ce94..0000000000 --- a/docker-unified/supervisord/identity.ini +++ /dev/null @@ -1,10 +0,0 @@ -[program:identity] -autostart=true -autorestart=true -command=/usr/bin/dotnet "Identity.dll" -directory=/app/Identity -environment=ASPNETCORE_URLS="http://+:5005" -priority=1 -redirect_stderr=true -startsecs=15 -stdout_logfile=/var/log/bitwarden/identity.log diff --git a/docker-unified/supervisord/nginx.ini b/docker-unified/supervisord/nginx.ini deleted file mode 100644 index bc52f3f91d..0000000000 --- a/docker-unified/supervisord/nginx.ini +++ /dev/null @@ -1,7 +0,0 @@ -[program:nginx] -autostart=true -autorestart=true -command=nginx -redirect_stderr=true -startsecs=15 -stdout_logfile=/var/log/bitwarden/nginx.log diff --git a/docker-unified/supervisord/notifications.ini b/docker-unified/supervisord/notifications.ini deleted file mode 100644 index 2744ff7117..0000000000 --- a/docker-unified/supervisord/notifications.ini +++ /dev/null @@ -1,9 +0,0 @@ -[program:notifications] -autostart=true -autorestart=true -command=/usr/bin/dotnet "Notifications.dll" -directory=/app/Notifications -environment=ASPNETCORE_URLS="http://+:5006" -redirect_stderr=true -startsecs=15 -stdout_logfile=/var/log/bitwarden/notifications.log diff --git a/docker-unified/supervisord/scim.ini b/docker-unified/supervisord/scim.ini deleted file mode 100644 index 11d00d4c29..0000000000 --- a/docker-unified/supervisord/scim.ini +++ /dev/null @@ -1,9 +0,0 @@ -[program:scim] -autostart=true -autorestart=true -command=/usr/bin/dotnet "Scim.dll" -directory=/app/Scim -environment=ASPNETCORE_URLS="http://+:5002" -redirect_stderr=true -startsecs=15 -stdout_logfile=/var/log/bitwarden/scim.log diff --git a/docker-unified/supervisord/sso.ini b/docker-unified/supervisord/sso.ini deleted file mode 100644 index cb29c731a7..0000000000 --- a/docker-unified/supervisord/sso.ini +++ /dev/null @@ -1,9 +0,0 @@ -[program:sso] -autostart=true -autorestart=true -command=/usr/bin/dotnet "Sso.dll" -directory=/app/Sso -environment=ASPNETCORE_URLS="http://+:5007" -redirect_stderr=true -startsecs=15 -stdout_logfile=/var/log/bitwarden/sso.log diff --git a/docker-unified/supervisord/supervisord.conf b/docker-unified/supervisord/supervisord.conf deleted file mode 100644 index 4cd6a8cb47..0000000000 --- a/docker-unified/supervisord/supervisord.conf +++ /dev/null @@ -1,15 +0,0 @@ -[unix_http_server] -file=/run/supervisord.sock ; the path to the socket file - -[supervisord] -logfile=/var/log/supervisord.log ; main log file; default $CWD/supervisord.log -nodaemon=true ; start in foreground if true; default false - -[rpcinterface:supervisor] -supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface - -[supervisorctl] -serverurl=unix:///run/supervisord.sock ; use a unix:// URL for a unix socket - -[include] -files = /etc/supervisor.d/*.ini From 1ab7560a8692d428f25abb8a44a39cc916af5d1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 23 Jun 2023 16:54:41 +0200 Subject: [PATCH 06/13] Fix build workflow (#3041) --- .github/workflows/build.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 32856df6ef..d95fade200 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -555,7 +555,7 @@ jobs: owner: 'bitwarden', repo: 'self-host', workflow_id: 'build-self-host.yml', - ref: 'DEVOPS-1204-Migrate_Build_pipeline_to_self-host_repo', + ref: 'master', inputs: { server_branch: '${{ github.ref }}' } @@ -573,6 +573,7 @@ jobs: - build-docker - upload - build-mssqlmigratorutility + - trigger-self-host-build steps: - name: Check if any job failed if: | @@ -587,6 +588,7 @@ jobs: BUILD_DOCKER_STATUS: ${{ needs.build-docker.result }} UPLOAD_STATUS: ${{ needs.upload.result }} BUILD_MSSQLMIGRATORUTILITY_STATUS: ${{ needs.build-mssqlmigratorutility.result }} + TRIGGER_SELF_HOST_BUILD_STATUS: ${{ needs.trigger-self-host-build.result }} run: | if [ "$CLOC_STATUS" = "failure" ]; then exit 1 @@ -602,6 +604,8 @@ jobs: exit 1 elif [ "$BUILD_MSSQLMIGRATORUTILITY_STATUS" = "failure" ]; then exit 1 + elif [ "$TRIGGER_SELF_HOST_BUILD_STATUS" = "failure" ]; then + exit 1 fi - name: Login to Azure - CI subscription From 62ae9cb695130ff921e7053c080430b0b1f55d2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Ch=C4=99ci=C5=84ski?= Date: Fri, 23 Jun 2023 17:13:45 +0200 Subject: [PATCH 07/13] Fix build: change self-host trigger workflow name (#3042) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d95fade200..4ae8ee4ac8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -554,7 +554,7 @@ jobs: await github.rest.actions.createWorkflowDispatch({ owner: 'bitwarden', repo: 'self-host', - workflow_id: 'build-self-host.yml', + workflow_id: 'build-unified.yml', ref: 'master', inputs: { server_branch: '${{ github.ref }}' From 4c61d05b243fbdf8f230d1a2b6f3d2f88f53008e Mon Sep 17 00:00:00 2001 From: Alex Urbina <42731074+urbinaalex17@users.noreply.github.com> Date: Fri, 23 Jun 2023 11:12:54 -0600 Subject: [PATCH 08/13] DEVOPS-1391 REFACTOR: server build workflow to use setup-docker-trust GitHub Action (#3040) --- .github/workflows/build.yml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4ae8ee4ac8..f95c3e8171 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -317,17 +317,12 @@ jobs: DOCKER_PASSWORD: ${{ steps.retrieve-secrets.outputs.docker-password }} run: echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin - - name: Setup Docker Trust + - name: Setup Docker Content Trust (DCT) if: ${{ env.is_publish_branch == 'true' }} - env: - DCT_DELEGATION_KEY_ID: "c9bde8ec820701516491e5e03d3a6354e7bd66d05fa3df2b0062f68b116dc59c" - DCT_DELEGATE_KEY: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-key }} - DCT_REPO_PASSPHRASE: ${{ steps.retrieve-secrets.outputs.dct-delegate-2-repo-passphrase }} - run: | - mkdir -p ~/.docker/trust/private - echo "$DCT_DELEGATE_KEY" > ~/.docker/trust/private/$DCT_DELEGATION_KEY_ID.key - echo "DOCKER_CONTENT_TRUST=1" >> $GITHUB_ENV - echo "DOCKER_CONTENT_TRUST_REPOSITORY_PASSPHRASE=$DCT_REPO_PASSPHRASE" >> $GITHUB_ENV + uses: bitwarden/gh-actions/setup-docker-trust@f955298c7a982b3fb5dbb73afd582c584fd5beec + with: + azure-creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} + azure-keyvault-name: "bitwarden-ci" ########## Generate image tag and build Docker image ########## - name: Generate Docker image tag From e96fc56dc278285a8734bc5925f9f9b61b51c036 Mon Sep 17 00:00:00 2001 From: SmithThe4th Date: Mon, 26 Jun 2023 15:04:21 -0400 Subject: [PATCH 09/13] [SG-497] BEEEP - Health Checks API Project (#2237) * health check services added * health check extension added * added get connection string * made changes to hrslth check method * Added database health check * added identity server health check * added identity server health check * Added logger publisher * latest changes * removed file * Added mail server check for dev * Added authorization to health check url path * commented * Added exception to switch * Removed exclude code coverage * Added health check for redis * Added todos * Added storage queue checks * Added checks for mail * Removed unused references and fixed linting issue * Lint issues * Moved healthchecks to sharedWeb project and exposed builder as a parameter to configure more health checks based on a project * Added health check to API project * dependencies updated * Removed ef core health check dependencies * Added checks to only add a health check when the connection string exists, moved health check from startup to extension class * Merged with master and fixed conflicts * Fixed lint issues * Added check for amazon ses * merged with master * fixed lint * Removed Amazon SES health check --- .../packages.lock.json | 2 +- bitwarden_license/src/Scim/packages.lock.json | 10 +- bitwarden_license/src/Sso/packages.lock.json | 10 +- .../Commercial.Core.Test/packages.lock.json | 8 +- .../Scim.IntegrationTest/packages.lock.json | 24 +- .../test/Scim.Test/packages.lock.json | 16 +- src/Admin/packages.lock.json | 26 +- src/Api/Api.csproj | 9 +- src/Api/Startup.cs | 17 +- .../Utilities/ServiceCollectionExtensions.cs | 45 +++ src/Api/packages.lock.json | 333 ++++++++++------ src/Billing/packages.lock.json | 10 +- src/Events/packages.lock.json | 10 +- src/EventsProcessor/packages.lock.json | 10 +- src/Icons/packages.lock.json | 10 +- src/Identity/packages.lock.json | 10 +- src/Notifications/packages.lock.json | 10 +- .../Health/HealthCheckServiceExtensions.cs | 60 +++ src/SharedWeb/packages.lock.json | 4 +- test/Api.IntegrationTest/packages.lock.json | 364 +++++++++++------ test/Api.Test/packages.lock.json | 377 +++++++++++------- test/Billing.Test/packages.lock.json | 16 +- test/Core.Test/packages.lock.json | 2 +- test/Icons.Test/packages.lock.json | 14 +- .../packages.lock.json | 20 +- test/Identity.Test/packages.lock.json | 16 +- .../packages.lock.json | 10 +- .../packages.lock.json | 4 +- test/IntegrationTestCommon/packages.lock.json | 16 +- util/MsSqlMigratorUtility/packages.lock.json | 2 +- util/MySqlMigrations/packages.lock.json | 2 +- util/PostgresMigrations/packages.lock.json | 2 +- util/Setup/packages.lock.json | 2 +- util/SqlServerEFScaffold/packages.lock.json | 345 ++++++++++------ util/SqliteMigrations/packages.lock.json | 2 +- 35 files changed, 1191 insertions(+), 627 deletions(-) create mode 100644 src/SharedWeb/Health/HealthCheckServiceExtensions.cs diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json index 8c22aac980..0f1a8e47ad 100644 --- a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json @@ -2783,7 +2783,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", diff --git a/bitwarden_license/src/Scim/packages.lock.json b/bitwarden_license/src/Scim/packages.lock.json index e53e007446..79daea5128 100644 --- a/bitwarden_license/src/Scim/packages.lock.json +++ b/bitwarden_license/src/Scim/packages.lock.json @@ -2786,7 +2786,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2794,7 +2794,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2806,9 +2806,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/bitwarden_license/src/Sso/packages.lock.json b/bitwarden_license/src/Sso/packages.lock.json index 750a13b70d..c2f6bc6a67 100644 --- a/bitwarden_license/src/Sso/packages.lock.json +++ b/bitwarden_license/src/Sso/packages.lock.json @@ -2945,7 +2945,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2953,7 +2953,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2965,9 +2965,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/bitwarden_license/test/Commercial.Core.Test/packages.lock.json b/bitwarden_license/test/Commercial.Core.Test/packages.lock.json index ce3b26f847..daa76ebc37 100644 --- a/bitwarden_license/test/Commercial.Core.Test/packages.lock.json +++ b/bitwarden_license/test/Commercial.Core.Test/packages.lock.json @@ -2818,7 +2818,7 @@ "commercial.core": { "type": "Project", "dependencies": { - "Core": "2023.3.0" + "Core": "2023.4.3" } }, "common": { @@ -2826,7 +2826,7 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "NSubstitute": "4.3.0", @@ -2880,8 +2880,8 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Common": "2023.3.0", - "Core": "2023.3.0", + "Common": "2023.4.3", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "Moq": "4.17.2", diff --git a/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json b/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json index 4a1d7324fb..3e5ff59a26 100644 --- a/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json +++ b/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json @@ -3144,7 +3144,7 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "NSubstitute": "4.3.0", @@ -3196,15 +3196,15 @@ "identity": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "SharedWeb": "2023.3.0", + "Core": "2023.4.3", + "SharedWeb": "2023.4.3", "Swashbuckle.AspNetCore.SwaggerGen": "6.5.0" } }, "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -3212,7 +3212,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -3224,8 +3224,8 @@ "integrationtestcommon": { "type": "Project", "dependencies": { - "Common": "2023.3.0", - "Identity": "2023.3.0", + "Common": "2023.4.3", + "Identity": "2023.4.3", "Microsoft.AspNetCore.Mvc.Testing": "6.0.5", "Microsoft.EntityFrameworkCore.InMemory": "6.0.5", "Microsoft.Extensions.Configuration": "6.0.1" @@ -3234,16 +3234,16 @@ "scim": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "SharedWeb": "2023.3.0" + "Core": "2023.4.3", + "SharedWeb": "2023.4.3" } }, "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/bitwarden_license/test/Scim.Test/packages.lock.json b/bitwarden_license/test/Scim.Test/packages.lock.json index 9b4e5e1a8f..20d19ac81b 100644 --- a/bitwarden_license/test/Scim.Test/packages.lock.json +++ b/bitwarden_license/test/Scim.Test/packages.lock.json @@ -2989,7 +2989,7 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "NSubstitute": "4.3.0", @@ -3041,7 +3041,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -3049,7 +3049,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -3061,16 +3061,16 @@ "scim": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "SharedWeb": "2023.3.0" + "Core": "2023.4.3", + "SharedWeb": "2023.4.3" } }, "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/src/Admin/packages.lock.json b/src/Admin/packages.lock.json index 5b57e3b372..bd8b7ae705 100644 --- a/src/Admin/packages.lock.json +++ b/src/Admin/packages.lock.json @@ -2834,7 +2834,7 @@ "commercial.core": { "type": "Project", "dependencies": { - "Core": "2023.3.0" + "Core": "2023.4.3" } }, "core": { @@ -2882,7 +2882,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2890,7 +2890,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2902,7 +2902,7 @@ "migrator": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.Extensions.Logging": "6.0.0", "dbup-sqlserver": "5.0.8" } @@ -2910,30 +2910,30 @@ "mysqlmigrations": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } }, "postgresmigrations": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } }, "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } }, "sqlitemigrations": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj index ea37ffb593..c659ec52d6 100644 --- a/src/Api/Api.csproj +++ b/src/Api/Api.csproj @@ -32,8 +32,15 @@ + + + + + + + - + diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index c114a96819..c73175d01a 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -8,9 +8,11 @@ using Bit.Core.Utilities; using IdentityModel; using System.Globalization; using Bit.Core.IdentityServer; +using Bit.SharedWeb.Health; using Microsoft.IdentityModel.Logging; using Microsoft.OpenApi.Models; using Bit.SharedWeb.Utilities; +using Microsoft.AspNetCore.Diagnostics.HealthChecks; using Microsoft.Extensions.DependencyInjection.Extensions; using Bit.Core.Auth.Identity; @@ -133,6 +135,9 @@ public class Startup services.AddDefaultServices(globalSettings); services.AddCoreLocalizationServices(); + //health check + services.AddHealthChecks(globalSettings); + #if OSS services.AddOosServices(); #else @@ -206,7 +211,17 @@ public class Startup app.UseMiddleware(); // Add endpoints to the request pipeline. - app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute()); + app.UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute(); + + endpoints.MapHealthChecks("/healthz"); + + endpoints.MapHealthChecks("/healthz/extended", new HealthCheckOptions + { + ResponseWriter = HealthCheckServiceExtensions.WriteResponse + }); + }); // Add Swagger if (Environment.IsDevelopment() || globalSettings.SelfHosted) diff --git a/src/Api/Utilities/ServiceCollectionExtensions.cs b/src/Api/Utilities/ServiceCollectionExtensions.cs index cf3f890922..1be9d54e19 100644 --- a/src/Api/Utilities/ServiceCollectionExtensions.cs +++ b/src/Api/Utilities/ServiceCollectionExtensions.cs @@ -1,5 +1,6 @@ using Bit.Core.IdentityServer; using Bit.Core.Settings; +using Bit.SharedWeb.Health; using Microsoft.OpenApi.Models; namespace Bit.Api.Utilities; @@ -69,4 +70,48 @@ public static class ServiceCollectionExtensions config.IncludeXmlComments(coreFilePath); }); } + + public static void AddHealthChecks(this IServiceCollection services, GlobalSettings globalSettings) + { + services.AddHealthCheckServices(globalSettings, builder => + { + var identityUri = new Uri(globalSettings.BaseServiceUri.Identity + + "/.well-known/openid-configuration"); + + builder.AddUrlGroup(identityUri, "identity"); + + if (!string.IsNullOrEmpty(globalSettings.SqlServer.ConnectionString)) + { + builder.AddSqlServer(globalSettings.SqlServer.ConnectionString); + } + + if (!string.IsNullOrEmpty(globalSettings.Redis.ConnectionString)) + { + builder.AddRedis(globalSettings.Redis.ConnectionString); + } + + if (!string.IsNullOrEmpty(globalSettings.Storage.ConnectionString)) + { + builder.AddAzureQueueStorage(globalSettings.Storage.ConnectionString, name: "storage_queue") + .AddAzureQueueStorage(globalSettings.Events.ConnectionString, name: "events_queue"); + } + + if (!string.IsNullOrEmpty(globalSettings.Notifications.ConnectionString)) + { + builder.AddAzureQueueStorage(globalSettings.Notifications.ConnectionString, + name: "notifications_queue"); + } + + if (!string.IsNullOrEmpty(globalSettings.ServiceBus.ConnectionString)) + { + builder.AddAzureServiceBusTopic(_ => globalSettings.ServiceBus.ConnectionString, + _ => globalSettings.ServiceBus.ApplicationCacheTopicName, name: "service_bus"); + } + + if (!string.IsNullOrEmpty(globalSettings.Mail.SendGridApiKey)) + { + builder.AddSendGrid(globalSettings.Mail.SendGridApiKey); + } + }); + } } diff --git a/src/Api/packages.lock.json b/src/Api/packages.lock.json index 265ff8d618..10b16441c0 100644 --- a/src/Api/packages.lock.json +++ b/src/Api/packages.lock.json @@ -2,6 +2,81 @@ "version": 1, "dependencies": { "net6.0": { + "AspNetCore.HealthChecks.AzureServiceBus": { + "type": "Direct", + "requested": "[6.1.0, )", + "resolved": "6.1.0", + "contentHash": "LepLE6NO4bLBVDzlx/730pD6jnfkV6zaaRUrbN1LqnNk4m1hROsv7wOpgbKgVDgYIfeLzdiVnBviEevSxWFKMQ==", + "dependencies": { + "Azure.Messaging.EventHubs": "5.7.4", + "Azure.Messaging.ServiceBus": "7.11.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.10" + } + }, + "AspNetCore.HealthChecks.AzureStorage": { + "type": "Direct", + "requested": "[6.1.2, )", + "resolved": "6.1.2", + "contentHash": "R/uHJ40Cc0fBLi48SqDtT6fHyR5G8L3+PeKlbe8t498GLebeBIR3ve4l4n7UzCD0qgmQDDvyIYvVywx3i5Y6Ng==", + "dependencies": { + "Azure.Storage.Blobs": "12.14.1", + "Azure.Storage.Files.Shares": "12.11.0", + "Azure.Storage.Queues": "12.11.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.10" + } + }, + "AspNetCore.HealthChecks.Network": { + "type": "Direct", + "requested": "[6.0.4, )", + "resolved": "6.0.4", + "contentHash": "rvoPkqlvhX1HW6dpqjE1rbvmmMo9v7+Uf9dJffEcd3mA/DyyEitlZFc6cwYtmZVFdgy2gbIU4ubs3654nVfvjA==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.7", + "SSH.NET": "2020.0.2", + "System.Buffers": "4.5.1" + } + }, + "AspNetCore.HealthChecks.Redis": { + "type": "Direct", + "requested": "[6.0.4, )", + "resolved": "6.0.4", + "contentHash": "adNNWF6kV8v1HLTmF3b9F5K6ubvgx+S7VqhzA8T/5YuIpRWsCDk8+q3RIDDV8Twvl9pRahLfzCbFrPYxvzmk7g==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.4", + "StackExchange.Redis": "2.5.61" + } + }, + "AspNetCore.HealthChecks.SendGrid": { + "type": "Direct", + "requested": "[6.0.2, )", + "resolved": "6.0.2", + "contentHash": "VgskjkCUmSpAxil20rZlrj14bMi9aFNdiGLDtDTKjkUU0GYkoyi4HRVEy9Gp0FIgu9ce7quN+dNCpydKvMxjqA==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.2", + "Microsoft.Extensions.Http": "6.0.0", + "SendGrid": "9.24.4" + } + }, + "AspNetCore.HealthChecks.SqlServer": { + "type": "Direct", + "requested": "[6.0.2, )", + "resolved": "6.0.2", + "contentHash": "Af7ws27DnZZ4bKCiEREm7emSAKEtIiYirEAkI0ixFgK1fwJ99jmMnPC+kU01zfqn3FyCO/gZOUO7WbyVvTPpFg==", + "dependencies": { + "Microsoft.Data.SqlClient": "3.0.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.0" + } + }, + "AspNetCore.HealthChecks.Uris": { + "type": "Direct", + "requested": "[6.0.3, )", + "resolved": "6.0.3", + "contentHash": "EY0Vh8s2UrbnyvM/QhbyYuCnbrBw36BKkdh5LqdINxqAGnlPFQXf+/UoNlH/76MTEyg+nvdp2wjr5MqWDkVFaQ==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.0", + "Microsoft.Extensions.Http": "6.0.0" + } + }, "Azure.Messaging.EventGrid": { "type": "Direct", "requested": "[4.10.0, )", @@ -97,6 +172,14 @@ "System.Threading.Tasks.Extensions": "4.5.4" } }, + "Azure.Core.Amqp": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "vrF4isvhwdZspzorLwYhukXz3DA8/ONSnZUIBAqBtOCzsDNUgAsuILbCzvtDrn2oDxyq7DZx5Nh81pe0BeWmDQ==", + "dependencies": { + "System.Memory": "4.5.4" + } + }, "Azure.Extensions.AspNetCore.DataProtection.Blobs": { "type": "Transitive", "resolved": "1.3.2", @@ -121,6 +204,34 @@ "System.Threading.Tasks.Extensions": "4.5.4" } }, + "Azure.Messaging.EventHubs": { + "type": "Transitive", + "resolved": "5.7.4", + "contentHash": "8vC4efO5HzDgZjx6LaViScywbyKu3xIkL+y+QoyN7Yo6u1pEmMAPW4ptaWIj1JW4gypeWC1tFy+U3zdQ/E7bGA==", + "dependencies": { + "Azure.Core": "1.25.0", + "Azure.Core.Amqp": "1.2.0", + "Microsoft.Azure.Amqp": "2.5.12", + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Reflection.TypeExtensions": "4.7.0", + "System.Threading.Channels": "4.7.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Messaging.ServiceBus": { + "type": "Transitive", + "resolved": "7.11.1", + "contentHash": "ioGedXeH8KK4HdTDEyOzdgNbEXGstGItVljI1EKYsz08sgwej6LpODCZmwPR2ui1fjXBWt8Zea0RJT4d9LwlMg==", + "dependencies": { + "Azure.Core": "1.25.0", + "Azure.Core.Amqp": "1.2.0", + "Microsoft.Azure.Amqp": "2.5.12", + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Memory.Data": "1.0.2" + } + }, "Azure.Storage.Blobs": { "type": "Transitive", "resolved": "12.14.1", @@ -139,6 +250,15 @@ "System.IO.Hashing": "6.0.0" } }, + "Azure.Storage.Files.Shares": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "C747FRSZNe/L4hu1wrvzQImVaIfNDcZXfttaV3FwX96+TsbgXotHe6Y0lmSu65H/gVYKt07sIW9E1mDi3bdADw==", + "dependencies": { + "Azure.Storage.Common": "12.12.0", + "System.Text.Json": "4.7.2" + } + }, "Azure.Storage.Queues": { "type": "Transitive", "resolved": "12.12.0", @@ -389,12 +509,8 @@ }, "Microsoft.Azure.Amqp": { "type": "Transitive", - "resolved": "2.4.11", - "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", - "dependencies": { - "System.Net.WebSockets.Client": "4.0.2", - "System.Runtime.Serialization.Primitives": "4.1.1" - } + "resolved": "2.5.12", + "contentHash": "0SlEl+TSQdpjXWf9/37dXWAa0zk6R1EJKmGtGZeKUAH7WEQpJOWMxJ9I43igcBCnTkFwa28CdPnpSCjFZVQlkw==" }, "Microsoft.Azure.Cosmos": { "type": "Transitive", @@ -722,6 +838,22 @@ "System.Text.Json": "6.0.0" } }, + "Microsoft.Extensions.Diagnostics.HealthChecks": { + "type": "Transitive", + "resolved": "6.0.10", + "contentHash": "YmTyFOc7xx2/9FKuAlCmcWYKYLr0bYgNrRlcNPy/vc8qXnxnRV+kua6z96RUXSJVSQadCbJcEjmnTUMTEVfXOQ==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "6.0.10", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.2", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": { + "type": "Transitive", + "resolved": "6.0.10", + "contentHash": "U1PO967am1BIWbxBiLcYzVx8KOTYa9NvhBNgTn8Oii3LcsjvIwHzM+GTYy6bTiHnAFAlK5HAjxusAnAHSHJRoA==" + }, "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -747,13 +879,12 @@ }, "Microsoft.Extensions.Hosting.Abstractions": { "type": "Transitive", - "resolved": "3.1.32", - "contentHash": "00J6eE920t5vfPnEHBSGyj1Ya9lG6WYsMwqvLZ0nMPPTD2UxkaL+FNJM5DNSnMFJtV84KkUudPRngmNiCkqhuA==", + "resolved": "6.0.0", + "contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.32", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.32", - "Microsoft.Extensions.FileProviders.Abstractions": "3.1.32", - "Microsoft.Extensions.Logging.Abstractions": "3.1.32" + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" } }, "Microsoft.Extensions.Http": { @@ -801,8 +932,8 @@ }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + "resolved": "6.0.2", + "contentHash": "pwXCZKaA7m5wgmCj49dW+H1RPSY7U62SKLTQYCcavf/k3Nyt/WnBgAjG4jMGnwy9rElfAZ2KvxvM5CJzJWG0hg==" }, "Microsoft.Extensions.Options": { "type": "Transitive", @@ -1423,10 +1554,23 @@ "SQLitePCLRaw.core": "2.1.2" } }, + "SSH.NET": { + "type": "Transitive", + "resolved": "2020.0.2", + "contentHash": "G0dNlTBAM00KZXv1wWVwgg26d9/METcM6qWBpNQwllzQmmbu+Zu+FS1L1X4fFgGdPu3e8k9mmTBu6SwtQ0614g==", + "dependencies": { + "SshNet.Security.Cryptography": "[1.3.0]" + } + }, + "SshNet.Security.Cryptography": { + "type": "Transitive", + "resolved": "1.3.0", + "contentHash": "5pBIXRjcSO/amY8WztpmNOhaaCNHY/B6CcYDI7FSTgqSyo/ZUojlLiKcsl+YGbxQuLX439qIkMfP0PHqxqJi/Q==" + }, "StackExchange.Redis": { "type": "Transitive", - "resolved": "2.5.43", - "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "resolved": "2.5.61", + "contentHash": "h1Gz4itrHL/PQ0GBLTEiPK8bBkOp5SFO6iaRFSSn/x1qltBWENsz/NUxPid6WHX9yf2Tiyzn9D3R7mtnksODxg==", "dependencies": { "Pipelines.Sockets.Unofficial": "2.2.2", "System.Diagnostics.PerformanceCounter": "5.0.0" @@ -2061,42 +2205,6 @@ "System.Runtime.Extensions": "4.1.0" } }, - "System.Net.WebSockets": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Threading.Tasks": "4.0.11" - } - }, - "System.Net.WebSockets.Client": { - "type": "Transitive", - "resolved": "4.0.2", - "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.2", - "Microsoft.Win32.Primitives": "4.0.1", - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Diagnostics.Tracing": "4.1.0", - "System.Globalization": "4.0.11", - "System.Net.Primitives": "4.0.11", - "System.Net.WebHeaderCollection": "4.0.1", - "System.Net.WebSockets": "4.0.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Security.Cryptography.X509Certificates": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11" - } - }, "System.Numerics.Vectors": { "type": "Transitive", "resolved": "4.5.0", @@ -2213,12 +2321,8 @@ }, "System.Reflection.TypeExtensions": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } + "resolved": "4.7.0", + "contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA==" }, "System.Resources.ResourceManager": { "type": "Transitive", @@ -2606,6 +2710,11 @@ "System.Threading.Tasks": "4.3.0" } }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "4.7.1", + "contentHash": "6akRtHK/wab3246t4p5v3HQrtQk8LboOt5T4dtpNgsp3zvDeM4/Gx8V12t0h+c/W9/enUrilk8n6EQqdQorZAA==" + }, "System.Threading.Overlapped": { "type": "Transitive", "resolved": "4.0.1", @@ -2798,85 +2907,85 @@ "commercial.core": { "type": "Project", "dependencies": { - "Core": "2023.3.0" + "Core": "[2023.5.0, )" } }, "commercial.infrastructure.entityframework": { "type": "Project", "dependencies": { - "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )", + "Core": "[2023.5.0, )", + "Infrastructure.EntityFramework": "[2023.5.0, )" } }, "core": { "type": "Project", "dependencies": { - "AWSSDK.SQS": "3.7.2.47", - "AWSSDK.SimpleEmail": "3.7.0.150", - "AspNetCoreRateLimit": "4.0.2", - "AspNetCoreRateLimit.Redis": "1.0.1", - "Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2", - "Azure.Storage.Blobs": "12.14.1", - "Azure.Storage.Queues": "12.12.0", - "BitPay.Light": "1.0.1907", - "Braintree": "5.12.0", - "DnsClient": "1.7.0", - "Fido2.AspNet": "3.0.1", - "Handlebars.Net": "2.1.2", - "IdentityServer4": "4.1.2", - "IdentityServer4.AccessTokenValidation": "3.0.1", - "LaunchDarkly.ServerSdk": "7.0.0", - "MailKit": "3.2.0", - "Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4", - "Microsoft.Azure.Cosmos.Table": "1.0.8", - "Microsoft.Azure.NotificationHubs": "4.1.0", - "Microsoft.Azure.ServiceBus": "5.2.0", - "Microsoft.Data.SqlClient": "5.0.1", - "Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1", - "Microsoft.Extensions.Configuration.UserSecrets": "6.0.1", - "Microsoft.Extensions.Identity.Stores": "6.0.4", - "Newtonsoft.Json": "13.0.1", - "Otp.NET": "1.2.2", - "Quartz": "3.4.0", - "SendGrid": "9.27.0", - "Sentry.Serilog": "3.16.0", - "Serilog.AspNetCore": "5.0.0", - "Serilog.Extensions.Logging": "3.1.0", - "Serilog.Extensions.Logging.File": "2.0.0", - "Serilog.Sinks.AzureCosmosDB": "2.0.0", - "Serilog.Sinks.SyslogMessages": "2.0.6", - "Stripe.net": "40.0.0", - "YubicoDotNetClient": "1.2.0" + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )", + "Azure.Storage.Blobs": "[12.14.1, )", + "Azure.Storage.Queues": "[12.12.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "DnsClient": "[1.7.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "LaunchDarkly.ServerSdk": "[7.0.0, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" } }, "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Dapper": "2.0.123" + "Core": "[2023.5.0, )", + "Dapper": "[2.0.123, )" } }, "infrastructure.entityframework": { "type": "Project", "dependencies": { - "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", - "Microsoft.EntityFrameworkCore.Relational": "6.0.12", - "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", - "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", - "Npgsql.EntityFrameworkCore.PostgreSQL": "6.0.8", - "Pomelo.EntityFrameworkCore.MySql": "6.0.2", - "linq2db.EntityFrameworkCore": "6.11.0" + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )", + "Core": "[2023.5.0, )", + "Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )", + "Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )", + "Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )", + "linq2db.EntityFrameworkCore": "[6.11.0, )" } }, "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "[2023.5.0, )", + "Infrastructure.Dapper": "[2023.5.0, )", + "Infrastructure.EntityFramework": "[2023.5.0, )" } } } diff --git a/src/Billing/packages.lock.json b/src/Billing/packages.lock.json index e53e007446..79daea5128 100644 --- a/src/Billing/packages.lock.json +++ b/src/Billing/packages.lock.json @@ -2786,7 +2786,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2794,7 +2794,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2806,9 +2806,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/src/Events/packages.lock.json b/src/Events/packages.lock.json index e53e007446..79daea5128 100644 --- a/src/Events/packages.lock.json +++ b/src/Events/packages.lock.json @@ -2786,7 +2786,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2794,7 +2794,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2806,9 +2806,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/src/EventsProcessor/packages.lock.json b/src/EventsProcessor/packages.lock.json index e53e007446..79daea5128 100644 --- a/src/EventsProcessor/packages.lock.json +++ b/src/EventsProcessor/packages.lock.json @@ -2786,7 +2786,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2794,7 +2794,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2806,9 +2806,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/src/Icons/packages.lock.json b/src/Icons/packages.lock.json index 0538d0f74f..606ce3fc30 100644 --- a/src/Icons/packages.lock.json +++ b/src/Icons/packages.lock.json @@ -2796,7 +2796,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2804,7 +2804,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2816,9 +2816,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/src/Identity/packages.lock.json b/src/Identity/packages.lock.json index 3c35872042..bcf1c0e8b4 100644 --- a/src/Identity/packages.lock.json +++ b/src/Identity/packages.lock.json @@ -2808,7 +2808,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2816,7 +2816,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2828,9 +2828,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/src/Notifications/packages.lock.json b/src/Notifications/packages.lock.json index 19c6dc1354..4d16450e93 100644 --- a/src/Notifications/packages.lock.json +++ b/src/Notifications/packages.lock.json @@ -2836,7 +2836,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2844,7 +2844,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2856,9 +2856,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/src/SharedWeb/Health/HealthCheckServiceExtensions.cs b/src/SharedWeb/Health/HealthCheckServiceExtensions.cs new file mode 100644 index 0000000000..9be369c676 --- /dev/null +++ b/src/SharedWeb/Health/HealthCheckServiceExtensions.cs @@ -0,0 +1,60 @@ +using System.Text; +using System.Text.Json; +using Bit.Core.Settings; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Bit.SharedWeb.Health; + +public static class HealthCheckServiceExtensions +{ + public static void AddHealthCheckServices(this IServiceCollection services, GlobalSettings globalSettings, + Action addBuilder = null) + { + var builder = services.AddHealthChecks(); + addBuilder?.Invoke(builder); + } + + public static Task WriteResponse(HttpContext context, HealthReport healthReport) + { + context.Response.ContentType = "application/json; charset=utf-8"; + + var options = new JsonWriterOptions { Indented = true }; + + using var memoryStream = new MemoryStream(); + using (var jsonWriter = new Utf8JsonWriter(memoryStream, options)) + { + jsonWriter.WriteStartObject(); + jsonWriter.WriteString("status", healthReport.Status.ToString()); + jsonWriter.WriteStartObject("results"); + + foreach (var healthReportEntry in healthReport.Entries) + { + jsonWriter.WriteStartObject(healthReportEntry.Key); + jsonWriter.WriteString("status", + healthReportEntry.Value.Status.ToString()); + jsonWriter.WriteString("description", + healthReportEntry.Value.Description ?? healthReportEntry.Value.Exception?.Message); + jsonWriter.WriteStartObject("data"); + + foreach (var item in healthReportEntry.Value.Data) + { + jsonWriter.WritePropertyName(item.Key); + + JsonSerializer.Serialize(jsonWriter, item.Value, + item.Value?.GetType() ?? typeof(object)); + } + + jsonWriter.WriteEndObject(); + jsonWriter.WriteEndObject(); + } + + jsonWriter.WriteEndObject(); + jsonWriter.WriteEndObject(); + } + + return context.Response.WriteAsync( + Encoding.UTF8.GetString(memoryStream.ToArray())); + } +} diff --git a/src/SharedWeb/packages.lock.json b/src/SharedWeb/packages.lock.json index d6dfb7ff41..db03af92cd 100644 --- a/src/SharedWeb/packages.lock.json +++ b/src/SharedWeb/packages.lock.json @@ -2786,7 +2786,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2794,7 +2794,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", diff --git a/test/Api.IntegrationTest/packages.lock.json b/test/Api.IntegrationTest/packages.lock.json index d464a72320..427d253dc9 100644 --- a/test/Api.IntegrationTest/packages.lock.json +++ b/test/Api.IntegrationTest/packages.lock.json @@ -35,6 +35,74 @@ "resolved": "2.4.3", "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" }, + "AspNetCore.HealthChecks.AzureServiceBus": { + "type": "Transitive", + "resolved": "6.1.0", + "contentHash": "LepLE6NO4bLBVDzlx/730pD6jnfkV6zaaRUrbN1LqnNk4m1hROsv7wOpgbKgVDgYIfeLzdiVnBviEevSxWFKMQ==", + "dependencies": { + "Azure.Messaging.EventHubs": "5.7.4", + "Azure.Messaging.ServiceBus": "7.11.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.10" + } + }, + "AspNetCore.HealthChecks.AzureStorage": { + "type": "Transitive", + "resolved": "6.1.2", + "contentHash": "R/uHJ40Cc0fBLi48SqDtT6fHyR5G8L3+PeKlbe8t498GLebeBIR3ve4l4n7UzCD0qgmQDDvyIYvVywx3i5Y6Ng==", + "dependencies": { + "Azure.Storage.Blobs": "12.14.1", + "Azure.Storage.Files.Shares": "12.11.0", + "Azure.Storage.Queues": "12.11.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.10" + } + }, + "AspNetCore.HealthChecks.Network": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "rvoPkqlvhX1HW6dpqjE1rbvmmMo9v7+Uf9dJffEcd3mA/DyyEitlZFc6cwYtmZVFdgy2gbIU4ubs3654nVfvjA==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.7", + "SSH.NET": "2020.0.2", + "System.Buffers": "4.5.1" + } + }, + "AspNetCore.HealthChecks.Redis": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "adNNWF6kV8v1HLTmF3b9F5K6ubvgx+S7VqhzA8T/5YuIpRWsCDk8+q3RIDDV8Twvl9pRahLfzCbFrPYxvzmk7g==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.4", + "StackExchange.Redis": "2.5.61" + } + }, + "AspNetCore.HealthChecks.SendGrid": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "VgskjkCUmSpAxil20rZlrj14bMi9aFNdiGLDtDTKjkUU0GYkoyi4HRVEy9Gp0FIgu9ce7quN+dNCpydKvMxjqA==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.2", + "Microsoft.Extensions.Http": "6.0.0", + "SendGrid": "9.24.4" + } + }, + "AspNetCore.HealthChecks.SqlServer": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "Af7ws27DnZZ4bKCiEREm7emSAKEtIiYirEAkI0ixFgK1fwJ99jmMnPC+kU01zfqn3FyCO/gZOUO7WbyVvTPpFg==", + "dependencies": { + "Microsoft.Data.SqlClient": "3.0.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.0" + } + }, + "AspNetCore.HealthChecks.Uris": { + "type": "Transitive", + "resolved": "6.0.3", + "contentHash": "EY0Vh8s2UrbnyvM/QhbyYuCnbrBw36BKkdh5LqdINxqAGnlPFQXf+/UoNlH/76MTEyg+nvdp2wjr5MqWDkVFaQ==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.0", + "Microsoft.Extensions.Http": "6.0.0" + } + }, "AspNetCoreRateLimit": { "type": "Transitive", "resolved": "4.0.2", @@ -134,6 +202,14 @@ "System.Threading.Tasks.Extensions": "4.5.4" } }, + "Azure.Core.Amqp": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "vrF4isvhwdZspzorLwYhukXz3DA8/ONSnZUIBAqBtOCzsDNUgAsuILbCzvtDrn2oDxyq7DZx5Nh81pe0BeWmDQ==", + "dependencies": { + "System.Memory": "4.5.4" + } + }, "Azure.Extensions.AspNetCore.DataProtection.Blobs": { "type": "Transitive", "resolved": "1.3.2", @@ -168,6 +244,34 @@ "System.Text.Json": "4.7.2" } }, + "Azure.Messaging.EventHubs": { + "type": "Transitive", + "resolved": "5.7.4", + "contentHash": "8vC4efO5HzDgZjx6LaViScywbyKu3xIkL+y+QoyN7Yo6u1pEmMAPW4ptaWIj1JW4gypeWC1tFy+U3zdQ/E7bGA==", + "dependencies": { + "Azure.Core": "1.25.0", + "Azure.Core.Amqp": "1.2.0", + "Microsoft.Azure.Amqp": "2.5.12", + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Reflection.TypeExtensions": "4.7.0", + "System.Threading.Channels": "4.7.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Messaging.ServiceBus": { + "type": "Transitive", + "resolved": "7.11.1", + "contentHash": "ioGedXeH8KK4HdTDEyOzdgNbEXGstGItVljI1EKYsz08sgwej6LpODCZmwPR2ui1fjXBWt8Zea0RJT4d9LwlMg==", + "dependencies": { + "Azure.Core": "1.25.0", + "Azure.Core.Amqp": "1.2.0", + "Microsoft.Azure.Amqp": "2.5.12", + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Memory.Data": "1.0.2" + } + }, "Azure.Storage.Blobs": { "type": "Transitive", "resolved": "12.14.1", @@ -186,6 +290,15 @@ "System.IO.Hashing": "6.0.0" } }, + "Azure.Storage.Files.Shares": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "C747FRSZNe/L4hu1wrvzQImVaIfNDcZXfttaV3FwX96+TsbgXotHe6Y0lmSu65H/gVYKt07sIW9E1mDi3bdADw==", + "dependencies": { + "Azure.Storage.Common": "12.12.0", + "System.Text.Json": "4.7.2" + } + }, "Azure.Storage.Queues": { "type": "Transitive", "resolved": "12.12.0", @@ -488,12 +601,8 @@ }, "Microsoft.Azure.Amqp": { "type": "Transitive", - "resolved": "2.4.11", - "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", - "dependencies": { - "System.Net.WebSockets.Client": "4.0.2", - "System.Runtime.Serialization.Primitives": "4.1.1" - } + "resolved": "2.5.12", + "contentHash": "0SlEl+TSQdpjXWf9/37dXWAa0zk6R1EJKmGtGZeKUAH7WEQpJOWMxJ9I43igcBCnTkFwa28CdPnpSCjFZVQlkw==" }, "Microsoft.Azure.Cosmos": { "type": "Transitive", @@ -843,6 +952,22 @@ "System.Text.Json": "6.0.0" } }, + "Microsoft.Extensions.Diagnostics.HealthChecks": { + "type": "Transitive", + "resolved": "6.0.10", + "contentHash": "YmTyFOc7xx2/9FKuAlCmcWYKYLr0bYgNrRlcNPy/vc8qXnxnRV+kua6z96RUXSJVSQadCbJcEjmnTUMTEVfXOQ==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "6.0.10", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.2", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": { + "type": "Transitive", + "resolved": "6.0.10", + "contentHash": "U1PO967am1BIWbxBiLcYzVx8KOTYa9NvhBNgTn8Oii3LcsjvIwHzM+GTYy6bTiHnAFAlK5HAjxusAnAHSHJRoA==" + }, "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -949,8 +1074,8 @@ }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + "resolved": "6.0.2", + "contentHash": "pwXCZKaA7m5wgmCj49dW+H1RPSY7U62SKLTQYCcavf/k3Nyt/WnBgAjG4jMGnwy9rElfAZ2KvxvM5CJzJWG0hg==" }, "Microsoft.Extensions.Logging.Configuration": { "type": "Transitive", @@ -1672,10 +1797,23 @@ "SQLitePCLRaw.core": "2.1.2" } }, + "SSH.NET": { + "type": "Transitive", + "resolved": "2020.0.2", + "contentHash": "G0dNlTBAM00KZXv1wWVwgg26d9/METcM6qWBpNQwllzQmmbu+Zu+FS1L1X4fFgGdPu3e8k9mmTBu6SwtQ0614g==", + "dependencies": { + "SshNet.Security.Cryptography": "[1.3.0]" + } + }, + "SshNet.Security.Cryptography": { + "type": "Transitive", + "resolved": "1.3.0", + "contentHash": "5pBIXRjcSO/amY8WztpmNOhaaCNHY/B6CcYDI7FSTgqSyo/ZUojlLiKcsl+YGbxQuLX439qIkMfP0PHqxqJi/Q==" + }, "StackExchange.Redis": { "type": "Transitive", - "resolved": "2.5.43", - "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "resolved": "2.5.61", + "contentHash": "h1Gz4itrHL/PQ0GBLTEiPK8bBkOp5SFO6iaRFSSn/x1qltBWENsz/NUxPid6WHX9yf2Tiyzn9D3R7mtnksODxg==", "dependencies": { "Pipelines.Sockets.Unofficial": "2.2.2", "System.Diagnostics.PerformanceCounter": "5.0.0" @@ -2383,42 +2521,6 @@ "System.Runtime.Extensions": "4.1.0" } }, - "System.Net.WebSockets": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Threading.Tasks": "4.0.11" - } - }, - "System.Net.WebSockets.Client": { - "type": "Transitive", - "resolved": "4.0.2", - "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.2", - "Microsoft.Win32.Primitives": "4.0.1", - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Diagnostics.Tracing": "4.1.0", - "System.Globalization": "4.0.11", - "System.Net.Primitives": "4.0.11", - "System.Net.WebHeaderCollection": "4.0.1", - "System.Net.WebSockets": "4.0.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Security.Cryptography.X509Certificates": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11" - } - }, "System.Numerics.Vectors": { "type": "Transitive", "resolved": "4.5.0", @@ -2540,12 +2642,8 @@ }, "System.Reflection.TypeExtensions": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } + "resolved": "4.7.0", + "contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA==" }, "System.Resources.ResourceManager": { "type": "Transitive", @@ -2933,6 +3031,11 @@ "System.Threading.Tasks": "4.3.0" } }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "4.7.1", + "contentHash": "6akRtHK/wab3246t4p5v3HQrtQk8LboOt5T4dtpNgsp3zvDeM4/Gx8V12t0h+c/W9/enUrilk8n6EQqdQorZAA==" + }, "System.Threading.Overlapped": { "type": "Transitive", "resolved": "4.0.1", @@ -3170,126 +3273,133 @@ "api": { "type": "Project", "dependencies": { - "Azure.Messaging.EventGrid": "4.10.0", - "Commercial.Core": "2023.3.0", - "Commercial.Infrastructure.EntityFramework": "2023.3.0", - "Core": "2023.3.0", - "SharedWeb": "2023.3.0", - "Swashbuckle.AspNetCore": "6.5.0" + "AspNetCore.HealthChecks.AzureServiceBus": "[6.1.0, )", + "AspNetCore.HealthChecks.AzureStorage": "[6.1.2, )", + "AspNetCore.HealthChecks.Network": "[6.0.4, )", + "AspNetCore.HealthChecks.Redis": "[6.0.4, )", + "AspNetCore.HealthChecks.SendGrid": "[6.0.2, )", + "AspNetCore.HealthChecks.SqlServer": "[6.0.2, )", + "AspNetCore.HealthChecks.Uris": "[6.0.3, )", + "Azure.Messaging.EventGrid": "[4.10.0, )", + "Commercial.Core": "[2023.5.0, )", + "Commercial.Infrastructure.EntityFramework": "[2023.5.0, )", + "Core": "[2023.5.0, )", + "SharedWeb": "[2023.5.0, )", + "Swashbuckle.AspNetCore": "[6.5.0, )" } }, "commercial.core": { "type": "Project", "dependencies": { - "Core": "2023.3.0" + "Core": "[2023.5.0, )" } }, "commercial.infrastructure.entityframework": { "type": "Project", "dependencies": { - "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )", + "Core": "[2023.5.0, )", + "Infrastructure.EntityFramework": "[2023.5.0, )" } }, "common": { "type": "Project", "dependencies": { - "AutoFixture.AutoNSubstitute": "4.17.0", - "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", - "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", - "Microsoft.NET.Test.Sdk": "17.1.0", - "NSubstitute": "4.3.0", - "xunit": "2.4.1" + "AutoFixture.AutoNSubstitute": "[4.17.0, )", + "AutoFixture.Xunit2": "[4.17.0, )", + "Core": "[2023.5.0, )", + "Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "NSubstitute": "[4.3.0, )", + "xunit": "[2.4.1, )" } }, "core": { "type": "Project", "dependencies": { - "AWSSDK.SQS": "3.7.2.47", - "AWSSDK.SimpleEmail": "3.7.0.150", - "AspNetCoreRateLimit": "4.0.2", - "AspNetCoreRateLimit.Redis": "1.0.1", - "Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2", - "Azure.Storage.Blobs": "12.14.1", - "Azure.Storage.Queues": "12.12.0", - "BitPay.Light": "1.0.1907", - "Braintree": "5.12.0", - "DnsClient": "1.7.0", - "Fido2.AspNet": "3.0.1", - "Handlebars.Net": "2.1.2", - "IdentityServer4": "4.1.2", - "IdentityServer4.AccessTokenValidation": "3.0.1", - "LaunchDarkly.ServerSdk": "7.0.0", - "MailKit": "3.2.0", - "Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4", - "Microsoft.Azure.Cosmos.Table": "1.0.8", - "Microsoft.Azure.NotificationHubs": "4.1.0", - "Microsoft.Azure.ServiceBus": "5.2.0", - "Microsoft.Data.SqlClient": "5.0.1", - "Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1", - "Microsoft.Extensions.Configuration.UserSecrets": "6.0.1", - "Microsoft.Extensions.Identity.Stores": "6.0.4", - "Newtonsoft.Json": "13.0.1", - "Otp.NET": "1.2.2", - "Quartz": "3.4.0", - "SendGrid": "9.27.0", - "Sentry.Serilog": "3.16.0", - "Serilog.AspNetCore": "5.0.0", - "Serilog.Extensions.Logging": "3.1.0", - "Serilog.Extensions.Logging.File": "2.0.0", - "Serilog.Sinks.AzureCosmosDB": "2.0.0", - "Serilog.Sinks.SyslogMessages": "2.0.6", - "Stripe.net": "40.0.0", - "YubicoDotNetClient": "1.2.0" + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )", + "Azure.Storage.Blobs": "[12.14.1, )", + "Azure.Storage.Queues": "[12.12.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "DnsClient": "[1.7.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "LaunchDarkly.ServerSdk": "[7.0.0, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" } }, "identity": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "SharedWeb": "2023.3.0", - "Swashbuckle.AspNetCore.SwaggerGen": "6.5.0" + "Core": "[2023.5.0, )", + "SharedWeb": "[2023.5.0, )", + "Swashbuckle.AspNetCore.SwaggerGen": "[6.5.0, )" } }, "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Dapper": "2.0.123" + "Core": "[2023.5.0, )", + "Dapper": "[2.0.123, )" } }, "infrastructure.entityframework": { "type": "Project", "dependencies": { - "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", - "Microsoft.EntityFrameworkCore.Relational": "6.0.12", - "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", - "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", - "Npgsql.EntityFrameworkCore.PostgreSQL": "6.0.8", - "Pomelo.EntityFrameworkCore.MySql": "6.0.2", - "linq2db.EntityFrameworkCore": "6.11.0" + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )", + "Core": "[2023.5.0, )", + "Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )", + "Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )", + "Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )", + "linq2db.EntityFrameworkCore": "[6.11.0, )" } }, "integrationtestcommon": { "type": "Project", "dependencies": { - "Common": "2023.3.0", - "Identity": "2023.3.0", - "Microsoft.AspNetCore.Mvc.Testing": "6.0.5", - "Microsoft.EntityFrameworkCore.InMemory": "6.0.5", - "Microsoft.Extensions.Configuration": "6.0.1" + "Common": "[2023.5.0, )", + "Identity": "[2023.5.0, )", + "Microsoft.AspNetCore.Mvc.Testing": "[6.0.5, )", + "Microsoft.EntityFrameworkCore.InMemory": "[6.0.5, )", + "Microsoft.Extensions.Configuration": "[6.0.1, )" } }, "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "[2023.5.0, )", + "Infrastructure.Dapper": "[2023.5.0, )", + "Infrastructure.EntityFramework": "[2023.5.0, )" } } } diff --git a/test/Api.Test/packages.lock.json b/test/Api.Test/packages.lock.json index da16df5d7b..c5bde98fde 100644 --- a/test/Api.Test/packages.lock.json +++ b/test/Api.Test/packages.lock.json @@ -54,6 +54,74 @@ "resolved": "2.4.3", "contentHash": "kZZSmOmKA8OBlAJaquPXnJJLM9RwQ27H7BMVqfMLUcTi9xHinWGJiWksa3D4NEtz0wZ/nxd2mogObvBgJKCRhQ==" }, + "AspNetCore.HealthChecks.AzureServiceBus": { + "type": "Transitive", + "resolved": "6.1.0", + "contentHash": "LepLE6NO4bLBVDzlx/730pD6jnfkV6zaaRUrbN1LqnNk4m1hROsv7wOpgbKgVDgYIfeLzdiVnBviEevSxWFKMQ==", + "dependencies": { + "Azure.Messaging.EventHubs": "5.7.4", + "Azure.Messaging.ServiceBus": "7.11.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.10" + } + }, + "AspNetCore.HealthChecks.AzureStorage": { + "type": "Transitive", + "resolved": "6.1.2", + "contentHash": "R/uHJ40Cc0fBLi48SqDtT6fHyR5G8L3+PeKlbe8t498GLebeBIR3ve4l4n7UzCD0qgmQDDvyIYvVywx3i5Y6Ng==", + "dependencies": { + "Azure.Storage.Blobs": "12.14.1", + "Azure.Storage.Files.Shares": "12.11.0", + "Azure.Storage.Queues": "12.11.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.10" + } + }, + "AspNetCore.HealthChecks.Network": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "rvoPkqlvhX1HW6dpqjE1rbvmmMo9v7+Uf9dJffEcd3mA/DyyEitlZFc6cwYtmZVFdgy2gbIU4ubs3654nVfvjA==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.7", + "SSH.NET": "2020.0.2", + "System.Buffers": "4.5.1" + } + }, + "AspNetCore.HealthChecks.Redis": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "adNNWF6kV8v1HLTmF3b9F5K6ubvgx+S7VqhzA8T/5YuIpRWsCDk8+q3RIDDV8Twvl9pRahLfzCbFrPYxvzmk7g==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.4", + "StackExchange.Redis": "2.5.61" + } + }, + "AspNetCore.HealthChecks.SendGrid": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "VgskjkCUmSpAxil20rZlrj14bMi9aFNdiGLDtDTKjkUU0GYkoyi4HRVEy9Gp0FIgu9ce7quN+dNCpydKvMxjqA==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.2", + "Microsoft.Extensions.Http": "6.0.0", + "SendGrid": "9.24.4" + } + }, + "AspNetCore.HealthChecks.SqlServer": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "Af7ws27DnZZ4bKCiEREm7emSAKEtIiYirEAkI0ixFgK1fwJ99jmMnPC+kU01zfqn3FyCO/gZOUO7WbyVvTPpFg==", + "dependencies": { + "Microsoft.Data.SqlClient": "3.0.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.0" + } + }, + "AspNetCore.HealthChecks.Uris": { + "type": "Transitive", + "resolved": "6.0.3", + "contentHash": "EY0Vh8s2UrbnyvM/QhbyYuCnbrBw36BKkdh5LqdINxqAGnlPFQXf+/UoNlH/76MTEyg+nvdp2wjr5MqWDkVFaQ==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.0", + "Microsoft.Extensions.Http": "6.0.0" + } + }, "AspNetCoreRateLimit": { "type": "Transitive", "resolved": "4.0.2", @@ -144,6 +212,14 @@ "System.Threading.Tasks.Extensions": "4.5.4" } }, + "Azure.Core.Amqp": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "vrF4isvhwdZspzorLwYhukXz3DA8/ONSnZUIBAqBtOCzsDNUgAsuILbCzvtDrn2oDxyq7DZx5Nh81pe0BeWmDQ==", + "dependencies": { + "System.Memory": "4.5.4" + } + }, "Azure.Extensions.AspNetCore.DataProtection.Blobs": { "type": "Transitive", "resolved": "1.3.2", @@ -178,6 +254,34 @@ "System.Text.Json": "4.7.2" } }, + "Azure.Messaging.EventHubs": { + "type": "Transitive", + "resolved": "5.7.4", + "contentHash": "8vC4efO5HzDgZjx6LaViScywbyKu3xIkL+y+QoyN7Yo6u1pEmMAPW4ptaWIj1JW4gypeWC1tFy+U3zdQ/E7bGA==", + "dependencies": { + "Azure.Core": "1.25.0", + "Azure.Core.Amqp": "1.2.0", + "Microsoft.Azure.Amqp": "2.5.12", + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Reflection.TypeExtensions": "4.7.0", + "System.Threading.Channels": "4.7.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Messaging.ServiceBus": { + "type": "Transitive", + "resolved": "7.11.1", + "contentHash": "ioGedXeH8KK4HdTDEyOzdgNbEXGstGItVljI1EKYsz08sgwej6LpODCZmwPR2ui1fjXBWt8Zea0RJT4d9LwlMg==", + "dependencies": { + "Azure.Core": "1.25.0", + "Azure.Core.Amqp": "1.2.0", + "Microsoft.Azure.Amqp": "2.5.12", + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Memory.Data": "1.0.2" + } + }, "Azure.Storage.Blobs": { "type": "Transitive", "resolved": "12.14.1", @@ -196,6 +300,15 @@ "System.IO.Hashing": "6.0.0" } }, + "Azure.Storage.Files.Shares": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "C747FRSZNe/L4hu1wrvzQImVaIfNDcZXfttaV3FwX96+TsbgXotHe6Y0lmSu65H/gVYKt07sIW9E1mDi3bdADw==", + "dependencies": { + "Azure.Storage.Common": "12.12.0", + "System.Text.Json": "4.7.2" + } + }, "Azure.Storage.Queues": { "type": "Transitive", "resolved": "12.12.0", @@ -480,12 +593,8 @@ }, "Microsoft.Azure.Amqp": { "type": "Transitive", - "resolved": "2.4.11", - "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", - "dependencies": { - "System.Net.WebSockets.Client": "4.0.2", - "System.Runtime.Serialization.Primitives": "4.1.1" - } + "resolved": "2.5.12", + "contentHash": "0SlEl+TSQdpjXWf9/37dXWAa0zk6R1EJKmGtGZeKUAH7WEQpJOWMxJ9I43igcBCnTkFwa28CdPnpSCjFZVQlkw==" }, "Microsoft.Azure.Cosmos": { "type": "Transitive", @@ -818,6 +927,22 @@ "System.Text.Json": "6.0.0" } }, + "Microsoft.Extensions.Diagnostics.HealthChecks": { + "type": "Transitive", + "resolved": "6.0.10", + "contentHash": "YmTyFOc7xx2/9FKuAlCmcWYKYLr0bYgNrRlcNPy/vc8qXnxnRV+kua6z96RUXSJVSQadCbJcEjmnTUMTEVfXOQ==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "6.0.10", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.2", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": { + "type": "Transitive", + "resolved": "6.0.10", + "contentHash": "U1PO967am1BIWbxBiLcYzVx8KOTYa9NvhBNgTn8Oii3LcsjvIwHzM+GTYy6bTiHnAFAlK5HAjxusAnAHSHJRoA==" + }, "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -843,13 +968,12 @@ }, "Microsoft.Extensions.Hosting.Abstractions": { "type": "Transitive", - "resolved": "3.1.32", - "contentHash": "00J6eE920t5vfPnEHBSGyj1Ya9lG6WYsMwqvLZ0nMPPTD2UxkaL+FNJM5DNSnMFJtV84KkUudPRngmNiCkqhuA==", + "resolved": "6.0.0", + "contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.32", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.32", - "Microsoft.Extensions.FileProviders.Abstractions": "3.1.32", - "Microsoft.Extensions.Logging.Abstractions": "3.1.32" + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" } }, "Microsoft.Extensions.Http": { @@ -897,8 +1021,8 @@ }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + "resolved": "6.0.2", + "contentHash": "pwXCZKaA7m5wgmCj49dW+H1RPSY7U62SKLTQYCcavf/k3Nyt/WnBgAjG4jMGnwy9rElfAZ2KvxvM5CJzJWG0hg==" }, "Microsoft.Extensions.Options": { "type": "Transitive", @@ -1556,10 +1680,23 @@ "SQLitePCLRaw.core": "2.1.2" } }, + "SSH.NET": { + "type": "Transitive", + "resolved": "2020.0.2", + "contentHash": "G0dNlTBAM00KZXv1wWVwgg26d9/METcM6qWBpNQwllzQmmbu+Zu+FS1L1X4fFgGdPu3e8k9mmTBu6SwtQ0614g==", + "dependencies": { + "SshNet.Security.Cryptography": "[1.3.0]" + } + }, + "SshNet.Security.Cryptography": { + "type": "Transitive", + "resolved": "1.3.0", + "contentHash": "5pBIXRjcSO/amY8WztpmNOhaaCNHY/B6CcYDI7FSTgqSyo/ZUojlLiKcsl+YGbxQuLX439qIkMfP0PHqxqJi/Q==" + }, "StackExchange.Redis": { "type": "Transitive", - "resolved": "2.5.43", - "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "resolved": "2.5.61", + "contentHash": "h1Gz4itrHL/PQ0GBLTEiPK8bBkOp5SFO6iaRFSSn/x1qltBWENsz/NUxPid6WHX9yf2Tiyzn9D3R7mtnksODxg==", "dependencies": { "Pipelines.Sockets.Unofficial": "2.2.2", "System.Diagnostics.PerformanceCounter": "5.0.0" @@ -2262,42 +2399,6 @@ "System.Runtime.Extensions": "4.1.0" } }, - "System.Net.WebSockets": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Threading.Tasks": "4.0.11" - } - }, - "System.Net.WebSockets.Client": { - "type": "Transitive", - "resolved": "4.0.2", - "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.2", - "Microsoft.Win32.Primitives": "4.0.1", - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Diagnostics.Tracing": "4.1.0", - "System.Globalization": "4.0.11", - "System.Net.Primitives": "4.0.11", - "System.Net.WebHeaderCollection": "4.0.1", - "System.Net.WebSockets": "4.0.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Security.Cryptography.X509Certificates": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11" - } - }, "System.Numerics.Vectors": { "type": "Transitive", "resolved": "4.5.0", @@ -2419,12 +2520,8 @@ }, "System.Reflection.TypeExtensions": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } + "resolved": "4.7.0", + "contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA==" }, "System.Resources.ResourceManager": { "type": "Transitive", @@ -2812,6 +2909,11 @@ "System.Threading.Tasks": "4.3.0" } }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "4.7.1", + "contentHash": "6akRtHK/wab3246t4p5v3HQrtQk8LboOt5T4dtpNgsp3zvDeM4/Gx8V12t0h+c/W9/enUrilk8n6EQqdQorZAA==" + }, "System.Threading.Overlapped": { "type": "Transitive", "resolved": "4.0.1", @@ -3049,122 +3151,129 @@ "api": { "type": "Project", "dependencies": { - "Azure.Messaging.EventGrid": "4.10.0", - "Commercial.Core": "2023.3.0", - "Commercial.Infrastructure.EntityFramework": "2023.3.0", - "Core": "2023.3.0", - "SharedWeb": "2023.3.0", - "Swashbuckle.AspNetCore": "6.5.0" + "AspNetCore.HealthChecks.AzureServiceBus": "[6.1.0, )", + "AspNetCore.HealthChecks.AzureStorage": "[6.1.2, )", + "AspNetCore.HealthChecks.Network": "[6.0.4, )", + "AspNetCore.HealthChecks.Redis": "[6.0.4, )", + "AspNetCore.HealthChecks.SendGrid": "[6.0.2, )", + "AspNetCore.HealthChecks.SqlServer": "[6.0.2, )", + "AspNetCore.HealthChecks.Uris": "[6.0.3, )", + "Azure.Messaging.EventGrid": "[4.10.0, )", + "Commercial.Core": "[2023.5.0, )", + "Commercial.Infrastructure.EntityFramework": "[2023.5.0, )", + "Core": "[2023.5.0, )", + "SharedWeb": "[2023.5.0, )", + "Swashbuckle.AspNetCore": "[6.5.0, )" } }, "commercial.core": { "type": "Project", "dependencies": { - "Core": "2023.3.0" + "Core": "[2023.5.0, )" } }, "commercial.infrastructure.entityframework": { "type": "Project", "dependencies": { - "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )", + "Core": "[2023.5.0, )", + "Infrastructure.EntityFramework": "[2023.5.0, )" } }, "common": { "type": "Project", "dependencies": { - "AutoFixture.AutoNSubstitute": "4.17.0", - "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", - "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", - "Microsoft.NET.Test.Sdk": "17.1.0", - "NSubstitute": "4.3.0", - "xunit": "2.4.1" + "AutoFixture.AutoNSubstitute": "[4.17.0, )", + "AutoFixture.Xunit2": "[4.17.0, )", + "Core": "[2023.5.0, )", + "Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "NSubstitute": "[4.3.0, )", + "xunit": "[2.4.1, )" } }, "core": { "type": "Project", "dependencies": { - "AWSSDK.SQS": "3.7.2.47", - "AWSSDK.SimpleEmail": "3.7.0.150", - "AspNetCoreRateLimit": "4.0.2", - "AspNetCoreRateLimit.Redis": "1.0.1", - "Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2", - "Azure.Storage.Blobs": "12.14.1", - "Azure.Storage.Queues": "12.12.0", - "BitPay.Light": "1.0.1907", - "Braintree": "5.12.0", - "DnsClient": "1.7.0", - "Fido2.AspNet": "3.0.1", - "Handlebars.Net": "2.1.2", - "IdentityServer4": "4.1.2", - "IdentityServer4.AccessTokenValidation": "3.0.1", - "LaunchDarkly.ServerSdk": "7.0.0", - "MailKit": "3.2.0", - "Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4", - "Microsoft.Azure.Cosmos.Table": "1.0.8", - "Microsoft.Azure.NotificationHubs": "4.1.0", - "Microsoft.Azure.ServiceBus": "5.2.0", - "Microsoft.Data.SqlClient": "5.0.1", - "Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1", - "Microsoft.Extensions.Configuration.UserSecrets": "6.0.1", - "Microsoft.Extensions.Identity.Stores": "6.0.4", - "Newtonsoft.Json": "13.0.1", - "Otp.NET": "1.2.2", - "Quartz": "3.4.0", - "SendGrid": "9.27.0", - "Sentry.Serilog": "3.16.0", - "Serilog.AspNetCore": "5.0.0", - "Serilog.Extensions.Logging": "3.1.0", - "Serilog.Extensions.Logging.File": "2.0.0", - "Serilog.Sinks.AzureCosmosDB": "2.0.0", - "Serilog.Sinks.SyslogMessages": "2.0.6", - "Stripe.net": "40.0.0", - "YubicoDotNetClient": "1.2.0" + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )", + "Azure.Storage.Blobs": "[12.14.1, )", + "Azure.Storage.Queues": "[12.12.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "DnsClient": "[1.7.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "LaunchDarkly.ServerSdk": "[7.0.0, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" } }, "core.test": { "type": "Project", "dependencies": { - "AutoFixture.AutoNSubstitute": "4.17.0", - "AutoFixture.Xunit2": "4.17.0", - "Common": "2023.3.0", - "Core": "2023.3.0", - "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", - "Microsoft.NET.Test.Sdk": "17.1.0", - "Moq": "4.17.2", - "NSubstitute": "4.3.0", - "xunit": "2.4.1" + "AutoFixture.AutoNSubstitute": "[4.17.0, )", + "AutoFixture.Xunit2": "[4.17.0, )", + "Common": "[2023.5.0, )", + "Core": "[2023.5.0, )", + "Kralizek.AutoFixture.Extensions.MockHttp": "[1.2.0, )", + "Microsoft.NET.Test.Sdk": "[17.1.0, )", + "Moq": "[4.17.2, )", + "NSubstitute": "[4.3.0, )", + "xunit": "[2.4.1, )" } }, "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Dapper": "2.0.123" + "Core": "[2023.5.0, )", + "Dapper": "[2.0.123, )" } }, "infrastructure.entityframework": { "type": "Project", "dependencies": { - "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", - "Microsoft.EntityFrameworkCore.Relational": "6.0.12", - "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", - "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", - "Npgsql.EntityFrameworkCore.PostgreSQL": "6.0.8", - "Pomelo.EntityFrameworkCore.MySql": "6.0.2", - "linq2db.EntityFrameworkCore": "6.11.0" + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )", + "Core": "[2023.5.0, )", + "Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )", + "Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )", + "Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )", + "linq2db.EntityFrameworkCore": "[6.11.0, )" } }, "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "[2023.5.0, )", + "Infrastructure.Dapper": "[2023.5.0, )", + "Infrastructure.EntityFramework": "[2023.5.0, )" } } } diff --git a/test/Billing.Test/packages.lock.json b/test/Billing.Test/packages.lock.json index 456fad9598..474bc52aec 100644 --- a/test/Billing.Test/packages.lock.json +++ b/test/Billing.Test/packages.lock.json @@ -2988,8 +2988,8 @@ "billing": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "SharedWeb": "2023.3.0" + "Core": "2023.4.3", + "SharedWeb": "2023.4.3" } }, "common": { @@ -2997,7 +2997,7 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "NSubstitute": "4.3.0", @@ -3049,7 +3049,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -3057,7 +3057,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -3069,9 +3069,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/test/Core.Test/packages.lock.json b/test/Core.Test/packages.lock.json index 0779d09152..dd605b4e62 100644 --- a/test/Core.Test/packages.lock.json +++ b/test/Core.Test/packages.lock.json @@ -2825,7 +2825,7 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "NSubstitute": "4.3.0", diff --git a/test/Icons.Test/packages.lock.json b/test/Icons.Test/packages.lock.json index 5584303deb..0c902100b4 100644 --- a/test/Icons.Test/packages.lock.json +++ b/test/Icons.Test/packages.lock.json @@ -2972,14 +2972,14 @@ "type": "Project", "dependencies": { "AngleSharp": "0.16.1", - "Core": "2023.3.0", - "SharedWeb": "2023.3.0" + "Core": "2023.4.3", + "SharedWeb": "2023.4.3" } }, "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2987,7 +2987,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -2999,9 +2999,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/test/Identity.IntegrationTest/packages.lock.json b/test/Identity.IntegrationTest/packages.lock.json index c7feb90f13..471e1da6a5 100644 --- a/test/Identity.IntegrationTest/packages.lock.json +++ b/test/Identity.IntegrationTest/packages.lock.json @@ -3144,7 +3144,7 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "NSubstitute": "4.3.0", @@ -3196,15 +3196,15 @@ "identity": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "SharedWeb": "2023.3.0", + "Core": "2023.4.3", + "SharedWeb": "2023.4.3", "Swashbuckle.AspNetCore.SwaggerGen": "6.5.0" } }, "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -3212,7 +3212,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -3224,8 +3224,8 @@ "integrationtestcommon": { "type": "Project", "dependencies": { - "Common": "2023.3.0", - "Identity": "2023.3.0", + "Common": "2023.4.3", + "Identity": "2023.4.3", "Microsoft.AspNetCore.Mvc.Testing": "6.0.5", "Microsoft.EntityFrameworkCore.InMemory": "6.0.5", "Microsoft.Extensions.Configuration": "6.0.1" @@ -3234,9 +3234,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/test/Identity.Test/packages.lock.json b/test/Identity.Test/packages.lock.json index aae8c8e33f..7df7684529 100644 --- a/test/Identity.Test/packages.lock.json +++ b/test/Identity.Test/packages.lock.json @@ -3011,7 +3011,7 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "NSubstitute": "4.3.0", @@ -3063,15 +3063,15 @@ "identity": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "SharedWeb": "2023.3.0", + "Core": "2023.4.3", + "SharedWeb": "2023.4.3", "Swashbuckle.AspNetCore.SwaggerGen": "6.5.0" } }, "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -3079,7 +3079,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -3091,9 +3091,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/test/Infrastructure.EFIntegration.Test/packages.lock.json b/test/Infrastructure.EFIntegration.Test/packages.lock.json index b14044d349..b0e5968c90 100644 --- a/test/Infrastructure.EFIntegration.Test/packages.lock.json +++ b/test/Infrastructure.EFIntegration.Test/packages.lock.json @@ -3001,7 +3001,7 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "NSubstitute": "4.3.0", @@ -3055,8 +3055,8 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Common": "2023.3.0", - "Core": "2023.3.0", + "Common": "2023.4.3", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "Moq": "4.17.2", @@ -3067,7 +3067,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -3075,7 +3075,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", diff --git a/test/Infrastructure.IntegrationTest/packages.lock.json b/test/Infrastructure.IntegrationTest/packages.lock.json index 34c6b87a97..7ae6c2b8fb 100644 --- a/test/Infrastructure.IntegrationTest/packages.lock.json +++ b/test/Infrastructure.IntegrationTest/packages.lock.json @@ -2901,7 +2901,7 @@ "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -2909,7 +2909,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", diff --git a/test/IntegrationTestCommon/packages.lock.json b/test/IntegrationTestCommon/packages.lock.json index aefb843b5b..fee97803ee 100644 --- a/test/IntegrationTestCommon/packages.lock.json +++ b/test/IntegrationTestCommon/packages.lock.json @@ -3130,7 +3130,7 @@ "dependencies": { "AutoFixture.AutoNSubstitute": "4.17.0", "AutoFixture.Xunit2": "4.17.0", - "Core": "2023.3.0", + "Core": "2023.4.3", "Kralizek.AutoFixture.Extensions.MockHttp": "1.2.0", "Microsoft.NET.Test.Sdk": "17.1.0", "NSubstitute": "4.3.0", @@ -3182,15 +3182,15 @@ "identity": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "SharedWeb": "2023.3.0", + "Core": "2023.4.3", + "SharedWeb": "2023.4.3", "Swashbuckle.AspNetCore.SwaggerGen": "6.5.0" } }, "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Dapper": "2.0.123" } }, @@ -3198,7 +3198,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", @@ -3210,9 +3210,9 @@ "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "2023.4.3", + "Infrastructure.Dapper": "2023.4.3", + "Infrastructure.EntityFramework": "2023.4.3" } } } diff --git a/util/MsSqlMigratorUtility/packages.lock.json b/util/MsSqlMigratorUtility/packages.lock.json index 89fbf31e7e..7489bc4272 100644 --- a/util/MsSqlMigratorUtility/packages.lock.json +++ b/util/MsSqlMigratorUtility/packages.lock.json @@ -2729,7 +2729,7 @@ "migrator": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.Extensions.Logging": "6.0.0", "dbup-sqlserver": "5.0.8" } diff --git a/util/MySqlMigrations/packages.lock.json b/util/MySqlMigrations/packages.lock.json index 5e97b54a6b..f15f8d717e 100644 --- a/util/MySqlMigrations/packages.lock.json +++ b/util/MySqlMigrations/packages.lock.json @@ -2797,7 +2797,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", diff --git a/util/PostgresMigrations/packages.lock.json b/util/PostgresMigrations/packages.lock.json index 5e97b54a6b..f15f8d717e 100644 --- a/util/PostgresMigrations/packages.lock.json +++ b/util/PostgresMigrations/packages.lock.json @@ -2797,7 +2797,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", diff --git a/util/Setup/packages.lock.json b/util/Setup/packages.lock.json index 3fe1499534..c2b4d660d8 100644 --- a/util/Setup/packages.lock.json +++ b/util/Setup/packages.lock.json @@ -2706,7 +2706,7 @@ "migrator": { "type": "Project", "dependencies": { - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.Extensions.Logging": "6.0.0", "dbup-sqlserver": "5.0.8" } diff --git a/util/SqlServerEFScaffold/packages.lock.json b/util/SqlServerEFScaffold/packages.lock.json index 4e04168d02..f425d941ec 100644 --- a/util/SqlServerEFScaffold/packages.lock.json +++ b/util/SqlServerEFScaffold/packages.lock.json @@ -12,6 +12,74 @@ "Microsoft.EntityFrameworkCore.Relational": "6.0.4" } }, + "AspNetCore.HealthChecks.AzureServiceBus": { + "type": "Transitive", + "resolved": "6.1.0", + "contentHash": "LepLE6NO4bLBVDzlx/730pD6jnfkV6zaaRUrbN1LqnNk4m1hROsv7wOpgbKgVDgYIfeLzdiVnBviEevSxWFKMQ==", + "dependencies": { + "Azure.Messaging.EventHubs": "5.7.4", + "Azure.Messaging.ServiceBus": "7.11.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.10" + } + }, + "AspNetCore.HealthChecks.AzureStorage": { + "type": "Transitive", + "resolved": "6.1.2", + "contentHash": "R/uHJ40Cc0fBLi48SqDtT6fHyR5G8L3+PeKlbe8t498GLebeBIR3ve4l4n7UzCD0qgmQDDvyIYvVywx3i5Y6Ng==", + "dependencies": { + "Azure.Storage.Blobs": "12.14.1", + "Azure.Storage.Files.Shares": "12.11.0", + "Azure.Storage.Queues": "12.11.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.10" + } + }, + "AspNetCore.HealthChecks.Network": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "rvoPkqlvhX1HW6dpqjE1rbvmmMo9v7+Uf9dJffEcd3mA/DyyEitlZFc6cwYtmZVFdgy2gbIU4ubs3654nVfvjA==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.7", + "SSH.NET": "2020.0.2", + "System.Buffers": "4.5.1" + } + }, + "AspNetCore.HealthChecks.Redis": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "adNNWF6kV8v1HLTmF3b9F5K6ubvgx+S7VqhzA8T/5YuIpRWsCDk8+q3RIDDV8Twvl9pRahLfzCbFrPYxvzmk7g==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.4", + "StackExchange.Redis": "2.5.61" + } + }, + "AspNetCore.HealthChecks.SendGrid": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "VgskjkCUmSpAxil20rZlrj14bMi9aFNdiGLDtDTKjkUU0GYkoyi4HRVEy9Gp0FIgu9ce7quN+dNCpydKvMxjqA==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.2", + "Microsoft.Extensions.Http": "6.0.0", + "SendGrid": "9.24.4" + } + }, + "AspNetCore.HealthChecks.SqlServer": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "Af7ws27DnZZ4bKCiEREm7emSAKEtIiYirEAkI0ixFgK1fwJ99jmMnPC+kU01zfqn3FyCO/gZOUO7WbyVvTPpFg==", + "dependencies": { + "Microsoft.Data.SqlClient": "3.0.1", + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.0" + } + }, + "AspNetCore.HealthChecks.Uris": { + "type": "Transitive", + "resolved": "6.0.3", + "contentHash": "EY0Vh8s2UrbnyvM/QhbyYuCnbrBw36BKkdh5LqdINxqAGnlPFQXf+/UoNlH/76MTEyg+nvdp2wjr5MqWDkVFaQ==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks": "6.0.0", + "Microsoft.Extensions.Http": "6.0.0" + } + }, "AspNetCoreRateLimit": { "type": "Transitive", "resolved": "4.0.2", @@ -84,6 +152,14 @@ "System.Threading.Tasks.Extensions": "4.5.4" } }, + "Azure.Core.Amqp": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "vrF4isvhwdZspzorLwYhukXz3DA8/ONSnZUIBAqBtOCzsDNUgAsuILbCzvtDrn2oDxyq7DZx5Nh81pe0BeWmDQ==", + "dependencies": { + "System.Memory": "4.5.4" + } + }, "Azure.Extensions.AspNetCore.DataProtection.Blobs": { "type": "Transitive", "resolved": "1.3.2", @@ -118,6 +194,34 @@ "System.Text.Json": "4.7.2" } }, + "Azure.Messaging.EventHubs": { + "type": "Transitive", + "resolved": "5.7.4", + "contentHash": "8vC4efO5HzDgZjx6LaViScywbyKu3xIkL+y+QoyN7Yo6u1pEmMAPW4ptaWIj1JW4gypeWC1tFy+U3zdQ/E7bGA==", + "dependencies": { + "Azure.Core": "1.25.0", + "Azure.Core.Amqp": "1.2.0", + "Microsoft.Azure.Amqp": "2.5.12", + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Reflection.TypeExtensions": "4.7.0", + "System.Threading.Channels": "4.7.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Messaging.ServiceBus": { + "type": "Transitive", + "resolved": "7.11.1", + "contentHash": "ioGedXeH8KK4HdTDEyOzdgNbEXGstGItVljI1EKYsz08sgwej6LpODCZmwPR2ui1fjXBWt8Zea0RJT4d9LwlMg==", + "dependencies": { + "Azure.Core": "1.25.0", + "Azure.Core.Amqp": "1.2.0", + "Microsoft.Azure.Amqp": "2.5.12", + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Memory.Data": "1.0.2" + } + }, "Azure.Storage.Blobs": { "type": "Transitive", "resolved": "12.14.1", @@ -136,6 +240,15 @@ "System.IO.Hashing": "6.0.0" } }, + "Azure.Storage.Files.Shares": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "C747FRSZNe/L4hu1wrvzQImVaIfNDcZXfttaV3FwX96+TsbgXotHe6Y0lmSu65H/gVYKt07sIW9E1mDi3bdADw==", + "dependencies": { + "Azure.Storage.Common": "12.12.0", + "System.Text.Json": "4.7.2" + } + }, "Azure.Storage.Queues": { "type": "Transitive", "resolved": "12.12.0", @@ -391,12 +504,8 @@ }, "Microsoft.Azure.Amqp": { "type": "Transitive", - "resolved": "2.4.11", - "contentHash": "7x5fu2f6TLQDDJS0sY5qW8/daFwJaY9O75YvU8RcUfRzbug+9YGjXUBxoRrprgyi0jxdBAMQL05p1s783SOSFQ==", - "dependencies": { - "System.Net.WebSockets.Client": "4.0.2", - "System.Runtime.Serialization.Primitives": "4.1.1" - } + "resolved": "2.5.12", + "contentHash": "0SlEl+TSQdpjXWf9/37dXWAa0zk6R1EJKmGtGZeKUAH7WEQpJOWMxJ9I43igcBCnTkFwa28CdPnpSCjFZVQlkw==" }, "Microsoft.Azure.Cosmos": { "type": "Transitive", @@ -724,6 +833,22 @@ "System.Text.Json": "6.0.0" } }, + "Microsoft.Extensions.Diagnostics.HealthChecks": { + "type": "Transitive", + "resolved": "6.0.10", + "contentHash": "YmTyFOc7xx2/9FKuAlCmcWYKYLr0bYgNrRlcNPy/vc8qXnxnRV+kua6z96RUXSJVSQadCbJcEjmnTUMTEVfXOQ==", + "dependencies": { + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": "6.0.10", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.2", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Diagnostics.HealthChecks.Abstractions": { + "type": "Transitive", + "resolved": "6.0.10", + "contentHash": "U1PO967am1BIWbxBiLcYzVx8KOTYa9NvhBNgTn8Oii3LcsjvIwHzM+GTYy6bTiHnAFAlK5HAjxusAnAHSHJRoA==" + }, "Microsoft.Extensions.FileProviders.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -749,13 +874,12 @@ }, "Microsoft.Extensions.Hosting.Abstractions": { "type": "Transitive", - "resolved": "3.1.32", - "contentHash": "00J6eE920t5vfPnEHBSGyj1Ya9lG6WYsMwqvLZ0nMPPTD2UxkaL+FNJM5DNSnMFJtV84KkUudPRngmNiCkqhuA==", + "resolved": "6.0.0", + "contentHash": "GcT5l2CYXL6Sa27KCSh0TixsRfADUgth+ojQSD5EkzisZxmGFh7CwzkcYuGwvmXLjr27uWRNrJ2vuuEjMhU05Q==", "dependencies": { - "Microsoft.Extensions.Configuration.Abstractions": "3.1.32", - "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.32", - "Microsoft.Extensions.FileProviders.Abstractions": "3.1.32", - "Microsoft.Extensions.Logging.Abstractions": "3.1.32" + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0" } }, "Microsoft.Extensions.Http": { @@ -803,8 +927,8 @@ }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + "resolved": "6.0.2", + "contentHash": "pwXCZKaA7m5wgmCj49dW+H1RPSY7U62SKLTQYCcavf/k3Nyt/WnBgAjG4jMGnwy9rElfAZ2KvxvM5CJzJWG0hg==" }, "Microsoft.Extensions.Options": { "type": "Transitive", @@ -1425,10 +1549,23 @@ "SQLitePCLRaw.core": "2.1.2" } }, + "SSH.NET": { + "type": "Transitive", + "resolved": "2020.0.2", + "contentHash": "G0dNlTBAM00KZXv1wWVwgg26d9/METcM6qWBpNQwllzQmmbu+Zu+FS1L1X4fFgGdPu3e8k9mmTBu6SwtQ0614g==", + "dependencies": { + "SshNet.Security.Cryptography": "[1.3.0]" + } + }, + "SshNet.Security.Cryptography": { + "type": "Transitive", + "resolved": "1.3.0", + "contentHash": "5pBIXRjcSO/amY8WztpmNOhaaCNHY/B6CcYDI7FSTgqSyo/ZUojlLiKcsl+YGbxQuLX439qIkMfP0PHqxqJi/Q==" + }, "StackExchange.Redis": { "type": "Transitive", - "resolved": "2.5.43", - "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "resolved": "2.5.61", + "contentHash": "h1Gz4itrHL/PQ0GBLTEiPK8bBkOp5SFO6iaRFSSn/x1qltBWENsz/NUxPid6WHX9yf2Tiyzn9D3R7mtnksODxg==", "dependencies": { "Pipelines.Sockets.Unofficial": "2.2.2", "System.Diagnostics.PerformanceCounter": "5.0.0" @@ -2074,42 +2211,6 @@ "System.Runtime.Extensions": "4.1.0" } }, - "System.Net.WebSockets": { - "type": "Transitive", - "resolved": "4.0.0", - "contentHash": "2KJo8hir6Edi9jnMDAMhiJoI691xRBmKcbNpwjrvpIMOCTYOtBpSsSEGBxBDV7PKbasJNaFp1+PZz1D7xS41Hg==", - "dependencies": { - "Microsoft.Win32.Primitives": "4.0.1", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Threading.Tasks": "4.0.11" - } - }, - "System.Net.WebSockets.Client": { - "type": "Transitive", - "resolved": "4.0.2", - "contentHash": "NUCcDroX4lCQXgOrzlwIZ1u9YJ0krfyF0wk0ONnyLUmcQoEiYV2/OfUPRqUwQBbpH1BlGApkLgoQUwMqb5+c1g==", - "dependencies": { - "Microsoft.NETCore.Platforms": "1.0.2", - "Microsoft.Win32.Primitives": "4.0.1", - "System.Collections": "4.0.11", - "System.Diagnostics.Debug": "4.0.11", - "System.Diagnostics.Tracing": "4.1.0", - "System.Globalization": "4.0.11", - "System.Net.Primitives": "4.0.11", - "System.Net.WebHeaderCollection": "4.0.1", - "System.Net.WebSockets": "4.0.0", - "System.Resources.ResourceManager": "4.0.1", - "System.Runtime": "4.1.0", - "System.Runtime.Extensions": "4.1.0", - "System.Runtime.Handles": "4.0.1", - "System.Runtime.InteropServices": "4.1.0", - "System.Security.Cryptography.X509Certificates": "4.1.0", - "System.Text.Encoding": "4.0.11", - "System.Threading": "4.0.11", - "System.Threading.Tasks": "4.0.11" - } - }, "System.Numerics.Vectors": { "type": "Transitive", "resolved": "4.5.0", @@ -2226,12 +2327,8 @@ }, "System.Reflection.TypeExtensions": { "type": "Transitive", - "resolved": "4.3.0", - "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", - "dependencies": { - "System.Reflection": "4.3.0", - "System.Runtime": "4.3.0" - } + "resolved": "4.7.0", + "contentHash": "VybpaOQQhqE6siHppMktjfGBw1GCwvCqiufqmP8F1nj7fTUNtW35LOEt3UZTEsECfo+ELAl/9o9nJx3U91i7vA==" }, "System.Resources.ResourceManager": { "type": "Transitive", @@ -2619,6 +2716,11 @@ "System.Threading.Tasks": "4.3.0" } }, + "System.Threading.Channels": { + "type": "Transitive", + "resolved": "4.7.1", + "contentHash": "6akRtHK/wab3246t4p5v3HQrtQk8LboOt5T4dtpNgsp3zvDeM4/Gx8V12t0h+c/W9/enUrilk8n6EQqdQorZAA==" + }, "System.Threading.Overlapped": { "type": "Transitive", "resolved": "4.0.1", @@ -2811,96 +2913,103 @@ "api": { "type": "Project", "dependencies": { - "Azure.Messaging.EventGrid": "4.10.0", - "Commercial.Core": "2023.3.0", - "Commercial.Infrastructure.EntityFramework": "2023.3.0", - "Core": "2023.3.0", - "SharedWeb": "2023.3.0", - "Swashbuckle.AspNetCore": "6.5.0" + "AspNetCore.HealthChecks.AzureServiceBus": "[6.1.0, )", + "AspNetCore.HealthChecks.AzureStorage": "[6.1.2, )", + "AspNetCore.HealthChecks.Network": "[6.0.4, )", + "AspNetCore.HealthChecks.Redis": "[6.0.4, )", + "AspNetCore.HealthChecks.SendGrid": "[6.0.2, )", + "AspNetCore.HealthChecks.SqlServer": "[6.0.2, )", + "AspNetCore.HealthChecks.Uris": "[6.0.3, )", + "Azure.Messaging.EventGrid": "[4.10.0, )", + "Commercial.Core": "[2023.5.0, )", + "Commercial.Infrastructure.EntityFramework": "[2023.5.0, )", + "Core": "[2023.5.0, )", + "SharedWeb": "[2023.5.0, )", + "Swashbuckle.AspNetCore": "[6.5.0, )" } }, "commercial.core": { "type": "Project", "dependencies": { - "Core": "2023.3.0" + "Core": "[2023.5.0, )" } }, "commercial.infrastructure.entityframework": { "type": "Project", "dependencies": { - "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )", + "Core": "[2023.5.0, )", + "Infrastructure.EntityFramework": "[2023.5.0, )" } }, "core": { "type": "Project", "dependencies": { - "AWSSDK.SQS": "3.7.2.47", - "AWSSDK.SimpleEmail": "3.7.0.150", - "AspNetCoreRateLimit": "4.0.2", - "AspNetCoreRateLimit.Redis": "1.0.1", - "Azure.Extensions.AspNetCore.DataProtection.Blobs": "1.3.2", - "Azure.Storage.Blobs": "12.14.1", - "Azure.Storage.Queues": "12.12.0", - "BitPay.Light": "1.0.1907", - "Braintree": "5.12.0", - "DnsClient": "1.7.0", - "Fido2.AspNet": "3.0.1", - "Handlebars.Net": "2.1.2", - "IdentityServer4": "4.1.2", - "IdentityServer4.AccessTokenValidation": "3.0.1", - "LaunchDarkly.ServerSdk": "7.0.0", - "MailKit": "3.2.0", - "Microsoft.AspNetCore.Authentication.JwtBearer": "6.0.4", - "Microsoft.Azure.Cosmos.Table": "1.0.8", - "Microsoft.Azure.NotificationHubs": "4.1.0", - "Microsoft.Azure.ServiceBus": "5.2.0", - "Microsoft.Data.SqlClient": "5.0.1", - "Microsoft.Extensions.Caching.StackExchangeRedis": "6.0.6", - "Microsoft.Extensions.Configuration.EnvironmentVariables": "6.0.1", - "Microsoft.Extensions.Configuration.UserSecrets": "6.0.1", - "Microsoft.Extensions.Identity.Stores": "6.0.4", - "Newtonsoft.Json": "13.0.1", - "Otp.NET": "1.2.2", - "Quartz": "3.4.0", - "SendGrid": "9.27.0", - "Sentry.Serilog": "3.16.0", - "Serilog.AspNetCore": "5.0.0", - "Serilog.Extensions.Logging": "3.1.0", - "Serilog.Extensions.Logging.File": "2.0.0", - "Serilog.Sinks.AzureCosmosDB": "2.0.0", - "Serilog.Sinks.SyslogMessages": "2.0.6", - "Stripe.net": "40.0.0", - "YubicoDotNetClient": "1.2.0" + "AWSSDK.SQS": "[3.7.2.47, )", + "AWSSDK.SimpleEmail": "[3.7.0.150, )", + "AspNetCoreRateLimit": "[4.0.2, )", + "AspNetCoreRateLimit.Redis": "[1.0.1, )", + "Azure.Extensions.AspNetCore.DataProtection.Blobs": "[1.3.2, )", + "Azure.Storage.Blobs": "[12.14.1, )", + "Azure.Storage.Queues": "[12.12.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "DnsClient": "[1.7.0, )", + "Fido2.AspNet": "[3.0.1, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "LaunchDarkly.ServerSdk": "[7.0.0, )", + "MailKit": "[3.2.0, )", + "Microsoft.AspNetCore.Authentication.JwtBearer": "[6.0.4, )", + "Microsoft.Azure.Cosmos.Table": "[1.0.8, )", + "Microsoft.Azure.NotificationHubs": "[4.1.0, )", + "Microsoft.Azure.ServiceBus": "[5.2.0, )", + "Microsoft.Data.SqlClient": "[5.0.1, )", + "Microsoft.Extensions.Caching.StackExchangeRedis": "[6.0.6, )", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "[6.0.1, )", + "Microsoft.Extensions.Configuration.UserSecrets": "[6.0.1, )", + "Microsoft.Extensions.Identity.Stores": "[6.0.4, )", + "Newtonsoft.Json": "[13.0.1, )", + "Otp.NET": "[1.2.2, )", + "Quartz": "[3.4.0, )", + "SendGrid": "[9.27.0, )", + "Sentry.Serilog": "[3.16.0, )", + "Serilog.AspNetCore": "[5.0.0, )", + "Serilog.Extensions.Logging": "[3.1.0, )", + "Serilog.Extensions.Logging.File": "[2.0.0, )", + "Serilog.Sinks.AzureCosmosDB": "[2.0.0, )", + "Serilog.Sinks.SyslogMessages": "[2.0.6, )", + "Stripe.net": "[40.0.0, )", + "YubicoDotNetClient": "[1.2.0, )" } }, "infrastructure.dapper": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Dapper": "2.0.123" + "Core": "[2023.5.0, )", + "Dapper": "[2.0.123, )" } }, "infrastructure.entityframework": { "type": "Project", "dependencies": { - "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", - "Microsoft.EntityFrameworkCore.Relational": "6.0.12", - "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", - "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", - "Npgsql.EntityFrameworkCore.PostgreSQL": "6.0.8", - "Pomelo.EntityFrameworkCore.MySql": "6.0.2", - "linq2db.EntityFrameworkCore": "6.11.0" + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[12.0.1, )", + "Core": "[2023.5.0, )", + "Microsoft.EntityFrameworkCore.Relational": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.SqlServer": "[6.0.12, )", + "Microsoft.EntityFrameworkCore.Sqlite": "[6.0.12, )", + "Npgsql.EntityFrameworkCore.PostgreSQL": "[6.0.8, )", + "Pomelo.EntityFrameworkCore.MySql": "[6.0.2, )", + "linq2db.EntityFrameworkCore": "[6.11.0, )" } }, "sharedweb": { "type": "Project", "dependencies": { - "Core": "2023.3.0", - "Infrastructure.Dapper": "2023.3.0", - "Infrastructure.EntityFramework": "2023.3.0" + "Core": "[2023.5.0, )", + "Infrastructure.Dapper": "[2023.5.0, )", + "Infrastructure.EntityFramework": "[2023.5.0, )" } } } diff --git a/util/SqliteMigrations/packages.lock.json b/util/SqliteMigrations/packages.lock.json index 5e97b54a6b..f15f8d717e 100644 --- a/util/SqliteMigrations/packages.lock.json +++ b/util/SqliteMigrations/packages.lock.json @@ -2797,7 +2797,7 @@ "type": "Project", "dependencies": { "AutoMapper.Extensions.Microsoft.DependencyInjection": "12.0.1", - "Core": "2023.3.0", + "Core": "2023.4.3", "Microsoft.EntityFrameworkCore.Relational": "6.0.12", "Microsoft.EntityFrameworkCore.SqlServer": "6.0.12", "Microsoft.EntityFrameworkCore.Sqlite": "6.0.12", From e0b231a2203736f8ae71b42d986c9b2f61e7ddef Mon Sep 17 00:00:00 2001 From: Justin Baur <19896123+justindbaur@users.noreply.github.com> Date: Mon, 26 Jun 2023 20:17:39 -0400 Subject: [PATCH 10/13] [PM-2697] Return `UserDecryptionOptions` Always (#3032) * Add Comments to UserDecryptionOptions * Move Feature Flag Check * Remove SSO Config Check * Move UserDecryptionOptions Creation - Put logic in BaseRequestValidator * Remove 'async' --- .../Api/Response/UserDecryptionOptions.cs | 6 +- .../IdentityServer/BaseRequestValidator.cs | 63 ++++++++++++- .../CustomTokenRequestValidator.cs | 94 ++++--------------- .../ResourceOwnerPasswordValidator.cs | 15 ++- .../Endpoints/IdentityServerSsoTests.cs | 57 ++++++++++- .../Endpoints/IdentityServerTests.cs | 11 +++ 6 files changed, 161 insertions(+), 85 deletions(-) diff --git a/src/Core/Auth/Models/Api/Response/UserDecryptionOptions.cs b/src/Core/Auth/Models/Api/Response/UserDecryptionOptions.cs index 28f876035a..8cf2586ce2 100644 --- a/src/Core/Auth/Models/Api/Response/UserDecryptionOptions.cs +++ b/src/Core/Auth/Models/Api/Response/UserDecryptionOptions.cs @@ -12,18 +12,18 @@ public class UserDecryptionOptions : ResponseModel } /// - /// + /// Gets or sets whether the current user has a master password that can be used to decrypt their vault. /// public bool HasMasterPassword { get; set; } /// - /// + /// Gets or sets information regarding this users trusted device decryption setup. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public TrustedDeviceUserDecryptionOption? TrustedDeviceOption { get; set; } /// - /// + /// Gets or set information about the current users KeyConnector setup. /// [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] public KeyConnectorUserDecryptionOption? KeyConnectorOption { get; set; } diff --git a/src/Identity/IdentityServer/BaseRequestValidator.cs b/src/Identity/IdentityServer/BaseRequestValidator.cs index 271b9769c8..9cfc19c13b 100644 --- a/src/Identity/IdentityServer/BaseRequestValidator.cs +++ b/src/Identity/IdentityServer/BaseRequestValidator.cs @@ -6,7 +6,10 @@ using Bit.Core; using Bit.Core.Auth.Enums; using Bit.Core.Auth.Identity; using Bit.Core.Auth.Models; +using Bit.Core.Auth.Models.Api.Response; using Bit.Core.Auth.Models.Business.Tokenables; +using Bit.Core.Auth.Models.Data; +using Bit.Core.Auth.Repositories; using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Enums; @@ -43,6 +46,8 @@ public abstract class BaseRequestValidator where T : class protected ICurrentContext CurrentContext { get; } protected IPolicyService PolicyService { get; } + protected IFeatureService FeatureService { get; } + protected ISsoConfigRepository SsoConfigRepository { get; } public BaseRequestValidator( UserManager userManager, @@ -58,10 +63,11 @@ public abstract class BaseRequestValidator where T : class ILogger logger, ICurrentContext currentContext, GlobalSettings globalSettings, - IPolicyRepository policyRepository, IUserRepository userRepository, IPolicyService policyService, - IDataProtectorTokenFactory tokenDataFactory) + IDataProtectorTokenFactory tokenDataFactory, + IFeatureService featureService, + ISsoConfigRepository ssoConfigRepository) { _userManager = userManager; _deviceRepository = deviceRepository; @@ -79,6 +85,8 @@ public abstract class BaseRequestValidator where T : class PolicyService = policyService; _userRepository = userRepository; _tokenDataFactory = tokenDataFactory; + FeatureService = featureService; + SsoConfigRepository = ssoConfigRepository; } protected async Task ValidateAsync(T context, ValidatedTokenRequest request, @@ -199,6 +207,7 @@ public abstract class BaseRequestValidator where T : class customResponse.Add("KdfIterations", user.KdfIterations); customResponse.Add("KdfMemory", user.KdfMemory); customResponse.Add("KdfParallelism", user.KdfParallelism); + customResponse.Add("UserDecryptionOptions", await CreateUserDecryptionOptionsAsync(user, GetSubject(context))); if (sendRememberToken) { @@ -300,6 +309,7 @@ public abstract class BaseRequestValidator where T : class Dictionary customResponse); protected abstract void SetErrorResult(T context, Dictionary customResponse); + protected abstract ClaimsPrincipal GetSubject(T context); private async Task> RequiresTwoFactorAsync(User user, ValidatedTokenRequest request) { @@ -572,4 +582,53 @@ public abstract class BaseRequestValidator where T : class return new MasterPasswordPolicyResponseModel(await PolicyService.GetMasterPasswordPolicyForUserAsync(user)); } + +#nullable enable + /// + /// Used to create a list of all possible ways the newly authenticated user can decrypt their vault contents + /// + private async Task CreateUserDecryptionOptionsAsync(User user, ClaimsPrincipal subject) + { + var ssoConfigurationData = await GetSsoConfigurationDataAsync(subject); + + var userDecryptionOption = new UserDecryptionOptions + { + HasMasterPassword = !string.IsNullOrEmpty(user.MasterPassword) + }; + + if (ssoConfigurationData is { MemberDecryptionType: MemberDecryptionType.KeyConnector } && !string.IsNullOrEmpty(ssoConfigurationData.KeyConnectorUrl)) + { + // KeyConnector makes it mutually exclusive + userDecryptionOption.KeyConnectorOption = new KeyConnectorUserDecryptionOption(ssoConfigurationData.KeyConnectorUrl); + return userDecryptionOption; + } + + // Only add the trusted device specific option when the flag is turned on + if (FeatureService.IsEnabled(FeatureFlagKeys.TrustedDeviceEncryption, CurrentContext) && ssoConfigurationData is { MemberDecryptionType: MemberDecryptionType.TrustedDeviceEncryption }) + { + var hasAdminApproval = await PolicyService.AnyPoliciesApplicableToUserAsync(user.Id, PolicyType.ResetPassword); + // TrustedDeviceEncryption only exists for SSO, but if that ever changes this value won't always be true + userDecryptionOption.TrustedDeviceOption = new TrustedDeviceUserDecryptionOption(hasAdminApproval); + } + + return userDecryptionOption; + } + + private async Task GetSsoConfigurationDataAsync(ClaimsPrincipal subject) + { + var organizationClaim = subject?.FindFirstValue("organizationId"); + + if (organizationClaim == null || !Guid.TryParse(organizationClaim, out var organizationId)) + { + return null; + } + + var ssoConfig = await SsoConfigRepository.GetByOrganizationIdAsync(organizationId); + if (ssoConfig == null) + { + return null; + } + + return ssoConfig.GetData(); + } } diff --git a/src/Identity/IdentityServer/CustomTokenRequestValidator.cs b/src/Identity/IdentityServer/CustomTokenRequestValidator.cs index 7096cb0389..e6e39bade1 100644 --- a/src/Identity/IdentityServer/CustomTokenRequestValidator.cs +++ b/src/Identity/IdentityServer/CustomTokenRequestValidator.cs @@ -1,14 +1,10 @@ using System.Security.Claims; -using Bit.Core; -using Bit.Core.Auth.Enums; using Bit.Core.Auth.Identity; using Bit.Core.Auth.Models.Api.Response; using Bit.Core.Auth.Models.Business.Tokenables; -using Bit.Core.Auth.Models.Data; using Bit.Core.Auth.Repositories; using Bit.Core.Context; using Bit.Core.Entities; -using Bit.Core.Enums; using Bit.Core.IdentityServer; using Bit.Core.Repositories; using Bit.Core.Services; @@ -27,8 +23,6 @@ public class CustomTokenRequestValidator : BaseRequestValidator _userManager; - private readonly ISsoConfigRepository _ssoConfigRepository; - private readonly IFeatureService _featureService; public CustomTokenRequestValidator( UserManager userManager, @@ -44,7 +38,6 @@ public class CustomTokenRequestValidator : BaseRequestValidator logger, ICurrentContext currentContext, GlobalSettings globalSettings, - IPolicyRepository policyRepository, ISsoConfigRepository ssoConfigRepository, IUserRepository userRepository, IPolicyService policyService, @@ -52,12 +45,10 @@ public class CustomTokenRequestValidator : BaseRequestValidator claims, Dictionary customResponse) { context.Result.CustomResponse = customResponse; @@ -110,23 +101,9 @@ public class CustomTokenRequestValidator : BaseRequestValidator GetSsoConfigurationDataAsync(ClaimsPrincipal? subject) + protected override ClaimsPrincipal GetSubject(CustomTokenRequestValidationContext context) { - var organizationClaim = subject?.FindFirstValue("organizationId"); - - if (organizationClaim == null || !Guid.TryParse(organizationClaim, out var organizationId)) - { - return null; - } - - var ssoConfig = await _ssoConfigRepository.GetByOrganizationIdAsync(organizationId); - if (ssoConfig == null) - { - return null; - } - - return ssoConfig.GetData(); + return context.Result.ValidatedRequest.Subject; } protected override void SetTwoFactorResult(CustomTokenRequestValidationContext context, @@ -198,29 +169,4 @@ public class CustomTokenRequestValidator : BaseRequestValidator - /// Used to create a list of all possible ways the newly authenticated user can decrypt their vault contents - /// - private async Task CreateUserDecryptionOptionsAsync(SsoConfigurationData ssoConfigurationData, User user) - { - var userDecryptionOption = new UserDecryptionOptions(); - if (ssoConfigurationData is { MemberDecryptionType: MemberDecryptionType.KeyConnector } && !string.IsNullOrEmpty(ssoConfigurationData.KeyConnectorUrl)) - { - // KeyConnector makes it mutually exclusive - userDecryptionOption.KeyConnectorOption = new KeyConnectorUserDecryptionOption(ssoConfigurationData.KeyConnectorUrl); - return userDecryptionOption; - } - - if (ssoConfigurationData is { MemberDecryptionType: MemberDecryptionType.TrustedDeviceEncryption }) - { - var hasAdminApproval = await PolicyService.AnyPoliciesApplicableToUserAsync(user.Id, PolicyType.ResetPassword); - // TrustedDeviceEncryption only exists for SSO, but if that ever changes this value won't always be true - userDecryptionOption.TrustedDeviceOption = new TrustedDeviceUserDecryptionOption(hasAdminApproval); - } - - userDecryptionOption.HasMasterPassword = !string.IsNullOrEmpty(user.MasterPassword); - - return userDecryptionOption; - } } diff --git a/src/Identity/IdentityServer/ResourceOwnerPasswordValidator.cs b/src/Identity/IdentityServer/ResourceOwnerPasswordValidator.cs index c36f39b45c..df17a474a3 100644 --- a/src/Identity/IdentityServer/ResourceOwnerPasswordValidator.cs +++ b/src/Identity/IdentityServer/ResourceOwnerPasswordValidator.cs @@ -1,6 +1,7 @@ using System.Security.Claims; using Bit.Core.Auth.Identity; using Bit.Core.Auth.Models.Business.Tokenables; +using Bit.Core.Auth.Repositories; using Bit.Core.Auth.Services; using Bit.Core.Context; using Bit.Core.Entities; @@ -37,16 +38,17 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator logger, ICurrentContext currentContext, GlobalSettings globalSettings, - IPolicyRepository policyRepository, ICaptchaValidationService captchaValidationService, IAuthRequestRepository authRequestRepository, IUserRepository userRepository, IPolicyService policyService, - IDataProtectorTokenFactory tokenDataFactory) + IDataProtectorTokenFactory tokenDataFactory, + IFeatureService featureService, + ISsoConfigRepository ssoConfigRepository) : base(userManager, deviceRepository, deviceService, userService, eventService, organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository, - applicationCacheService, mailService, logger, currentContext, globalSettings, policyRepository, - userRepository, policyService, tokenDataFactory) + applicationCacheService, mailService, logger, currentContext, globalSettings, userRepository, policyService, + tokenDataFactory, featureService, ssoConfigRepository) { _userManager = userManager; _userService = userService; @@ -166,6 +168,11 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator user.MasterPassword = null); + + // Act + var context = await factory.Server.PostAsync("/connect/token", new FormUrlEncodedContent(new Dictionary + { + { "scope", "api offline_access" }, + { "client_id", "web" }, + { "deviceType", "10" }, + { "deviceIdentifier", "test_id" }, + { "deviceName", "firefox" }, + { "twoFactorToken", "TEST"}, + { "twoFactorProvider", "5" }, // RememberMe Provider + { "twoFactorRemember", "0" }, + { "grant_type", "authorization_code" }, + { "code", "test_code" }, + { "code_verifier", challenge }, + { "redirect_uri", "https://localhost:8080/sso-connector.html" } + })); + + // Assert + // If the organization has selected TrustedDeviceEncryption but the user still has their master password + // they can decrypt with either option + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + using var responseBody = await AssertHelper.AssertResponseTypeIs(context); + var root = responseBody.RootElement; + AssertHelper.AssertJsonProperty(root, "access_token", JsonValueKind.String); + var userDecryptionOptions = AssertHelper.AssertJsonProperty(root, "UserDecryptionOptions", JsonValueKind.Object); + + // Expected to look like: + // "UserDecryptionOptions": { + // "Object": "userDecryptionOptions" + // "HasMasterPassword": false + // } + + // Should only have 2 properties + Assert.Equal(2, userDecryptionOptions.EnumerateObject().Count()); + } + [Fact] public async Task SsoLogin_KeyConnector_ReturnsOptions() { @@ -301,7 +354,7 @@ public class IdentityServerSsoTests Assert.Equal("https://key_connector.com", keyConnectorUrl); } - private static async Task CreateFactoryAsync(SsoConfigurationData ssoConfigurationData, string challenge) + private static async Task CreateFactoryAsync(SsoConfigurationData ssoConfigurationData, string challenge, bool trustedDeviceEnabled = true) { var factory = new IdentityApplicationFactory(); @@ -327,7 +380,7 @@ public class IdentityServerSsoTests factory.SubstitueService(service => { service.IsEnabled(FeatureFlagKeys.TrustedDeviceEncryption, Arg.Any()) - .Returns(true); + .Returns(trustedDeviceEnabled); }); // This starts the server and finalizes services diff --git a/test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs b/test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs index 316f89647f..f29a09c6e2 100644 --- a/test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs +++ b/test/Identity.IntegrationTest/Endpoints/IdentityServerTests.cs @@ -65,6 +65,7 @@ public class IdentityServerTests : IClassFixture Assert.Equal(0, kdf); var kdfIterations = AssertHelper.AssertJsonProperty(root, "KdfIterations", JsonValueKind.Number).GetInt32(); Assert.Equal(5000, kdfIterations); + AssertUserDecryptionOptions(root); } [Theory, BitAutoData] @@ -635,6 +636,16 @@ public class IdentityServerTests : IClassFixture Assert.StartsWith("sso authentication", errorDescription.ToLowerInvariant()); } + private static void AssertUserDecryptionOptions(JsonElement tokenResponse) + { + var userDecryptionOptions = AssertHelper.AssertJsonProperty(tokenResponse, "UserDecryptionOptions", JsonValueKind.Object) + .EnumerateObject(); + + Assert.Collection(userDecryptionOptions, + (prop) => { Assert.Equal("HasMasterPassword", prop.Name); Assert.Equal(JsonValueKind.True, prop.Value.ValueKind); }, + (prop) => { Assert.Equal("Object", prop.Name); Assert.Equal("userDecryptionOptions", prop.Value.GetString()); }); + } + private void ReinitializeDbForTests() { var databaseContext = _factory.GetDatabaseContext(); From 333145209e6274bd0f135cc11b753c2653bdf5a3 Mon Sep 17 00:00:00 2001 From: cturnbull-bitwarden <133619638+cturnbull-bitwarden@users.noreply.github.com> Date: Tue, 27 Jun 2023 05:23:23 -0400 Subject: [PATCH 11/13] [AC-1429] Add new secrets manager fields to organization edit page in admin portal (#3009) * Added new secrets fields to organization edit page * Reordered fields based on feedback from Priya --- .../Controllers/OrganizationsController.cs | 6 ++ src/Admin/Models/OrganizationEditModel.cs | 16 +++ .../Views/Shared/_OrganizationForm.cshtml | 97 +++++++++++++------ .../Shared/_OrganizationFormScripts.cshtml | 20 ++++ 4 files changed, 111 insertions(+), 28 deletions(-) diff --git a/src/Admin/Controllers/OrganizationsController.cs b/src/Admin/Controllers/OrganizationsController.cs index 01e55f86a9..9a367d7997 100644 --- a/src/Admin/Controllers/OrganizationsController.cs +++ b/src/Admin/Controllers/OrganizationsController.cs @@ -287,6 +287,12 @@ public class OrganizationsController : Controller organization.UseTotp = model.UseTotp; organization.UsersGetPremium = model.UsersGetPremium; organization.UseSecretsManager = model.UseSecretsManager; + + //secrets + organization.SmSeats = model.SmSeats; + organization.MaxAutoscaleSmSeats = model.MaxAutoscaleSmSeats; + organization.SmServiceAccounts = model.SmServiceAccounts; + organization.MaxAutoscaleSmServiceAccounts = model.MaxAutoscaleSmServiceAccounts; } if (_accessControlService.UserHasPermission(Permission.Org_Licensing_Edit)) diff --git a/src/Admin/Models/OrganizationEditModel.cs b/src/Admin/Models/OrganizationEditModel.cs index f67ad18abc..19a82bb31c 100644 --- a/src/Admin/Models/OrganizationEditModel.cs +++ b/src/Admin/Models/OrganizationEditModel.cs @@ -63,6 +63,10 @@ public class OrganizationEditModel : OrganizationViewModel Enabled = org.Enabled; LicenseKey = org.LicenseKey; ExpirationDate = org.ExpirationDate; + SmSeats = org.SmSeats; + MaxAutoscaleSmSeats = org.MaxAutoscaleSmSeats; + SmServiceAccounts = org.SmServiceAccounts; + MaxAutoscaleSmServiceAccounts = org.MaxAutoscaleSmServiceAccounts; } public BillingInfo BillingInfo { get; set; } @@ -134,6 +138,14 @@ public class OrganizationEditModel : OrganizationViewModel [Display(Name = "Expiration Date")] public DateTime? ExpirationDate { get; set; } public bool SalesAssistedTrialStarted { get; set; } + [Display(Name = "Seats")] + public int? SmSeats { get; set; } + [Display(Name = "Max Autoscale Seats")] + public int? MaxAutoscaleSmSeats { get; set; } + [Display(Name = "Max Service Accounts")] + public int? SmServiceAccounts { get; set; } + [Display(Name = "Max Autoscale Service Accounts")] + public int? MaxAutoscaleSmServiceAccounts { get; set; } public Organization CreateOrganization(Provider provider) { @@ -174,6 +186,10 @@ public class OrganizationEditModel : OrganizationViewModel existingOrganization.LicenseKey = LicenseKey; existingOrganization.ExpirationDate = ExpirationDate; existingOrganization.MaxAutoscaleSeats = MaxAutoscaleSeats; + existingOrganization.SmSeats = SmSeats; + existingOrganization.MaxAutoscaleSmSeats = MaxAutoscaleSmSeats; + existingOrganization.SmServiceAccounts = SmServiceAccounts; + existingOrganization.MaxAutoscaleSmServiceAccounts = MaxAutoscaleSmServiceAccounts; return existingOrganization; } } diff --git a/src/Admin/Views/Shared/_OrganizationForm.cshtml b/src/Admin/Views/Shared/_OrganizationForm.cshtml index f20b80f280..ae5970603c 100644 --- a/src/Admin/Views/Shared/_OrganizationForm.cshtml +++ b/src/Admin/Views/Shared/_OrganizationForm.cshtml @@ -99,34 +99,6 @@ -
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
-
-
-
-
- - -
-
-

Features

@@ -200,6 +172,75 @@
} + + @if (canViewPlan) + { +

Password Manager Configuration

+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+ } + + @if (canViewPlan) + { + + } + @if(canViewLicensing) {

Licensing

diff --git a/src/Admin/Views/Shared/_OrganizationFormScripts.cshtml b/src/Admin/Views/Shared/_OrganizationFormScripts.cshtml index 70a5ae60d7..8fd7ef10e0 100644 --- a/src/Admin/Views/Shared/_OrganizationFormScripts.cshtml +++ b/src/Admin/Views/Shared/_OrganizationFormScripts.cshtml @@ -32,6 +32,18 @@ 'subscriptions/' + subId.value, '_blank'); } }); + document.getElementById('@(nameof(Model.UseSecretsManager))').addEventListener('change', (event) => { + document.getElementById('organization-secrets-configuration').hidden = !event.target.checked; + + if (event.target.checked) { + return; + } + + document.getElementById('@(nameof(Model.SmSeats))').value = ''; + document.getElementById('@(nameof(Model.MaxAutoscaleSmSeats))').value = ''; + document.getElementById('@(nameof(Model.SmServiceAccounts))').value = ''; + document.getElementById('@(nameof(Model.MaxAutoscaleSmServiceAccounts))').value = ''; + }); })(); function togglePlanSettings(planType) { @@ -43,6 +55,10 @@ document.getElementById('@(nameof(Model.Seats))').value = '10'; document.getElementById('@(nameof(Model.MaxCollections))').value = ''; document.getElementById('@(nameof(Model.MaxStorageGb))').value = '1'; + // Secrets + if (document.getElementById('@(nameof(Model.UseSecretsManager))').checked) { + document.getElementById('@(nameof(Model.SmServiceAccounts))').value = '50'; + } // Features document.getElementById('@(nameof(Model.UsePolicies))').checked = false; document.getElementById('@(nameof(Model.UseSso))').checked = false; @@ -69,6 +85,10 @@ document.getElementById('@(nameof(Model.Seats))').value = '10'; document.getElementById('@(nameof(Model.MaxCollections))').value = ''; document.getElementById('@(nameof(Model.MaxStorageGb))').value = '1'; + // Secrets + if (document.getElementById('@(nameof(Model.UseSecretsManager))').checked) { + document.getElementById('@(nameof(Model.SmServiceAccounts))').value = '200'; + } // Features document.getElementById('@(nameof(Model.UsePolicies))').checked = true; document.getElementById('@(nameof(Model.UseSso))').checked = true; From c1723d9e903507e973f14f72be2168d5e1bfb841 Mon Sep 17 00:00:00 2001 From: Vince Grassia <593223+vgrassia@users.noreply.github.com> Date: Tue, 27 Jun 2023 13:18:51 -0400 Subject: [PATCH 12/13] DEVOPS-1446 - Update Build Workflow (#3047) --- .github/workflows/build.yml | 43 ++++++++----------------------------- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f95c3e8171..071e2ad6de 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -523,38 +523,13 @@ jobs: path: util/MsSqlMigratorUtility/obj/build-output/publish/MsSqlMigratorUtility if-no-files-found: error - trigger-self-host-build: - name: Trigger self-host build - runs-on: ubuntu-22.04 - needs: - - build-docker - steps: - - name: Login to Azure - CI Subscription - uses: Azure/login@1f63701bf3e6892515f1b7ce2d2bf1708b46beaf # v1.4.3 - with: - creds: ${{ secrets.AZURE_KV_CI_SERVICE_PRINCIPAL }} - - - name: Retrieve github PAT secrets - id: retrieve-secret-pat - uses: bitwarden/gh-actions/get-keyvault-secrets@c86ced0dc8c9daeecf057a6333e6f318db9c5a2b - with: - keyvault: "bitwarden-ci" - secrets: "github-pat-bitwarden-devops-bot-repo-scope" - - - name: Trigger self-host build - uses: actions/github-script@v6 - with: - github-token: ${{ steps.retrieve-secret-pat.outputs.github-pat-bitwarden-devops-bot-repo-scope }} - script: | - await github.rest.actions.createWorkflowDispatch({ - owner: 'bitwarden', - repo: 'self-host', - workflow_id: 'build-unified.yml', - ref: 'master', - inputs: { - server_branch: '${{ github.ref }}' - } - }) + self-host-build: + name: Self-host build + needs: build-docker + uses: bitwarden/self-host/.github/workflows/build-unified.yml@master + with: + server_branch: ${{ github.ref_name }} + secrets: inherit check-failures: name: Check for failures @@ -568,7 +543,7 @@ jobs: - build-docker - upload - build-mssqlmigratorutility - - trigger-self-host-build + - self-host-build steps: - name: Check if any job failed if: | @@ -583,7 +558,7 @@ jobs: BUILD_DOCKER_STATUS: ${{ needs.build-docker.result }} UPLOAD_STATUS: ${{ needs.upload.result }} BUILD_MSSQLMIGRATORUTILITY_STATUS: ${{ needs.build-mssqlmigratorutility.result }} - TRIGGER_SELF_HOST_BUILD_STATUS: ${{ needs.trigger-self-host-build.result }} + TRIGGER_SELF_HOST_BUILD_STATUS: ${{ needs.self-host-build.result }} run: | if [ "$CLOC_STATUS" = "failure" ]; then exit 1 From d020c49c0e3957e4bf08a38be32f306e4225fdda Mon Sep 17 00:00:00 2001 From: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com> Date: Tue, 27 Jun 2023 13:12:34 -0500 Subject: [PATCH 13/13] [SM-788] Extract authorization from secret delete command (#3003) * Extract authorization from secret delete command --- .../Secrets/SecretAuthorizationHandler.cs | 21 +++ .../Commands/Secrets/DeleteSecretCommand.cs | 68 +-------- .../SecretAuthorizationHandlerTests.cs | 79 +++++++++++ .../Secrets/DeleteSecretCommandTests.cs | 77 +---------- .../Controllers/SecretsController.cs | 38 +++++- .../SecretOperationRequirement.cs | 1 + .../Interfaces/IDeleteSecretCommand.cs | 2 +- .../Controllers/SecretsControllerTests.cs | 68 ++++++--- .../Controllers/SecretsControllerTests.cs | 129 +++++++++++++----- 9 files changed, 287 insertions(+), 196 deletions(-) diff --git a/bitwarden_license/src/Commercial.Core/SecretsManager/AuthorizationHandlers/Secrets/SecretAuthorizationHandler.cs b/bitwarden_license/src/Commercial.Core/SecretsManager/AuthorizationHandlers/Secrets/SecretAuthorizationHandler.cs index 7ddc8b8867..b02271c7a6 100644 --- a/bitwarden_license/src/Commercial.Core/SecretsManager/AuthorizationHandlers/Secrets/SecretAuthorizationHandler.cs +++ b/bitwarden_license/src/Commercial.Core/SecretsManager/AuthorizationHandlers/Secrets/SecretAuthorizationHandler.cs @@ -41,6 +41,9 @@ public class SecretAuthorizationHandler : AuthorizationHandler>> DeleteSecrets(List ids, Guid userId) + public async Task DeleteSecrets(IEnumerable secrets) { - var secrets = (await _secretRepository.GetManyByIds(ids)).ToList(); - - if (secrets.Any() != true) - { - throw new NotFoundException(); - } - - // Ensure all secrets belongs to the same organization - var organizationId = secrets.First().OrganizationId; - if (secrets.Any(secret => secret.OrganizationId != organizationId)) - { - throw new BadRequestException(); - } - - if (!_currentContext.AccessSecretsManager(organizationId)) - { - throw new NotFoundException(); - } - - var orgAdmin = await _currentContext.OrganizationAdmin(organizationId); - var accessClient = AccessClientHelper.ToAccessClient(_currentContext.ClientType, orgAdmin); - - var results = new List>(); - var deleteIds = new List(); - - foreach (var secret in secrets) - { - var hasAccess = orgAdmin; - - if (secret.Projects != null && secret.Projects?.Count > 0) - { - var projectId = secret.Projects.First().Id; - hasAccess = (await _projectRepository.AccessToProjectAsync(projectId, userId, accessClient)).Write; - } - - if (!hasAccess || accessClient == AccessClientType.ServiceAccount) - { - results.Add(new Tuple(secret, "access denied")); - } - else - { - deleteIds.Add(secret.Id); - results.Add(new Tuple(secret, "")); - } - } - - - - if (deleteIds.Count > 0) - { - await _secretRepository.SoftDeleteManyByIdAsync(deleteIds); - } - - return results; + await _secretRepository.SoftDeleteManyByIdAsync(secrets.Select(s => s.Id)); } } diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AuthorizationHandlers/Secrets/SecretAuthorizationHandlerTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AuthorizationHandlers/Secrets/SecretAuthorizationHandlerTests.cs index 24b9d481e5..3e18a83493 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AuthorizationHandlers/Secrets/SecretAuthorizationHandlerTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/AuthorizationHandlers/Secrets/SecretAuthorizationHandlerTests.cs @@ -374,4 +374,83 @@ public class SecretAuthorizationHandlerTests Assert.True(authzContext.HasSucceeded); } + + [Theory] + [BitAutoData] + public async Task CanDeleteSecret_AccessToSecretsManagerFalse_DoesNotSucceed( + SutProvider sutProvider, Secret secret, + ClaimsPrincipal claimsPrincipal) + { + var requirement = SecretOperations.Delete; + sutProvider.GetDependency().AccessSecretsManager(secret.OrganizationId) + .Returns(false); + var authzContext = new AuthorizationHandlerContext(new List { requirement }, + claimsPrincipal, secret); + + await sutProvider.Sut.HandleAsync(authzContext); + + Assert.False(authzContext.HasSucceeded); + } + + [Theory] + [BitAutoData] + public async Task CanDeleteSecret_NullResource_DoesNotSucceed( + SutProvider sutProvider, Secret secret, + ClaimsPrincipal claimsPrincipal, + Guid userId) + { + var requirement = SecretOperations.Delete; + SetupPermission(sutProvider, PermissionType.RunAsAdmin, secret.OrganizationId, userId); + var authzContext = new AuthorizationHandlerContext(new List { requirement }, + claimsPrincipal, null); + + await sutProvider.Sut.HandleAsync(authzContext); + + Assert.False(authzContext.HasSucceeded); + } + + [Theory] + [BitAutoData] + public async Task CanDeleteSecret_ServiceAccountClient_DoesNotSucceed( + SutProvider sutProvider, Secret secret, Guid userId, + ClaimsPrincipal claimsPrincipal) + { + var requirement = SecretOperations.Delete; + SetupPermission(sutProvider, PermissionType.RunAsUserWithPermission, secret.OrganizationId, userId, + AccessClientType.ServiceAccount); + sutProvider.GetDependency() + .AccessToSecretAsync(secret.Id, userId, Arg.Any()) + .Returns((true, true)); + var authzContext = new AuthorizationHandlerContext(new List { requirement }, + claimsPrincipal, secret); + + await sutProvider.Sut.HandleAsync(authzContext); + + Assert.False(authzContext.HasSucceeded); + } + + [Theory] + [BitAutoData(PermissionType.RunAsAdmin, true, true, true)] + [BitAutoData(PermissionType.RunAsUserWithPermission, false, false, false)] + [BitAutoData(PermissionType.RunAsUserWithPermission, false, true, true)] + [BitAutoData(PermissionType.RunAsUserWithPermission, true, false, false)] + [BitAutoData(PermissionType.RunAsUserWithPermission, true, true, true)] + public async Task CanDeleteProject_AccessCheck(PermissionType permissionType, bool read, bool write, + bool expected, + SutProvider sutProvider, Secret secret, + ClaimsPrincipal claimsPrincipal, + Guid userId) + { + var requirement = SecretOperations.Delete; + SetupPermission(sutProvider, permissionType, secret.OrganizationId, userId); + sutProvider.GetDependency() + .AccessToSecretAsync(secret.Id, userId, Arg.Any()) + .Returns((read, write)); + var authzContext = new AuthorizationHandlerContext(new List { requirement }, + claimsPrincipal, secret); + + await sutProvider.Sut.HandleAsync(authzContext); + + Assert.Equal(expected, authzContext.HasSucceeded); + } } diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/Secrets/DeleteSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/Secrets/DeleteSecretCommandTests.cs index c3183e9064..bdd7b1a6f2 100644 --- a/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/Secrets/DeleteSecretCommandTests.cs +++ b/bitwarden_license/test/Commercial.Core.Test/SecretsManager/Commands/Secrets/DeleteSecretCommandTests.cs @@ -1,8 +1,4 @@ using Bit.Commercial.Core.SecretsManager.Commands.Secrets; -using Bit.Commercial.Core.Test.SecretsManager.Enums; -using Bit.Core.Context; -using Bit.Core.Enums; -using Bit.Core.Exceptions; using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Repositories; using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture; @@ -20,75 +16,12 @@ public class DeleteSecretCommandTests { [Theory] [BitAutoData] - public async Task DeleteSecrets_Throws_NotFoundException(List data, - SutProvider sutProvider) + public async Task DeleteSecrets_Success(SutProvider sutProvider, List data) { - sutProvider.GetDependency().GetManyByIds(data).Returns(new List()); - - var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteSecrets(data, default)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().SoftDeleteManyByIdAsync(default); - } - - [Theory] - [BitAutoData] - public async Task DeleteSecrets_OneIdNotFound_Throws_NotFoundException(List data, - SutProvider sutProvider) - { - var secret = new Secret() - { - Id = Guid.NewGuid() - }; - sutProvider.GetDependency().GetManyByIds(data).Returns(new List() { secret }); - - var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteSecrets(data, default)); - - await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().SoftDeleteManyByIdAsync(default); - } - - [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] - public async Task DeleteSecrets_Success(PermissionType permissionType, List data, - SutProvider sutProvider, Guid userId, Guid organizationId, Project mockProject) - { - List projects = null; - - if (permissionType == PermissionType.RunAsAdmin) - { - sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(true); - } - else - { - sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().AccessToProjectAsync(mockProject.Id, userId, AccessClientType.User) - .Returns((true, true)); - projects = new List() { mockProject }; - } - - - var secrets = new List(); - foreach (Guid id in data) - { - var secret = new Secret() - { - Id = id, - OrganizationId = organizationId, - Projects = projects - }; - secrets.Add(secret); - } - - sutProvider.GetDependency().GetManyByIds(data).Returns(secrets); - sutProvider.GetDependency().AccessSecretsManager(default).ReturnsForAnyArgs(true); - - var results = await sutProvider.Sut.DeleteSecrets(data, userId); - await sutProvider.GetDependency().Received(1).SoftDeleteManyByIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); - - foreach (var result in results) - { - Assert.Equal("", result.Item2); - } + await sutProvider.Sut.DeleteSecrets(data); + await sutProvider.GetDependency() + .Received(1) + .SoftDeleteManyByIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data.Select(d => d.Id)))); } } diff --git a/src/Api/SecretsManager/Controllers/SecretsController.cs b/src/Api/SecretsManager/Controllers/SecretsController.cs index dcf62f322b..99f641a172 100644 --- a/src/Api/SecretsManager/Controllers/SecretsController.cs +++ b/src/Api/SecretsManager/Controllers/SecretsController.cs @@ -8,6 +8,7 @@ using Bit.Core.Identity; using Bit.Core.Repositories; using Bit.Core.SecretsManager.AuthorizationRequirements; using Bit.Core.SecretsManager.Commands.Secrets.Interfaces; +using Bit.Core.SecretsManager.Entities; using Bit.Core.SecretsManager.Repositories; using Bit.Core.Services; using Bit.Core.Tools.Enums; @@ -170,9 +171,40 @@ public class SecretsController : Controller [HttpPost("secrets/delete")] public async Task> BulkDeleteAsync([FromBody] List ids) { - var userId = _userService.GetProperUserId(User).Value; - var results = await _deleteSecretCommand.DeleteSecrets(ids, userId); - var responses = results.Select(r => new BulkDeleteResponseModel(r.Item1.Id, r.Item2)); + var secrets = (await _secretRepository.GetManyByIds(ids)).ToList(); + if (!secrets.Any() || secrets.Count != ids.Count) + { + throw new NotFoundException(); + } + + // Ensure all secrets belong to the same organization. + var organizationId = secrets.First().OrganizationId; + if (secrets.Any(secret => secret.OrganizationId != organizationId) || + !_currentContext.AccessSecretsManager(organizationId)) + { + throw new NotFoundException(); + } + + var secretsToDelete = new List(); + var results = new List<(Secret Secret, string Error)>(); + + foreach (var secret in secrets) + { + var authorizationResult = + await _authorizationService.AuthorizeAsync(User, secret, SecretOperations.Delete); + if (authorizationResult.Succeeded) + { + secretsToDelete.Add(secret); + results.Add((secret, "")); + } + else + { + results.Add((secret, "access denied")); + } + } + + await _deleteSecretCommand.DeleteSecrets(secretsToDelete); + var responses = results.Select(r => new BulkDeleteResponseModel(r.Secret.Id, r.Error)); return new ListResponseModel(responses); } } diff --git a/src/Core/SecretsManager/AuthorizationRequirements/SecretOperationRequirement.cs b/src/Core/SecretsManager/AuthorizationRequirements/SecretOperationRequirement.cs index 8b1e8a6134..c6956ed306 100644 --- a/src/Core/SecretsManager/AuthorizationRequirements/SecretOperationRequirement.cs +++ b/src/Core/SecretsManager/AuthorizationRequirements/SecretOperationRequirement.cs @@ -10,4 +10,5 @@ public static class SecretOperations { public static readonly SecretOperationRequirement Create = new() { Name = nameof(Create) }; public static readonly SecretOperationRequirement Update = new() { Name = nameof(Update) }; + public static readonly SecretOperationRequirement Delete = new() { Name = nameof(Delete) }; } diff --git a/src/Core/SecretsManager/Commands/Secrets/Interfaces/IDeleteSecretCommand.cs b/src/Core/SecretsManager/Commands/Secrets/Interfaces/IDeleteSecretCommand.cs index 2517c70df7..300a810350 100644 --- a/src/Core/SecretsManager/Commands/Secrets/Interfaces/IDeleteSecretCommand.cs +++ b/src/Core/SecretsManager/Commands/Secrets/Interfaces/IDeleteSecretCommand.cs @@ -4,6 +4,6 @@ namespace Bit.Core.SecretsManager.Commands.Secrets.Interfaces; public interface IDeleteSecretCommand { - Task>> DeleteSecrets(List ids, Guid userId); + Task DeleteSecrets(IEnumerable secrets); } diff --git a/test/Api.IntegrationTest/SecretsManager/Controllers/SecretsControllerTests.cs b/test/Api.IntegrationTest/SecretsManager/Controllers/SecretsControllerTests.cs index 88b1a33508..b319b28594 100644 --- a/test/Api.IntegrationTest/SecretsManager/Controllers/SecretsControllerTests.cs +++ b/test/Api.IntegrationTest/SecretsManager/Controllers/SecretsControllerTests.cs @@ -644,10 +644,28 @@ public class SecretsControllerTests : IClassFixture, IAsy }); var secretIds = new[] { secret.Id }; - var response = await _client.PostAsJsonAsync($"/secrets/{org.Id}/delete", secretIds); + var response = await _client.PostAsJsonAsync($"/secrets/delete", secretIds); Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); } + [Fact] + public async Task Delete_MissingAccessPolicy_AccessDenied() + { + var (org, _) = await _organizationHelper.Initialize(true, true); + var (email, _) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true); + await LoginAsync(email); + + var (_, secretIds) = await CreateSecretsAsync(org.Id, 3); + + var response = await _client.PostAsync("/secrets/delete", JsonContent.Create(secretIds)); + + var results = await response.Content.ReadFromJsonAsync>(); + Assert.NotNull(results); + Assert.Equal(secretIds.OrderBy(x => x), + results!.Data.Select(x => x.Id).OrderBy(x => x)); + Assert.All(results.Data, item => Assert.Equal("access denied", item.Error)); + } + [Theory] [InlineData(PermissionType.RunAsAdmin)] [InlineData(PermissionType.RunAsUserWithPermission)] @@ -656,12 +674,7 @@ public class SecretsControllerTests : IClassFixture, IAsy var (org, _) = await _organizationHelper.Initialize(true, true); await LoginAsync(_email); - var project = await _projectRepository.CreateAsync(new Project() - { - Id = new Guid(), - OrganizationId = org.Id, - Name = _mockEncryptedString - }); + var (project, secretIds) = await CreateSecretsAsync(org.Id, 3); if (permissionType == PermissionType.RunAsUserWithPermission) { @@ -678,21 +691,6 @@ public class SecretsControllerTests : IClassFixture, IAsy await _accessPolicyRepository.CreateManyAsync(accessPolicies); } - - var secretIds = new List(); - for (var i = 0; i < 3; i++) - { - var secret = await _secretRepository.CreateAsync(new Secret - { - OrganizationId = org.Id, - Key = _mockEncryptedString, - Value = _mockEncryptedString, - Note = _mockEncryptedString, - Projects = new List() { project } - }); - secretIds.Add(secret.Id); - } - var response = await _client.PostAsJsonAsync($"/secrets/delete", secretIds); response.EnsureSuccessStatusCode(); @@ -710,4 +708,30 @@ public class SecretsControllerTests : IClassFixture, IAsy var secrets = await _secretRepository.GetManyByIds(secretIds); Assert.Empty(secrets); } + + private async Task<(Project Project, List secretIds)> CreateSecretsAsync(Guid orgId, int numberToCreate = 3) + { + var project = await _projectRepository.CreateAsync(new Project + { + Id = new Guid(), + OrganizationId = orgId, + Name = _mockEncryptedString + }); + + var secretIds = new List(); + for (var i = 0; i < numberToCreate; i++) + { + var secret = await _secretRepository.CreateAsync(new Secret + { + OrganizationId = orgId, + Key = _mockEncryptedString, + Value = _mockEncryptedString, + Note = _mockEncryptedString, + Projects = new List() { project } + }); + secretIds.Add(secret.Id); + } + + return (project, secretIds); + } } diff --git a/test/Api.Test/SecretsManager/Controllers/SecretsControllerTests.cs b/test/Api.Test/SecretsManager/Controllers/SecretsControllerTests.cs index dc677a19f4..8afa2000a4 100644 --- a/test/Api.Test/SecretsManager/Controllers/SecretsControllerTests.cs +++ b/test/Api.Test/SecretsManager/Controllers/SecretsControllerTests.cs @@ -244,45 +244,106 @@ public class SecretsControllerTests } [Theory] - [BitAutoData(PermissionType.RunAsAdmin)] - [BitAutoData(PermissionType.RunAsUserWithPermission)] - public async void BulkDeleteSecret_Success(PermissionType permissionType, SutProvider sutProvider, List data, Guid organizationId, Guid userId, Project mockProject) + [BitAutoData] + public async void BulkDelete_NoSecretsFound_ThrowsNotFound(SutProvider sutProvider, List data) { - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(userId); - - if (permissionType == PermissionType.RunAsAdmin) - { - sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(true); - } - else - { - data.FirstOrDefault().Projects = new List() { mockProject }; - sutProvider.GetDependency().OrganizationAdmin(organizationId).Returns(false); - sutProvider.GetDependency().AccessToProjectAsync(default, default, default) - .Returns((true, true)); - } - - - var ids = data.Select(secret => secret.Id).ToList(); - var mockResult = new List>(); - - foreach (var secret in data) - { - mockResult.Add(new Tuple(secret, "")); - } - sutProvider.GetDependency().DeleteSecrets(ids, userId).ReturnsForAnyArgs(mockResult); - - var results = await sutProvider.Sut.BulkDeleteAsync(ids); - await sutProvider.GetDependency().Received(1) - .DeleteSecrets(Arg.Is(ids), userId); - Assert.Equal(data.Count, results.Data.Count()); + var ids = data.Select(s => s.Id).ToList(); + sutProvider.GetDependency().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(new List()); + await Assert.ThrowsAsync(() => sutProvider.Sut.BulkDeleteAsync(ids)); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteSecrets(Arg.Any>()); } [Theory] [BitAutoData] - public async void BulkDeleteSecret_NoGuids_ThrowsArgumentNullException(SutProvider sutProvider) + public async void BulkDelete_SecretsFoundMisMatch_ThrowsNotFound(SutProvider sutProvider, List data, Secret mockSecret) { - sutProvider.GetDependency().GetProperUserId(default).ReturnsForAnyArgs(new Guid()); - await Assert.ThrowsAsync(() => sutProvider.Sut.BulkDeleteAsync(new List())); + data.Add(mockSecret); + var ids = data.Select(s => s.Id).ToList(); + sutProvider.GetDependency().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(new List { mockSecret }); + await Assert.ThrowsAsync(() => sutProvider.Sut.BulkDeleteAsync(ids)); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteSecrets(Arg.Any>()); + } + + [Theory] + [BitAutoData] + public async void BulkDelete_OrganizationMistMatch_ThrowsNotFound(SutProvider sutProvider, List data) + { + var ids = data.Select(s => s.Id).ToList(); + sutProvider.GetDependency().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(data); + await Assert.ThrowsAsync(() => sutProvider.Sut.BulkDeleteAsync(ids)); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteSecrets(Arg.Any>()); + } + + [Theory] + [BitAutoData] + public async void BulkDelete_NoAccessToSecretsManager_ThrowsNotFound(SutProvider sutProvider, List data) + { + var ids = data.Select(s => s.Id).ToList(); + var organizationId = data.First().OrganizationId; + foreach (var s in data) + { + s.OrganizationId = organizationId; + } + sutProvider.GetDependency().AccessSecretsManager(Arg.Is(organizationId)).ReturnsForAnyArgs(false); + sutProvider.GetDependency().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(data); + await Assert.ThrowsAsync(() => sutProvider.Sut.BulkDeleteAsync(ids)); + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteSecrets(Arg.Any>()); + } + + [Theory] + [BitAutoData] + public async void BulkDelete_ReturnsAccessDeniedForSecretsWithoutAccess_Success(SutProvider sutProvider, List data) + { + var ids = data.Select(s => s.Id).ToList(); + var organizationId = data.First().OrganizationId; + foreach (var secret in data) + { + secret.OrganizationId = organizationId; + sutProvider.GetDependency() + .AuthorizeAsync(Arg.Any(), secret, + Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); + } + sutProvider.GetDependency() + .AuthorizeAsync(Arg.Any(), data.First(), + Arg.Any>()).Returns(AuthorizationResult.Failed()); + sutProvider.GetDependency().AccessSecretsManager(Arg.Is(organizationId)).ReturnsForAnyArgs(true); + sutProvider.GetDependency().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(data); + + var results = await sutProvider.Sut.BulkDeleteAsync(ids); + + Assert.Equal(data.Count, results.Data.Count()); + Assert.Equal("access denied", results.Data.First().Error); + + data.Remove(data.First()); + await sutProvider.GetDependency().Received(1) + .DeleteSecrets(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } + + [Theory] + [BitAutoData] + public async void BulkDelete_Success(SutProvider sutProvider, List data) + { + var ids = data.Select(sa => sa.Id).ToList(); + var organizationId = data.First().OrganizationId; + foreach (var secret in data) + { + secret.OrganizationId = organizationId; + sutProvider.GetDependency() + .AuthorizeAsync(Arg.Any(), secret, + Arg.Any>()).ReturnsForAnyArgs(AuthorizationResult.Success()); + } + + sutProvider.GetDependency().AccessSecretsManager(Arg.Is(organizationId)).ReturnsForAnyArgs(true); + sutProvider.GetDependency().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(data); + + var results = await sutProvider.Sut.BulkDeleteAsync(ids); + + await sutProvider.GetDependency().Received(1) + .DeleteSecrets(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + Assert.Equal(data.Count, results.Data.Count()); + foreach (var result in results.Data) + { + Assert.Null(result.Error); + } } }