diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 82b37aa9f..0ea4b0b90 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -455,6 +455,7 @@ jobs: ASPNETCORE_ENVIRONMENT: Production swaggerGen: "True" DOTNET_ROLL_FORWARD_ON_NO_CANDIDATE_FX: 2 + GLOBALSETTINGS__SQLSERVER__CONNECTIONSTRING: "placeholder" - name: Upload Swagger artifact uses: actions/upload-artifact@6673cd052c4cd6fcf4b4e6e60ea986c889389535 diff --git a/bitwarden-server.sln b/bitwarden-server.sln index 2b5963e02..a8c3e2255 100644 --- a/bitwarden-server.sln +++ b/bitwarden-server.sln @@ -92,6 +92,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTestCommon", "te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Scim", "bitwarden_license\src\Scim\Scim.csproj", "{BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqlServerEFScaffold", "util\SqlServerEFScaffold\SqlServerEFScaffold.csproj", "{2F2E8BB0-6838-48DA-B581-71B9F13DE364}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Commercial.Infrastructure.EntityFramework", "bitwarden_license\src\Commercial.Infrastructure.EntityFramework\Commercial.Infrastructure.EntityFramework.csproj", "{5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Infrastructure.EFIntegration.Test", "test\Infrastructure.EFIntegration.Test\Infrastructure.EFIntegration.Test.csproj", "{7EFB1124-F40A-40EB-9EDA-94FD540AA8FD}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Api.IntegrationTest", "test\Api.IntegrationTest\Api.IntegrationTest.csproj", "{CBE96C6D-A4D6-46E1-94C5-42D6CAD8531C}" @@ -236,6 +240,14 @@ Global {BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747}.Debug|Any CPU.Build.0 = Debug|Any CPU {BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747}.Release|Any CPU.ActiveCfg = Release|Any CPU {BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747}.Release|Any CPU.Build.0 = Release|Any CPU + {2F2E8BB0-6838-48DA-B581-71B9F13DE364}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2F2E8BB0-6838-48DA-B581-71B9F13DE364}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2F2E8BB0-6838-48DA-B581-71B9F13DE364}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2F2E8BB0-6838-48DA-B581-71B9F13DE364}.Release|Any CPU.Build.0 = Release|Any CPU + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1}.Release|Any CPU.Build.0 = Release|Any CPU {7EFB1124-F40A-40EB-9EDA-94FD540AA8FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7EFB1124-F40A-40EB-9EDA-94FD540AA8FD}.Debug|Any CPU.Build.0 = Debug|Any CPU {7EFB1124-F40A-40EB-9EDA-94FD540AA8FD}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -299,6 +311,8 @@ Global {0D3B2BD2-53F3-421D-AD8F-C19B954C796B} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} {0923DE59-5FB1-44F2-9302-A09D2236B470} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} {BC3B3F8C-621A-4CB8-9563-6EC0A2C8C747} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A} + {2F2E8BB0-6838-48DA-B581-71B9F13DE364} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84E} + {5AB3BBFB-9D98-4EF8-BFCD-462D50A16EB1} = {4FDB6543-F68B-4202-9EA6-7FEA984D2D0A} {7EFB1124-F40A-40EB-9EDA-94FD540AA8FD} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} {CBE96C6D-A4D6-46E1-94C5-42D6CAD8531C} = {DD5BD056-4AAE-43EF-BBD2-0B569B8DA84F} {FE998849-5FC8-41A2-B7C9-9227901471A0} = {287CFF34-BBDB-4BC4-AF88-1E19A5A4679B} diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/AccessTokens/CreateAccessTokenCommand.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/AccessTokens/CreateAccessTokenCommand.cs new file mode 100644 index 000000000..3d1cf574b --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/AccessTokens/CreateAccessTokenCommand.cs @@ -0,0 +1,23 @@ +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.AccessTokens.Interfaces; +using Bit.Core.Utilities; + +namespace Bit.Commercial.Core.SecretManagerFeatures.AccessTokens; + +public class CreateAccessTokenCommand : ICreateAccessTokenCommand +{ + private readonly int _clientSecretMaxLength = 30; + private readonly IApiKeyRepository _apiKeyRepository; + + public CreateAccessTokenCommand(IApiKeyRepository apiKeyRepository) + { + _apiKeyRepository = apiKeyRepository; + } + + public async Task CreateAsync(ApiKey apiKey) + { + apiKey.ClientSecret = CoreHelpers.SecureRandomString(_clientSecretMaxLength); + return await _apiKeyRepository.CreateAsync(apiKey); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Projects/CreateProjectCommand.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Projects/CreateProjectCommand.cs new file mode 100644 index 000000000..2f703b2f9 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Projects/CreateProjectCommand.cs @@ -0,0 +1,20 @@ +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.Projects.Interfaces; + +namespace Bit.Commercial.Core.SecretManagerFeatures.Projects; + +public class CreateProjectCommand : ICreateProjectCommand +{ + private readonly IProjectRepository _projectRepository; + + public CreateProjectCommand(IProjectRepository projectRepository) + { + _projectRepository = projectRepository; + } + + public async Task CreateAsync(Project project) + { + return await _projectRepository.CreateAsync(project); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Projects/DeleteProjectCommand.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Projects/DeleteProjectCommand.cs new file mode 100644 index 000000000..3d2061418 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Projects/DeleteProjectCommand.cs @@ -0,0 +1,44 @@ +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.Projects.Interfaces; + +namespace Bit.Commercial.Core.SecretManagerFeatures.Projects; + +public class DeleteProjectCommand : IDeleteProjectCommand +{ + private readonly IProjectRepository _projectRepository; + + public DeleteProjectCommand(IProjectRepository projectRepository) + { + _projectRepository = projectRepository; + } + + public async Task>> DeleteProjects(List ids) + { + var projects = await _projectRepository.GetManyByIds(ids); + + if (projects?.Any() != true) + { + throw new NotFoundException(); + } + + var results = ids.Select(id => + { + var project = projects.FirstOrDefault(project => project.Id == id); + if (project == null) + { + throw new NotFoundException(); + } + // TODO Once permissions are implemented add check for each project here. + else + { + return new Tuple(project, ""); + } + }).ToList(); + + await _projectRepository.DeleteManyByIdAsync(ids); + return results; + } +} + diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Projects/UpdateProjectCommand.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Projects/UpdateProjectCommand.cs new file mode 100644 index 000000000..1e0163ecc --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Projects/UpdateProjectCommand.cs @@ -0,0 +1,33 @@ +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.Projects.Interfaces; + +namespace Bit.Commercial.Core.SecretManagerFeatures.Projects; + +public class UpdateProjectCommand : IUpdateProjectCommand +{ + private readonly IProjectRepository _projectRepository; + + public UpdateProjectCommand(IProjectRepository projectRepository) + { + _projectRepository = projectRepository; + } + + public async Task UpdateAsync(Project project) + { + var existingProject = await _projectRepository.GetByIdAsync(project.Id); + if (existingProject == null) + { + throw new NotFoundException(); + } + + project.OrganizationId = existingProject.OrganizationId; + project.CreationDate = existingProject.CreationDate; + project.DeletedDate = existingProject.DeletedDate; + project.RevisionDate = DateTime.UtcNow; + + await _projectRepository.ReplaceAsync(project); + return project; + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/SecretManagerCollectionExtensions.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/SecretManagerCollectionExtensions.cs new file mode 100644 index 000000000..f4a4f1bee --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/SecretManagerCollectionExtensions.cs @@ -0,0 +1,28 @@ +using Bit.Commercial.Core.SecretManagerFeatures.AccessTokens; +using Bit.Commercial.Core.SecretManagerFeatures.Projects; +using Bit.Commercial.Core.SecretManagerFeatures.Secrets; +using Bit.Commercial.Core.SecretManagerFeatures.ServiceAccounts; +using Bit.Core.SecretManagerFeatures.AccessTokens.Interfaces; +using Bit.Core.SecretManagerFeatures.Projects.Interfaces; +using Bit.Core.SecretManagerFeatures.Secrets.Interfaces; +using Bit.Core.SecretManagerFeatures.ServiceAccounts.Interfaces; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Core.SecretManagerFeatures; + +public static class SecretManagerCollectionExtensions +{ + public static void AddSecretManagerServices(this IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + } +} + diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Secrets/CreateSecretCommand.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Secrets/CreateSecretCommand.cs new file mode 100644 index 000000000..17c812ca4 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Secrets/CreateSecretCommand.cs @@ -0,0 +1,20 @@ +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.Secrets.Interfaces; + +namespace Bit.Commercial.Core.SecretManagerFeatures.Secrets; + +public class CreateSecretCommand : ICreateSecretCommand +{ + private readonly ISecretRepository _secretRepository; + + public CreateSecretCommand(ISecretRepository secretRepository) + { + _secretRepository = secretRepository; + } + + public async Task CreateAsync(Secret secret) + { + return await _secretRepository.CreateAsync(secret); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Secrets/DeleteSecretCommand.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Secrets/DeleteSecretCommand.cs new file mode 100644 index 000000000..1a4d83c51 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Secrets/DeleteSecretCommand.cs @@ -0,0 +1,44 @@ +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.Secrets.Interfaces; + +namespace Bit.Commercial.Core.SecretManagerFeatures.Secrets; + +public class DeleteSecretCommand : IDeleteSecretCommand +{ + private readonly ISecretRepository _secretRepository; + + public DeleteSecretCommand(ISecretRepository secretRepository) + { + _secretRepository = secretRepository; + } + + public async Task>> DeleteSecrets(List ids) + { + var secrets = await _secretRepository.GetManyByIds(ids); + + if (secrets?.Any() != true) + { + throw new NotFoundException(); + } + + var results = ids.Select(id => + { + var secret = secrets.FirstOrDefault(secret => secret.Id == id); + if (secret == null) + { + throw new NotFoundException(); + } + // TODO Once permissions are implemented add check for each secret here. + else + { + return new Tuple(secret, ""); + } + }).ToList(); + + await _secretRepository.SoftDeleteManyByIdAsync(ids); + return results; + } +} + diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Secrets/UpdateSecretCommand.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Secrets/UpdateSecretCommand.cs new file mode 100644 index 000000000..0f8030804 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/Secrets/UpdateSecretCommand.cs @@ -0,0 +1,33 @@ +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.Secrets.Interfaces; + +namespace Bit.Commercial.Core.SecretManagerFeatures.Secrets; + +public class UpdateSecretCommand : IUpdateSecretCommand +{ + private readonly ISecretRepository _secretRepository; + + public UpdateSecretCommand(ISecretRepository secretRepository) + { + _secretRepository = secretRepository; + } + + public async Task UpdateAsync(Secret secret) + { + var existingSecret = await _secretRepository.GetByIdAsync(secret.Id); + if (existingSecret == null) + { + throw new NotFoundException(); + } + + secret.OrganizationId = existingSecret.OrganizationId; + secret.CreationDate = existingSecret.CreationDate; + secret.DeletedDate = existingSecret.DeletedDate; + secret.RevisionDate = DateTime.UtcNow; + + await _secretRepository.UpdateAsync(secret); + return secret; + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/ServiceAccounts/CreateServiceAccountCommand.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/ServiceAccounts/CreateServiceAccountCommand.cs new file mode 100644 index 000000000..db49d3342 --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/ServiceAccounts/CreateServiceAccountCommand.cs @@ -0,0 +1,20 @@ +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.ServiceAccounts.Interfaces; + +namespace Bit.Commercial.Core.SecretManagerFeatures.ServiceAccounts; + +public class CreateServiceAccountCommand : ICreateServiceAccountCommand +{ + private readonly IServiceAccountRepository _serviceAccountRepository; + + public CreateServiceAccountCommand(IServiceAccountRepository serviceAccountRepository) + { + _serviceAccountRepository = serviceAccountRepository; + } + + public async Task CreateAsync(ServiceAccount serviceAccount) + { + return await _serviceAccountRepository.CreateAsync(serviceAccount); + } +} diff --git a/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/ServiceAccounts/UpdateServiceAccountCommand.cs b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/ServiceAccounts/UpdateServiceAccountCommand.cs new file mode 100644 index 000000000..2fad0567a --- /dev/null +++ b/bitwarden_license/src/Commercial.Core/SecretManagerFeatures/ServiceAccounts/UpdateServiceAccountCommand.cs @@ -0,0 +1,32 @@ +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.ServiceAccounts.Interfaces; + +namespace Bit.Commercial.Core.SecretManagerFeatures.ServiceAccounts; + +public class UpdateServiceAccountCommand : IUpdateServiceAccountCommand +{ + private readonly IServiceAccountRepository _serviceAccountRepository; + + public UpdateServiceAccountCommand(IServiceAccountRepository serviceAccountRepository) + { + _serviceAccountRepository = serviceAccountRepository; + } + + public async Task UpdateAsync(ServiceAccount serviceAccount) + { + var existingServiceAccount = await _serviceAccountRepository.GetByIdAsync(serviceAccount.Id); + if (existingServiceAccount == null) + { + throw new NotFoundException(); + } + + serviceAccount.OrganizationId = existingServiceAccount.OrganizationId; + serviceAccount.CreationDate = existingServiceAccount.CreationDate; + serviceAccount.RevisionDate = DateTime.UtcNow; + + await _serviceAccountRepository.ReplaceAsync(serviceAccount); + return serviceAccount; + } +} diff --git a/bitwarden_license/src/Commercial.Core/Utilities/ServiceCollectionExtensions.cs b/bitwarden_license/src/Commercial.Core/Utilities/ServiceCollectionExtensions.cs index 5bb1a5bde..07881c4a3 100644 --- a/bitwarden_license/src/Commercial.Core/Utilities/ServiceCollectionExtensions.cs +++ b/bitwarden_license/src/Commercial.Core/Utilities/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ -using Bit.Commercial.Core.Services; +using Bit.Commercial.Core.SecretManagerFeatures; +using Bit.Commercial.Core.Services; using Bit.Core.Services; using Microsoft.Extensions.DependencyInjection; @@ -6,8 +7,13 @@ namespace Bit.Commercial.Core.Utilities; public static class ServiceCollectionExtensions { - public static void AddCommCoreServices(this IServiceCollection services) + public static void AddCommercialCoreServices(this IServiceCollection services) { services.AddScoped(); } + + public static void AddCommercialSecretsManagerServices(this IServiceCollection services) + { + services.AddSecretManagerServices(); + } } diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Commercial.Infrastructure.EntityFramework.csproj b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Commercial.Infrastructure.EntityFramework.csproj new file mode 100644 index 000000000..7e94399c0 --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Commercial.Infrastructure.EntityFramework.csproj @@ -0,0 +1,13 @@ + + + + enable + + + + + + + + + diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/CommercialEFServiceCollectionExtensions.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/CommercialEFServiceCollectionExtensions.cs new file mode 100644 index 000000000..1fbc1bf9d --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/CommercialEFServiceCollectionExtensions.cs @@ -0,0 +1,18 @@ +using Bit.Commercial.Infrastructure.EntityFramework.Repositories; +using Bit.Core.Repositories; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Infrastructure.EntityFramework; + +public static class CommercialEFServiceCollectionExtensions +{ + public static void AddCommercialEFRepositories(this IServiceCollection services) + { + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + } +} + diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Repositories/ProjectRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Repositories/ProjectRepository.cs new file mode 100644 index 000000000..b500a5734 --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Repositories/ProjectRepository.cs @@ -0,0 +1,73 @@ +using System.Linq.Expressions; +using AutoMapper; +using Bit.Core.Repositories; +using Bit.Infrastructure.EntityFramework.Models; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Infrastructure.EntityFramework.Repositories; + +public class ProjectRepository : Repository, IProjectRepository +{ + public ProjectRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) + : base(serviceScopeFactory, mapper, db => db.Project) + { } + + public override async Task GetByIdAsync(Guid id) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var project = await dbContext.Project + .Where(c => c.Id == id && c.DeletedDate == null) + .FirstOrDefaultAsync(); + return Mapper.Map(project); + } + } + + public async Task> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId) + { + using var scope = ServiceScopeFactory.CreateScope(); + var dbContext = GetDatabaseContext(scope); + var project = await dbContext.Project + .Where(p => p.OrganizationId == organizationId && p.DeletedDate == null) + // TODO: Enable this + Handle Admins + //.Where(UserHasAccessToProject(userId)) + .OrderBy(p => p.RevisionDate) + .ToListAsync(); + return Mapper.Map>(project); + } + + private static Expression> UserHasAccessToProject(Guid userId) => p => + p.UserAccessPolicies.Any(ap => ap.OrganizationUser.User.Id == userId && ap.Read) || + p.GroupAccessPolicies.Any(ap => ap.Group.GroupUsers.Any(gu => gu.OrganizationUser.User.Id == userId && ap.Read)); + + public async Task DeleteManyByIdAsync(IEnumerable ids) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var utcNow = DateTime.UtcNow; + var projects = dbContext.Project.Where(c => ids.Contains(c.Id)); + await projects.ForEachAsync(project => + { + dbContext.Remove(project); + }); + await dbContext.SaveChangesAsync(); + } + } + + public async Task> GetManyByIds(IEnumerable ids) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var projects = await dbContext.Project + .Where(c => ids.Contains(c.Id) && c.DeletedDate == null) + .ToListAsync(); + return Mapper.Map>(projects); + } + + } +} diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Repositories/SecretRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Repositories/SecretRepository.cs new file mode 100644 index 000000000..1a31bf36c --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Repositories/SecretRepository.cs @@ -0,0 +1,139 @@ +using AutoMapper; +using Bit.Core.Repositories; +using Bit.Infrastructure.EntityFramework; +using Bit.Infrastructure.EntityFramework.Models; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Infrastructure.EntityFramework.Repositories; + +public class SecretRepository : Repository, ISecretRepository +{ + public SecretRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) + : base(serviceScopeFactory, mapper, db => db.Secret) + { } + + public override async Task GetByIdAsync(Guid id) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var secret = await dbContext.Secret + .Include("Projects") + .Where(c => c.Id == id && c.DeletedDate == null) + .FirstOrDefaultAsync(); + return Mapper.Map(secret); + } + } + + public async Task> GetManyByIds(IEnumerable ids) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var secrets = await dbContext.Secret + .Where(c => ids.Contains(c.Id) && c.DeletedDate == null) + .ToListAsync(); + return Mapper.Map>(secrets); + } + } + + public async Task> GetManyByOrganizationIdAsync(Guid organizationId) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var secrets = await dbContext.Secret + .Where(c => c.OrganizationId == organizationId && c.DeletedDate == null) + .Include("Projects") + .OrderBy(c => c.RevisionDate) + .ToListAsync(); + + return Mapper.Map>(secrets); + } + } + + public async Task> GetManyByProjectIdAsync(Guid projectId) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var secrets = await dbContext.Secret + .Where(s => s.Projects.Any(p => p.Id == projectId) && s.DeletedDate == null).Include("Projects") + .OrderBy(s => s.RevisionDate).ToListAsync(); + + return Mapper.Map>(secrets); + } + } + + public override async Task CreateAsync(Core.Entities.Secret secret) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + secret.SetNewId(); + var entity = Mapper.Map(secret); + + if (secret.Projects?.Count > 0) + { + foreach (var p in entity.Projects) + { + dbContext.Attach(p); + } + } + + await dbContext.AddAsync(entity); + await dbContext.SaveChangesAsync(); + secret.Id = entity.Id; + return secret; + } + } + + public async Task UpdateAsync(Core.Entities.Secret secret) + { + + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var mappedEntity = Mapper.Map(secret); + var entity = await dbContext.Secret + .Include("Projects") + .FirstAsync(s => s.Id == secret.Id); + + foreach (var p in entity.Projects?.Where(p => mappedEntity.Projects.All(mp => mp.Id != p.Id))) + { + entity.Projects.Remove(p); + } + + // Add new relationships + foreach (var project in mappedEntity.Projects?.Where(p => entity.Projects.All(ep => ep.Id != p.Id))) + { + var p = dbContext.AttachToOrGet(_ => _.Id == project.Id, () => project); + entity.Projects.Add(p); + } + + dbContext.Entry(entity).CurrentValues.SetValues(mappedEntity); + await dbContext.SaveChangesAsync(); + } + + return secret; + } + + public async Task SoftDeleteManyByIdAsync(IEnumerable ids) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var utcNow = DateTime.UtcNow; + var secrets = dbContext.Secret.Where(c => ids.Contains(c.Id)); + await secrets.ForEachAsync(secret => + { + dbContext.Attach(secret); + secret.DeletedDate = utcNow; + secret.RevisionDate = utcNow; + }); + await dbContext.SaveChangesAsync(); + } + } +} diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Repositories/ServiceAccountRepository.cs b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Repositories/ServiceAccountRepository.cs new file mode 100644 index 000000000..e04d65ce8 --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/Repositories/ServiceAccountRepository.cs @@ -0,0 +1,28 @@ +using AutoMapper; +using Bit.Core.Repositories; +using Bit.Infrastructure.EntityFramework.Models; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Commercial.Infrastructure.EntityFramework.Repositories; + +public class ServiceAccountRepository : Repository, IServiceAccountRepository +{ + public ServiceAccountRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) + : base(serviceScopeFactory, mapper, db => db.ServiceAccount) + { } + + public async Task> GetManyByOrganizationIdAsync(Guid organizationId) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var serviceAccounts = await dbContext.ServiceAccount + .Where(c => c.OrganizationId == organizationId) + .OrderBy(c => c.RevisionDate) + .ToListAsync(); + return Mapper.Map>(serviceAccounts); + } + } +} diff --git a/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json new file mode 100644 index 000000000..a963bc593 --- /dev/null +++ b/bitwarden_license/src/Commercial.Infrastructure.EntityFramework/packages.lock.json @@ -0,0 +1,2747 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": { + "type": "Direct", + "requested": "[11.0.0, )", + "resolved": "11.0.0", + "contentHash": "0asw5WxdCFh2OTi9Gv+oKyH9SzxwYQSnO8TV5Dd0GggovILzJW4UimP26JAcxc3yB5NnC5urooZ1BBs8ElpiBw==", + "dependencies": { + "AutoMapper": "11.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AutoMapper": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "+596AnKykYCk9RxXCEF4GYuapSebQtFVvIA1oVG1rrRkCLAC7AkWehJ0brCfYUbdDW3v1H/p0W3hob7JoXGjMw==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.22.0", + "contentHash": "ze/xRCHSSDe5TIk5vBDbVrauW1EN7UIbnBvIBfMH8KSt/I9+/7yPAjTBDgNBk0IwG6WBV+BBHp4IUtS/PGAQwQ==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.3.0", + "contentHash": "l1SYfZKOFBuUFG7C2SWHmJcrQQaiXgBdVCycx4vcZQkC6efDVt7mzZ5pfJAFEJDBUq7mjRQ0RPq9ZDGdSswqMg==", + "dependencies": { + "Azure.Core": "1.6.0", + "Microsoft.Identity.Client": "4.22.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.16.5", + "System.Memory": "4.5.3", + "System.Security.Cryptography.ProtectedData": "4.5.0", + "System.Text.Json": "4.6.0", + "System.Threading.Tasks.Extensions": "4.5.2" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.0-beta2", + "contentHash": "FnNMbK88dyPp0Ww/iMim5g89rSPdqkjQiDiTJJtvxDcEk8JK/eBdTzAl4myNaKS9e8PKrxxddOTrnNja3PHGtQ==", + "dependencies": { + "Fido2.Models": "3.0.0-beta2", + "NSec.Cryptography": "20.2.0", + "System.Formats.Cbor": "5.0.0", + "System.IdentityModel.Tokens.Jwt": "6.6.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.0-beta2", + "contentHash": "qkowZS0WPS26gDG97rwjZObOa/xtFVjSpvWHl3OwWRQ9ZU5xNePXKk2XJWmO2MCQc40idxyEOfA34MMexCHc3w==", + "dependencies": { + "Fido2": "3.0.0-beta2", + "Fido2.Models": "3.0.0-beta2" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.0-beta2", + "contentHash": "6ePSMUtqz6lAfDUjDvOONMLugcKiAyz8hzoLSAISk3iDIjBMLMPlZSV3TVZqiY+5SAzC8x61OHNoCODqorucNw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18", + "contentHash": "Ajv3AR9Qg/C4SQcE2ONx/UieeKnn5lSvVNc6egC3p6NP6qjZzWJ+Xg2vJURNYjkpHui/KctBwQjMPqpZK8/CHA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1" + } + }, + "linq2db": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "6/u1EzQlV25bhN0Ej/I5dLV5Hgxun+ww/TX2VnMBnSVytED2VzQGeFIO/14I624GkfPOtB79x1ooL3F18dAbdw==" + }, + "linq2db.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.11.0", + "contentHash": "mS+L6HyVHP3oJaTuFVZswNmPpTfYleGjDTo2IWBJmYXZpSQ5EPw1DpHzmyLAiQd+93ofy0Ala+9HWzv6/k73ZQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "6.0.5", + "linq2db": "4.4.0" + } + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "G+UoMHL0xiyFh30wkL7Bv/XL6eugTAKYhLPS53k1/Me1bYRwOOw+8VL/q0ppq3/yMzpHX+MkExaCTDlYl48FgA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", + "Microsoft.Extensions.Logging.Abstractions": "2.1.0", + "Microsoft.Extensions.Options": "2.1.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2+HVDhUqrnV9+EJNEewSy+Gk4hOVPzLPMpFDZI7kuH7NWxtbNkI6A6gT5lO2/kEPMyM8/iLWtohbOwjpC9rHVw==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "1TQgBfd/NPZLR2o/h6l5Cml2ZCF5hsyV4h9WEwWwAIavrbdTnaNozGGcTOd4AOgQvogMM9UM1ajflm9Cwd0jLQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "YTKMi2vHX6P+WHEVpW/DS+eFHnwivCSMklkyamcK1ETtc/4j8H3VR0kgW8XIBqukNxhD8k5wYt22P7PhrWSXjQ==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "vbFDyKsSYBnxl3+RABtN79b0vsTcG66fDY8vD6Nqvu9uLtSej70Q5NcbGlnN6bJpZci5orSdgFTHMhBywivDPg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "UmkUePxRjsQW0j5euFFscBwjvTu25b8+qIK/2fI3GvcqQ+mkwgbWNAT8b/Gkoei1m2bTWC07lSdutuRDPPLcJA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.0" + } + }, + "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" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "o/sIRlcKEcI9vg5z9USqJ/VCxtUUBYEOXYr4TrkMNu+gGBh0KfUi06Jqpe+xZgeoxcqYruV9dLOn046uFA4vHQ==", + "dependencies": { + "Azure.Identity": "1.3.0", + "Microsoft.Data.SqlClient.SNI.runtime": "4.0.0", + "Microsoft.Identity.Client": "4.22.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.8.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.8.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "wtLlRwQX7YoBUYm25xBjJ3UsuLgycme1xXqDn8t3S5kPCWiZrx8uOkyZHLKzH4kkCiQ9m2/J5JeCKNRbZNn3Qg==" + }, + "Microsoft.Data.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bui5wPPqq9OwTL5A+YJPcVStTPrOFcLwg/kAVWyqdjrTief4kTK/3bNv0MqUDVNgAUG8pcFbtdc674CIh1F3gw==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "xb10XFoPf/gWu8ik5v7xnVyUY7W21LBOLtT7PidzwYVdnE3aKuQ/bIZLcQuY7rdDNT89/wse2q5FRjm207cIMQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Analyzers": "6.0.12", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.Logging": "6.0.0", + "System.Collections.Immutable": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Abstractions": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "hvRytAcLhrb35HmtMjYWsNZZLt39ryuN7j04lDchRa9VToreyqgo5gMniTdQ6MfCflxtGnDes65V/Y2pjbEyWg==" + }, + "Microsoft.EntityFrameworkCore.Analyzers": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "ZDUY+KlsIyKdfvIJeNdqRiPExFQ5GRZVdx/Cp52vhpCJRImYv34O0Xfmw2eiLu4qe1jmM2pTzAAFKELaKwtj/w==" + }, + "Microsoft.EntityFrameworkCore.Relational": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "HBtRGHtF0Vf+BIQTkRGiopmE5rLYhj59xPpd17S1tLgYpiHDVbepCuHwh5H63fzjO99Z4tW5wmmEGF7KnD91WQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "2Hutlqt07bnWZFtYqT1lj0otX8ygMyBikysGnfQNF2TK3i5GqSTeJ8tqNi/URiI9II7Cyl15A0rflXmFoySuIw==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Sqlite.Core": "6.0.12", + "SQLitePCLRaw.bundle_e_sqlite3": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "07vKE7+t9Z2BfGmHuJwNZNv8m1GWt7ZpYYHFh1tQg1oC6FJ78bSaFzLawsf2NK6CLhbB8DBsjE0rRhxMJ4rXsA==", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Microsoft.Extensions.DependencyModel": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "IznHHzGUtrdpuQqIUdmzF6TYPcsYHONhHh3o9dGp39sX/9Zfmt476UnhvU0UhXgJnXXAikt/MpN6AuSLCCMdEQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "7ZJUKwPipkDvuv2KJPZ3r01wp2AWNMiYH+61i0dL89F7QICknjKpWgLKLpTSUYFgl77S3b4264I6i4HzDdrb2A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y/lGICwO27fCkQRK3tZseVzFjZaxfGmui990E67sB4MuiPzdJHnJDS/BeYWrHShSSBgCl4KyKRx4ux686fftPg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0", + "Microsoft.Extensions.Options": "2.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.22.0", + "contentHash": "GlamU9rs8cSVIx9WSGv5QKpt66KkE+ImxNa/wNZZUJ3knt3PM98T9sOY8B7NcEfhw7NoxU2/0TSOcmnRSJQgqw==" + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.16.5", + "contentHash": "VlGUZEpF8KP/GCfFI59sdE0WA0o9quqwM1YQY0dSp6jpGy5EOBkureaybLfpwCuYUUjQbLkN2p7neUIcQCfbzA==", + "dependencies": { + "Microsoft.Identity.Client": "4.22.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "0qjS31rN1MQTc46tAYbzmMTSRfdV5ndZxSjYxIGqKSidd4wpNJfNII/pdhU5Fx8olarQoKL9lqqYw4yNOIwT0Q==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.10.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "zbcwV6esnNzhZZ/VP87dji6VrUBLB5rxnZBkDMqNYpyG+nrBnBsbm4PUYLCBMUflHCM9EMLDG0rLnqqT+l0ldA==" + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "DFyXD0xylP+DknCT3hzJ7q/Q5qRNu0hO/gCU90O0ATdR0twZmlcuY9RNYaaDofXKVbzcShYNCFCGle2G/o8mkg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.10.0", + "Microsoft.IdentityModel.Tokens": "6.10.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "LVvMXAWPbPeEWTylDrxunlHH2wFyE4Mv0L4gZrJHC4HTESbWHquKZb/y/S8jgiQEDycOP0PDQvbG4RR/tr2TVQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.10.0", + "System.IdentityModel.Tokens.Jwt": "6.10.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "qbf1NslutDB4oLrriYTJpy7oB1pbh2ej2lEHd2IPDQH9C74ysOdhU5wAC7KoXblldbo7YsNR2QYFOqQM/b0Rsg==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.10.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "MySqlConnector": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "JVokQTUNN3WHAu9Vw8ieeq1dXTFokJiig5P0VJ4f439UxRrsPo6SaVWC8Zdm6mkPeQFhZ0/9afdWa02EY/1j/w==" + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "Npgsql": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "wKa8MJEJaj0xQXUQZGv7q/KfPID23jSSvFFtljMworrv7dNajr0GN8PCU1SpywqHjMWdYEfK29DY1aYbiISbQg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Npgsql.EntityFrameworkCore.PostgreSQL": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "YJRpO+3wXQyWuwRUCVJj/Rsn46sY0bZ6uCGOEFApiRe0ZYJ6N6TxZUWKbTNJYjesickcLGzynOerpSbDJX1AYg==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Npgsql": "6.0.8" + } + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "20.2.0", + "contentHash": "NxzHaDQm3JfH+9VQdLI1bC4h/ZTKPo5o/4BEscBu4KK0Yv35sB87hSRuzpr09VahxY5ZpJfE2tHyK4u27jfiyQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "4.7.0", + "libsodium": "[1.0.18, 1.0.19)" + } + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Pomelo.EntityFrameworkCore.MySql": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "KvlZ800CnEuEGnxj5OT1fCKGjQXxW5kpPlCP91JqBYG+2Z3927eqXmlX6LLKUt4swqE8ZsEQ+Zkpab8bqstf4g==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "[6.0.7, 7.0.0)", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "MySqlConnector": "2.1.2" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "SQLitePCLRaw.bundle_e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "ilkvNhrTersLmIVAcDwwPqfhUFCg19Z1GVMvCSi3xk6Akq94f4qadLORQCq/T8+9JgMiPs+F/NECw5uauviaNw==", + "dependencies": { + "SQLitePCLRaw.lib.e_sqlite3": "2.1.2", + "SQLitePCLRaw.provider.e_sqlite3": "2.1.2" + } + }, + "SQLitePCLRaw.core": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "A8EBepVqY2lnAp3a8jnhbgzF2tlj2S3HcJQGANTYg/TbYbKa8Z5cM1h74An/vy0svhfzT7tVY0sFmUglLgv+2g==", + "dependencies": { + "System.Memory": "4.5.3" + } + }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "zibGtku8M4Eea1R3ZCAxc86QbNvyEN17mAcQkvWKBuHvRpMiK2g5anG4R5Be7cWKSd1i6baYz8y4dMMAKcXKPg==" + }, + "SQLitePCLRaw.provider.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "lxCZarZdvAsMl2zw9bXHrXK6RxVhB4b23iTFhCOdHFhxfbsxLxWf+ocvswJwR/9Wh/E//ddMi+wJGqUKV7VwoA==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "/HKQyVP0yH1I0YtK7KJL/28snxHNH/bi+0lgk/+MbURF6ULhAE31MDI+NZDerNWu264YbxklXCCygISgm+HMug==", + "dependencies": { + "System.Collections.NonGeneric": "4.0.1", + "System.Globalization": "4.0.11", + "System.Globalization.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "6WVCczFZKXwpWpzd/iJkYnsmWTSFFiU24Xx/YdHXBcu+nFI/ehTgeqdJQFbtRPzbrO3KtRNjvkhtj4t5/WwWsA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "OJ8UXNyYIvu22ZrMHDBcnBvs3l6w2wEWUSwgPf2gimUrdoKJC4pcg963kiYAA9kvs8HYLQKQ+2Arr7pm19aZ4A==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "C+Q5ORsFycRkRuvy/Xd0Pv5xVpmWSAvQYZAGs7VQogmkqlLhvfZXTgBIlHqC3cxkstSoLJAYx6xZB7foQ2y5eg==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.10.0", + "Microsoft.IdentityModel.Tokens": "6.10.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "qEePWsaq9LoEEIqhbGe6D5J8c9IqQOUuTzzV6wn1POlfdLkJliZY3OlB0j0f17uMWlqZYjH7txj+2YbyrIA8Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "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.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.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.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.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.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "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", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.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.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.0-beta2, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "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": "[4.1.0, )", + "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.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2022.12.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, )" + } + } + } + } +} \ No newline at end of file diff --git a/bitwarden_license/src/Scim/packages.lock.json b/bitwarden_license/src/Scim/packages.lock.json index 547bc6c9a..8872d119d 100644 --- a/bitwarden_license/src/Scim/packages.lock.json +++ b/bitwarden_license/src/Scim/packages.lock.json @@ -644,6 +644,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3026,6 +3035,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/bitwarden_license/src/Sso/packages.lock.json b/bitwarden_license/src/Sso/packages.lock.json index 630f3a8e1..aa6b33739 100644 --- a/bitwarden_license/src/Sso/packages.lock.json +++ b/bitwarden_license/src/Sso/packages.lock.json @@ -625,6 +625,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2896,6 +2905,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/AccessTokens/CreateAccessTokenCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/AccessTokens/CreateAccessTokenCommandTests.cs new file mode 100644 index 000000000..e9a9c7ba8 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/AccessTokens/CreateAccessTokenCommandTests.cs @@ -0,0 +1,25 @@ +using Bit.Commercial.Core.SecretManagerFeatures.AccessTokens; +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretManagerFeatures.AccessTokens; + +[SutProviderCustomize] +public class CreateServiceAccountCommandTests +{ + [Theory] + [BitAutoData] + public async Task CreateAsync_CallsCreate(ApiKey data, + SutProvider sutProvider) + { + await sutProvider.Sut.CreateAsync(data); + + await sutProvider.GetDependency().Received(1) + .CreateAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Projects/DeleteProjectCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Projects/DeleteProjectCommandTests.cs new file mode 100644 index 000000000..c9dca6242 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Projects/DeleteProjectCommandTests.cs @@ -0,0 +1,69 @@ +using Bit.Commercial.Core.SecretManagerFeatures.Projects; +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretManagerFeatures.Projects; + +[SutProviderCustomize] +public class DeleteProjectCommandTests +{ + [Theory] + [BitAutoData] + public async Task DeleteProjects_Throws_NotFoundException(List data, + SutProvider sutProvider) + { + sutProvider.GetDependency().GetManyByIds(data).Returns(new List()); + + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteProjects(data)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteManyByIdAsync(default); + } + + [Theory] + [BitAutoData] + public async Task DeleteSecrets_OneIdNotFound_Throws_NotFoundException(List data, + SutProvider sutProvider) + { + var project = new Project() + { + Id = Guid.NewGuid() + }; + sutProvider.GetDependency().GetManyByIds(data).Returns(new List() { project }); + + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteProjects(data)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().DeleteManyByIdAsync(default); + } + + [Theory] + [BitAutoData] + public async Task DeleteSecrets_Success(List data, + SutProvider sutProvider) + { + var projects = new List(); + foreach (Guid id in data) + { + var project = new Project() + { + Id = id + }; + projects.Add(project); + } + + sutProvider.GetDependency().GetManyByIds(data).Returns(projects); + + var results = await sutProvider.Sut.DeleteProjects(data); + + await sutProvider.GetDependency().Received(1).DeleteManyByIdAsync(Arg.Is(data)); + foreach (var result in results) + { + Assert.Equal("", result.Item2); + } + } +} + diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Secrets/CreateSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Secrets/CreateSecretCommandTests.cs new file mode 100644 index 000000000..2dcca20b7 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Secrets/CreateSecretCommandTests.cs @@ -0,0 +1,27 @@ +using Bit.Commercial.Core.SecretManagerFeatures.Secrets; +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Core.Test.AutoFixture.SecretsFixture; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretManagerFeatures.Secrets; + +[SutProviderCustomize] +[SecretCustomize] +public class CreateSecretCommandTests +{ + [Theory] + [BitAutoData] + public async Task CreateAsync_CallsCreate(Secret data, + SutProvider sutProvider) + { + await sutProvider.Sut.CreateAsync(data); + + await sutProvider.GetDependency().Received(1) + .CreateAsync(data); + } +} + diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Secrets/DeleteSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Secrets/DeleteSecretCommandTests.cs new file mode 100644 index 000000000..1561f0058 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Secrets/DeleteSecretCommandTests.cs @@ -0,0 +1,69 @@ +using Bit.Commercial.Core.SecretManagerFeatures.Secrets; +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretManagerFeatures.Secrets; + +[SutProviderCustomize] +public class DeleteSecretCommandTests +{ + [Theory] + [BitAutoData] + public async Task DeleteSecrets_Throws_NotFoundException(List data, + SutProvider sutProvider) + { + sutProvider.GetDependency().GetManyByIds(data).Returns(new List()); + + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.DeleteSecrets(data)); + + 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)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().SoftDeleteManyByIdAsync(default); + } + + [Theory] + [BitAutoData] + public async Task DeleteSecrets_Success(List data, + SutProvider sutProvider) + { + var secrets = new List(); + foreach (Guid id in data) + { + var secret = new Secret() + { + Id = id + }; + secrets.Add(secret); + } + + sutProvider.GetDependency().GetManyByIds(data).Returns(secrets); + + var results = await sutProvider.Sut.DeleteSecrets(data); + + await sutProvider.GetDependency().Received(1).SoftDeleteManyByIdAsync(Arg.Is(data)); + foreach (var result in results) + { + Assert.Equal("", result.Item2); + } + } +} + diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Secrets/UpdateSecretCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Secrets/UpdateSecretCommandTests.cs new file mode 100644 index 000000000..64b52ce6f --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/Secrets/UpdateSecretCommandTests.cs @@ -0,0 +1,119 @@ +using Bit.Commercial.Core.SecretManagerFeatures.Secrets; +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.Test.AutoFixture.SecretsFixture; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretManagerFeatures.Secrets; + +[SutProviderCustomize] +[SecretCustomize] +public class UpdateSecretCommandTests +{ + [Theory] + [BitAutoData] + public async Task UpdateAsync_SecretDoesNotExist_ThrowsNotFound(Secret data, SutProvider sutProvider) + { + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(data)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().UpdateAsync(default); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_CallsReplaceAsync(Secret data, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + await sutProvider.Sut.UpdateAsync(data); + + await sutProvider.GetDependency().Received(1) + .UpdateAsync(data); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyOrganizationId(Secret existingSecret, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingSecret.Id).Returns(existingSecret); + + var updatedOrgId = Guid.NewGuid(); + var secretUpdate = new Secret() + { + OrganizationId = updatedOrgId, + Id = existingSecret.Id, + Key = existingSecret.Key, + }; + + var result = await sutProvider.Sut.UpdateAsync(secretUpdate); + + Assert.Equal(existingSecret.OrganizationId, result.OrganizationId); + Assert.NotEqual(existingSecret.OrganizationId, updatedOrgId); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyCreationDate(Secret existingSecret, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingSecret.Id).Returns(existingSecret); + + var updatedCreationDate = DateTime.UtcNow; + var secretUpdate = new Secret() + { + CreationDate = updatedCreationDate, + Id = existingSecret.Id, + Key = existingSecret.Key, + }; + + var result = await sutProvider.Sut.UpdateAsync(secretUpdate); + + Assert.Equal(existingSecret.CreationDate, result.CreationDate); + Assert.NotEqual(existingSecret.CreationDate, updatedCreationDate); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyDeletionDate(Secret existingSecret, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingSecret.Id).Returns(existingSecret); + + var updatedDeletionDate = DateTime.UtcNow; + var secretUpdate = new Secret() + { + DeletedDate = updatedDeletionDate, + Id = existingSecret.Id, + Key = existingSecret.Key, + }; + + var result = await sutProvider.Sut.UpdateAsync(secretUpdate); + + Assert.Equal(existingSecret.DeletedDate, result.DeletedDate); + Assert.NotEqual(existingSecret.DeletedDate, updatedDeletionDate); + } + + + [Theory] + [BitAutoData] + public async Task UpdateAsync_RevisionDateIsUpdatedToUtcNow(Secret existingSecret, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingSecret.Id).Returns(existingSecret); + + var updatedRevisionDate = DateTime.UtcNow.AddDays(10); + var secretUpdate = new Secret() + { + RevisionDate = updatedRevisionDate, + Id = existingSecret.Id, + Key = existingSecret.Key, + }; + + var result = await sutProvider.Sut.UpdateAsync(secretUpdate); + + Assert.NotEqual(existingSecret.RevisionDate, result.RevisionDate); + AssertHelper.AssertRecent(result.RevisionDate); + } +} + diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/ServiceAccounts/CreateServiceAccountCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/ServiceAccounts/CreateServiceAccountCommandTests.cs new file mode 100644 index 000000000..209cea2cc --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/ServiceAccounts/CreateServiceAccountCommandTests.cs @@ -0,0 +1,25 @@ +using Bit.Commercial.Core.SecretManagerFeatures.ServiceAccounts; +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretManagerFeatures.ServiceAccounts; + +[SutProviderCustomize] +public class CreateServiceAccountCommandTests +{ + [Theory] + [BitAutoData] + public async Task CreateAsync_CallsCreate(ServiceAccount data, + SutProvider sutProvider) + { + await sutProvider.Sut.CreateAsync(data); + + await sutProvider.GetDependency().Received(1) + .CreateAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } +} diff --git a/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/ServiceAccounts/UpdateServiceAccountCommandTests.cs b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/ServiceAccounts/UpdateServiceAccountCommandTests.cs new file mode 100644 index 000000000..3a3fd6c66 --- /dev/null +++ b/bitwarden_license/test/Commercial.Core.Test/SecretManagerFeatures/ServiceAccounts/UpdateServiceAccountCommandTests.cs @@ -0,0 +1,95 @@ +using Bit.Commercial.Core.SecretManagerFeatures.ServiceAccounts; +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Commercial.Core.Test.SecretManagerFeatures.ServiceAccounts; + +[SutProviderCustomize] +public class UpdateServiceAccountCommandTests +{ + [Theory] + [BitAutoData] + public async Task UpdateAsync_ServiceAccountDoesNotExist_ThrowsNotFound(ServiceAccount data, SutProvider sutProvider) + { + var exception = await Assert.ThrowsAsync(() => sutProvider.Sut.UpdateAsync(data)); + + await sutProvider.GetDependency().DidNotReceiveWithAnyArgs().ReplaceAsync(default); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_CallsReplaceAsync(ServiceAccount data, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(data.Id).Returns(data); + await sutProvider.Sut.UpdateAsync(data); + + await sutProvider.GetDependency().Received(1) + .ReplaceAsync(Arg.Is(AssertHelper.AssertPropertyEqual(data))); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyOrganizationId(ServiceAccount existingServiceAccount, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingServiceAccount.Id).Returns(existingServiceAccount); + + var updatedOrgId = Guid.NewGuid(); + var serviceAccountUpdate = new ServiceAccount() + { + OrganizationId = updatedOrgId, + Id = existingServiceAccount.Id, + Name = existingServiceAccount.Name, + }; + + var result = await sutProvider.Sut.UpdateAsync(serviceAccountUpdate); + + Assert.Equal(existingServiceAccount.OrganizationId, result.OrganizationId); + Assert.NotEqual(existingServiceAccount.OrganizationId, updatedOrgId); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_DoesNotModifyCreationDate(ServiceAccount existingServiceAccount, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingServiceAccount.Id).Returns(existingServiceAccount); + + var updatedCreationDate = DateTime.UtcNow; + var serviceAccountUpdate = new ServiceAccount() + { + CreationDate = updatedCreationDate, + Id = existingServiceAccount.Id, + Name = existingServiceAccount.Name, + }; + + var result = await sutProvider.Sut.UpdateAsync(serviceAccountUpdate); + + Assert.Equal(existingServiceAccount.CreationDate, result.CreationDate); + Assert.NotEqual(existingServiceAccount.CreationDate, updatedCreationDate); + } + + [Theory] + [BitAutoData] + public async Task UpdateAsync_RevisionDateIsUpdatedToUtcNow(ServiceAccount existingServiceAccount, SutProvider sutProvider) + { + sutProvider.GetDependency().GetByIdAsync(existingServiceAccount.Id).Returns(existingServiceAccount); + + var updatedRevisionDate = DateTime.UtcNow.AddDays(10); + var serviceAccountUpdate = new ServiceAccount() + { + RevisionDate = updatedRevisionDate, + Id = existingServiceAccount.Id, + Name = existingServiceAccount.Name, + }; + + var result = await sutProvider.Sut.UpdateAsync(serviceAccountUpdate); + + Assert.NotEqual(existingServiceAccount.RevisionDate, result.RevisionDate); + AssertHelper.AssertRecent(result.RevisionDate); + } +} diff --git a/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json b/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json index d613943f1..e908ea60a 100644 --- a/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json +++ b/bitwarden_license/test/Scim.IntegrationTest/packages.lock.json @@ -771,6 +771,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3438,6 +3447,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/bitwarden_license/test/Scim.Test/packages.lock.json b/bitwarden_license/test/Scim.Test/packages.lock.json index 4e93545fd..bbdeab8de 100644 --- a/bitwarden_license/test/Scim.Test/packages.lock.json +++ b/bitwarden_license/test/Scim.Test/packages.lock.json @@ -743,6 +743,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3275,6 +3284,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/docker-unified/Dockerfile b/docker-unified/Dockerfile index 9d15f7eea..ce9bd5aa8 100644 --- a/docker-unified/Dockerfile +++ b/docker-unified/Dockerfile @@ -75,6 +75,7 @@ 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 @@ -129,6 +130,7 @@ 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 diff --git a/src/Admin/Models/OrganizationEditModel.cs b/src/Admin/Models/OrganizationEditModel.cs index ed172d6fd..2eeafb77a 100644 --- a/src/Admin/Models/OrganizationEditModel.cs +++ b/src/Admin/Models/OrganizationEditModel.cs @@ -39,6 +39,7 @@ public class OrganizationEditModel : OrganizationViewModel UseTotp = org.UseTotp; Use2fa = org.Use2fa; UseApi = org.UseApi; + UseSecretsManager = org.UseSecretsManager; UseResetPassword = org.UseResetPassword; SelfHost = org.SelfHost; UsersGetPremium = org.UsersGetPremium; @@ -98,6 +99,8 @@ public class OrganizationEditModel : OrganizationViewModel public bool UseResetPassword { get; set; } [Display(Name = "SCIM")] public bool UseScim { get; set; } + [Display(Name = "Secrets Manager")] + public bool UseSecretsManager { get; set; } [Display(Name = "Self Host")] public bool SelfHost { get; set; } [Display(Name = "Users Get Premium")] @@ -139,6 +142,7 @@ public class OrganizationEditModel : OrganizationViewModel existingOrganization.UseTotp = UseTotp; existingOrganization.Use2fa = Use2fa; existingOrganization.UseApi = UseApi; + existingOrganization.UseSecretsManager = UseSecretsManager; existingOrganization.UseResetPassword = UseResetPassword; existingOrganization.SelfHost = SelfHost; existingOrganization.UsersGetPremium = UsersGetPremium; diff --git a/src/Admin/Startup.cs b/src/Admin/Startup.cs index f3814fffa..55dfa99b3 100644 --- a/src/Admin/Startup.cs +++ b/src/Admin/Startup.cs @@ -83,9 +83,9 @@ public class Startup services.AddDefaultServices(globalSettings); #if OSS - services.AddOosServices(); + services.AddOosServices(); #else - services.AddCommCoreServices(); + services.AddCommercialCoreServices(); #endif // Mvc diff --git a/src/Admin/Views/Organizations/Edit.cshtml b/src/Admin/Views/Organizations/Edit.cshtml index 7c5e1dce2..b77be0d72 100644 --- a/src/Admin/Views/Organizations/Edit.cshtml +++ b/src/Admin/Views/Organizations/Edit.cshtml @@ -191,62 +191,78 @@

Features

-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - +
+
+

General

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+

Password Manager

+
+ + +
+
+ + +
+
+
+

Secrets Manager

+
+ + +
+
+

Licensing

diff --git a/src/Admin/packages.lock.json b/src/Admin/packages.lock.json index 69a9d55c3..73f27f51d 100644 --- a/src/Admin/packages.lock.json +++ b/src/Admin/packages.lock.json @@ -815,6 +815,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3338,6 +3347,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj index 901036fcc..613dba05a 100644 --- a/src/Api/Api.csproj +++ b/src/Api/Api.csproj @@ -24,6 +24,7 @@ + diff --git a/src/Api/Controllers/ProjectsController.cs b/src/Api/Controllers/ProjectsController.cs new file mode 100644 index 000000000..8b706d42d --- /dev/null +++ b/src/Api/Controllers/ProjectsController.cs @@ -0,0 +1,77 @@ +using Bit.Api.Models.Response; +using Bit.Api.SecretManagerFeatures.Models.Request; +using Bit.Api.SecretManagerFeatures.Models.Response; +using Bit.Api.Utilities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.Projects.Interfaces; +using Bit.Core.Services; +using Microsoft.AspNetCore.Mvc; + +namespace Bit.Api.Controllers; + +[SecretsManager] +public class ProjectsController : Controller +{ + private readonly IUserService _userService; + private readonly IProjectRepository _projectRepository; + private readonly ICreateProjectCommand _createProjectCommand; + private readonly IUpdateProjectCommand _updateProjectCommand; + private readonly IDeleteProjectCommand _deleteProjectCommand; + + public ProjectsController( + IUserService userService, + IProjectRepository projectRepository, + ICreateProjectCommand createProjectCommand, + IUpdateProjectCommand updateProjectCommand, + IDeleteProjectCommand deleteProjectCommand) + { + _userService = userService; + _projectRepository = projectRepository; + _createProjectCommand = createProjectCommand; + _updateProjectCommand = updateProjectCommand; + _deleteProjectCommand = deleteProjectCommand; + } + + [HttpPost("organizations/{organizationId}/projects")] + public async Task CreateAsync([FromRoute] Guid organizationId, [FromBody] ProjectCreateRequestModel createRequest) + { + var result = await _createProjectCommand.CreateAsync(createRequest.ToProject(organizationId)); + return new ProjectResponseModel(result); + } + + [HttpPut("projects/{id}")] + public async Task UpdateProjectAsync([FromRoute] Guid id, [FromBody] ProjectUpdateRequestModel updateRequest) + { + var result = await _updateProjectCommand.UpdateAsync(updateRequest.ToProject(id)); + return new ProjectResponseModel(result); + } + + [HttpGet("organizations/{organizationId}/projects")] + public async Task> GetProjectsByOrganizationAsync([FromRoute] Guid organizationId) + { + var userId = _userService.GetProperUserId(User).Value; + var projects = await _projectRepository.GetManyByOrganizationIdAsync(organizationId, userId); + var responses = projects.Select(project => new ProjectResponseModel(project)); + return new ListResponseModel(responses); + } + + [HttpGet("projects/{id}")] + public async Task GetProjectAsync([FromRoute] Guid id) + { + var project = await _projectRepository.GetByIdAsync(id); + if (project == null) + { + throw new NotFoundException(); + } + return new ProjectResponseModel(project); + } + + [HttpPost("projects/delete")] + public async Task> BulkDeleteProjectsAsync([FromBody] List ids) + { + var results = await _deleteProjectCommand.DeleteProjects(ids); + var responses = results.Select(r => new BulkDeleteResponseModel(r.Item1.Id, r.Item2)); + return new ListResponseModel(responses); + } +} diff --git a/src/Api/Controllers/SecretsController.cs b/src/Api/Controllers/SecretsController.cs new file mode 100644 index 000000000..95a694bed --- /dev/null +++ b/src/Api/Controllers/SecretsController.cs @@ -0,0 +1,80 @@ +using Bit.Api.Models.Response; +using Bit.Api.SecretManagerFeatures.Models.Request; +using Bit.Api.SecretManagerFeatures.Models.Response; +using Bit.Api.Utilities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.Secrets.Interfaces; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Bit.Api.Controllers; + +[SecretsManager] +[Authorize("secrets")] +public class SecretsController : Controller +{ + private readonly ISecretRepository _secretRepository; + private readonly IProjectRepository _projectRepository; + private readonly ICreateSecretCommand _createSecretCommand; + private readonly IUpdateSecretCommand _updateSecretCommand; + private readonly IDeleteSecretCommand _deleteSecretCommand; + + public SecretsController(ISecretRepository secretRepository, IProjectRepository projectRepository, ICreateSecretCommand createSecretCommand, IUpdateSecretCommand updateSecretCommand, IDeleteSecretCommand deleteSecretCommand) + { + _secretRepository = secretRepository; + _projectRepository = projectRepository; + _createSecretCommand = createSecretCommand; + _updateSecretCommand = updateSecretCommand; + _deleteSecretCommand = deleteSecretCommand; + } + + [HttpGet("organizations/{organizationId}/secrets")] + public async Task GetSecretsByOrganizationAsync([FromRoute] Guid organizationId) + { + var secrets = await _secretRepository.GetManyByOrganizationIdAsync(organizationId); + return new SecretWithProjectsListResponseModel(secrets); + } + + [HttpGet("secrets/{id}")] + public async Task GetSecretAsync([FromRoute] Guid id) + { + var secret = await _secretRepository.GetByIdAsync(id); + if (secret == null) + { + throw new NotFoundException(); + } + return new SecretResponseModel(secret); + } + + [HttpGet("projects/{projectId}/secrets")] + public async Task GetSecretsByProjectAsync([FromRoute] Guid projectId) + { + var secrets = await _secretRepository.GetManyByProjectIdAsync(projectId); + var responses = secrets.Select(s => new SecretResponseModel(s)); + return new SecretWithProjectsListResponseModel(secrets); + } + + [HttpPost("organizations/{organizationId}/secrets")] + public async Task CreateSecretAsync([FromRoute] Guid organizationId, [FromBody] SecretCreateRequestModel createRequest) + { + var result = await _createSecretCommand.CreateAsync(createRequest.ToSecret(organizationId)); + return new SecretResponseModel(result); + } + + [HttpPut("secrets/{id}")] + public async Task UpdateSecretAsync([FromRoute] Guid id, [FromBody] SecretUpdateRequestModel updateRequest) + { + var result = await _updateSecretCommand.UpdateAsync(updateRequest.ToSecret(id)); + return new SecretResponseModel(result); + } + + // TODO Once permissions are setup for Secrets Manager need to enforce them on delete. + [HttpPost("secrets/delete")] + public async Task> BulkDeleteAsync([FromBody] List ids) + { + var results = await _deleteSecretCommand.DeleteSecrets(ids); + var responses = results.Select(r => new BulkDeleteResponseModel(r.Item1.Id, r.Item2)); + return new ListResponseModel(responses); + } +} diff --git a/src/Api/Controllers/ServiceAccountsController.cs b/src/Api/Controllers/ServiceAccountsController.cs new file mode 100644 index 000000000..353d9bba7 --- /dev/null +++ b/src/Api/Controllers/ServiceAccountsController.cs @@ -0,0 +1,72 @@ +using Bit.Api.Models.Response; +using Bit.Api.Models.Response.SecretsManager; +using Bit.Api.SecretManagerFeatures.Models.Request; +using Bit.Api.SecretManagerFeatures.Models.Response; +using Bit.Api.Utilities; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.AccessTokens.Interfaces; +using Bit.Core.SecretManagerFeatures.ServiceAccounts.Interfaces; +using Microsoft.AspNetCore.Mvc; + +namespace Bit.Api.Controllers; + +[SecretsManager] +[Route("service-accounts")] +public class ServiceAccountsController : Controller +{ + private readonly IServiceAccountRepository _serviceAccountRepository; + private readonly IApiKeyRepository _apiKeyRepository; + private readonly ICreateServiceAccountCommand _createServiceAccountCommand; + private readonly ICreateAccessTokenCommand _createAccessTokenCommand; + private readonly IUpdateServiceAccountCommand _updateServiceAccountCommand; + + public ServiceAccountsController( + IServiceAccountRepository serviceAccountRepository, + ICreateAccessTokenCommand createAccessTokenCommand, + IApiKeyRepository apiKeyRepository, ICreateServiceAccountCommand createServiceAccountCommand, + IUpdateServiceAccountCommand updateServiceAccountCommand) + { + _serviceAccountRepository = serviceAccountRepository; + _apiKeyRepository = apiKeyRepository; + _createServiceAccountCommand = createServiceAccountCommand; + _updateServiceAccountCommand = updateServiceAccountCommand; + _createAccessTokenCommand = createAccessTokenCommand; + } + + [HttpGet("/organizations/{organizationId}/service-accounts")] + public async Task> GetServiceAccountsByOrganizationAsync([FromRoute] Guid organizationId) + { + var serviceAccounts = await _serviceAccountRepository.GetManyByOrganizationIdAsync(organizationId); + var responses = serviceAccounts.Select(serviceAccount => new ServiceAccountResponseModel(serviceAccount)); + return new ListResponseModel(responses); + } + + [HttpPost("/organizations/{organizationId}/service-accounts")] + public async Task CreateServiceAccountAsync([FromRoute] Guid organizationId, [FromBody] ServiceAccountCreateRequestModel createRequest) + { + var result = await _createServiceAccountCommand.CreateAsync(createRequest.ToServiceAccount(organizationId)); + return new ServiceAccountResponseModel(result); + } + + [HttpPut("{id}")] + public async Task UpdateServiceAccountAsync([FromRoute] Guid id, [FromBody] ServiceAccountUpdateRequestModel updateRequest) + { + var result = await _updateServiceAccountCommand.UpdateAsync(updateRequest.ToServiceAccount(id)); + return new ServiceAccountResponseModel(result); + } + + [HttpGet("{id}/access-tokens")] + public async Task> GetAccessTokens([FromRoute] Guid id) + { + var accessTokens = await _apiKeyRepository.GetManyByServiceAccountIdAsync(id); + var responses = accessTokens.Select(token => new AccessTokenResponseModel(token)); + return new ListResponseModel(responses); + } + + [HttpPost("{id}/access-tokens")] + public async Task CreateAccessTokenAsync([FromRoute] Guid id, [FromBody] AccessTokenCreateRequestModel request) + { + var result = await _createAccessTokenCommand.CreateAsync(request.ToApiKey(id)); + return new AccessTokenCreationResponseModel(result); + } +} diff --git a/src/Api/Models/Response/Organizations/OrganizationResponseModel.cs b/src/Api/Models/Response/Organizations/OrganizationResponseModel.cs index 3e12e951c..4df4a4dce 100644 --- a/src/Api/Models/Response/Organizations/OrganizationResponseModel.cs +++ b/src/Api/Models/Response/Organizations/OrganizationResponseModel.cs @@ -43,6 +43,7 @@ public class OrganizationResponseModel : ResponseModel Use2fa = organization.Use2fa; UseApi = organization.UseApi; UseResetPassword = organization.UseResetPassword; + UseSecretsManager = organization.UseSecretsManager; UsersGetPremium = organization.UsersGetPremium; UseCustomPermissions = organization.UseCustomPermissions; SelfHost = organization.SelfHost; @@ -75,6 +76,7 @@ public class OrganizationResponseModel : ResponseModel public bool UseTotp { get; set; } public bool Use2fa { get; set; } public bool UseApi { get; set; } + public bool UseSecretsManager { get; set; } public bool UseResetPassword { get; set; } public bool UsersGetPremium { get; set; } public bool UseCustomPermissions { get; set; } diff --git a/src/Api/Models/Response/ProfileOrganizationResponseModel.cs b/src/Api/Models/Response/ProfileOrganizationResponseModel.cs index 83ae38968..d2b98099e 100644 --- a/src/Api/Models/Response/ProfileOrganizationResponseModel.cs +++ b/src/Api/Models/Response/ProfileOrganizationResponseModel.cs @@ -25,6 +25,7 @@ public class ProfileOrganizationResponseModel : ResponseModel Use2fa = organization.Use2fa; UseApi = organization.UseApi; UseResetPassword = organization.UseResetPassword; + UseSecretsManager = organization.UseSecretsManager; UsersGetPremium = organization.UsersGetPremium; UseCustomPermissions = organization.UseCustomPermissions; SelfHost = organization.SelfHost; @@ -73,6 +74,7 @@ public class ProfileOrganizationResponseModel : ResponseModel public bool Use2fa { get; set; } public bool UseApi { get; set; } public bool UseResetPassword { get; set; } + public bool UseSecretsManager { get; set; } public bool UsersGetPremium { get; set; } public bool UseCustomPermissions { get; set; } public bool SelfHost { get; set; } diff --git a/src/Api/Models/Response/SecretsManager/AccessTokenResponseModel.cs b/src/Api/Models/Response/SecretsManager/AccessTokenResponseModel.cs new file mode 100644 index 000000000..235678509 --- /dev/null +++ b/src/Api/Models/Response/SecretsManager/AccessTokenResponseModel.cs @@ -0,0 +1,27 @@ +using Bit.Core.Entities; +using Bit.Core.Models.Api; + +namespace Bit.Api.Models.Response.SecretsManager; + +public class AccessTokenResponseModel : ResponseModel +{ + public AccessTokenResponseModel(ApiKey apiKey, string obj = "accessToken") + : base(obj) + { + Id = apiKey.Id; + Name = apiKey.Name; + Scopes = apiKey.GetScopes(); + + ExpireAt = apiKey.ExpireAt; + CreationDate = apiKey.CreationDate; + RevisionDate = apiKey.RevisionDate; + } + + public Guid Id { get; } + public string Name { get; } + public ICollection Scopes { get; } + + public DateTime? ExpireAt { get; } + public DateTime CreationDate { get; } + public DateTime RevisionDate { get; } +} diff --git a/src/Api/SecretManagerFeatures/Models/Request/AccessTokenCreateRequestModel.cs b/src/Api/SecretManagerFeatures/Models/Request/AccessTokenCreateRequestModel.cs new file mode 100644 index 000000000..8e71b2eab --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Request/AccessTokenCreateRequestModel.cs @@ -0,0 +1,37 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; +using Bit.Core.Utilities; + +namespace Bit.Api.SecretManagerFeatures.Models.Request; + +public class AccessTokenCreateRequestModel +{ + [Required] + [EncryptedString] + [EncryptedStringLength(200)] + public string Name { get; set; } + + [Required] + [EncryptedString] + [EncryptedStringLength(4000)] + public string EncryptedPayload { get; set; } + + [Required] + [EncryptedString] + public string Key { get; set; } + + public DateTime? ExpireAt { get; set; } + + public ApiKey ToApiKey(Guid serviceAccountId) + { + return new ApiKey() + { + ServiceAccountId = serviceAccountId, + Name = Name, + Key = Key, + ExpireAt = ExpireAt, + Scope = "[\"api.secrets\"]", + EncryptedPayload = EncryptedPayload, + }; + } +} diff --git a/src/Api/SecretManagerFeatures/Models/Request/ProjectCreateRequestModel.cs b/src/Api/SecretManagerFeatures/Models/Request/ProjectCreateRequestModel.cs new file mode 100644 index 000000000..f00e0d648 --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Request/ProjectCreateRequestModel.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; +using Bit.Core.Utilities; + +namespace Bit.Api.SecretManagerFeatures.Models.Request; + +public class ProjectCreateRequestModel +{ + [Required] + [EncryptedString] + public string Name { get; set; } + + public Project ToProject(Guid organizationId) + { + return new Project() + { + OrganizationId = organizationId, + Name = Name, + }; + } +} diff --git a/src/Api/SecretManagerFeatures/Models/Request/ProjectUpdateRequestModel.cs b/src/Api/SecretManagerFeatures/Models/Request/ProjectUpdateRequestModel.cs new file mode 100644 index 000000000..e0ef727c7 --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Request/ProjectUpdateRequestModel.cs @@ -0,0 +1,22 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; +using Bit.Core.Utilities; + +namespace Bit.Api.SecretManagerFeatures.Models.Request; + +public class ProjectUpdateRequestModel +{ + [Required] + [EncryptedString] + public string Name { get; set; } + + public Project ToProject(Guid id) + { + return new Project() + { + Id = id, + Name = Name, + }; + } +} + diff --git a/src/Api/SecretManagerFeatures/Models/Request/SecretCreateRequestModel.cs b/src/Api/SecretManagerFeatures/Models/Request/SecretCreateRequestModel.cs new file mode 100644 index 000000000..94dac2c21 --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Request/SecretCreateRequestModel.cs @@ -0,0 +1,35 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; +using Bit.Core.Utilities; + +namespace Bit.Api.SecretManagerFeatures.Models.Request; + +public class SecretCreateRequestModel +{ + [Required] + [EncryptedString] + public string Key { get; set; } + + [Required] + [EncryptedString] + public string Value { get; set; } + + [Required] + [EncryptedString] + public string Note { get; set; } + + public Guid[] ProjectIds { get; set; } + + public Secret ToSecret(Guid organizationId) + { + return new Secret() + { + OrganizationId = organizationId, + Key = Key, + Value = Value, + Note = Note, + DeletedDate = null, + Projects = ProjectIds != null && ProjectIds.Any() ? ProjectIds.Select(x => new Project() { Id = x }).ToList() : null, + }; + } +} diff --git a/src/Api/SecretManagerFeatures/Models/Request/SecretUpdateRequestModel.cs b/src/Api/SecretManagerFeatures/Models/Request/SecretUpdateRequestModel.cs new file mode 100644 index 000000000..5ef585f2a --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Request/SecretUpdateRequestModel.cs @@ -0,0 +1,35 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; +using Bit.Core.Utilities; + +namespace Bit.Api.SecretManagerFeatures.Models.Request; + +public class SecretUpdateRequestModel +{ + [Required] + [EncryptedString] + public string Key { get; set; } + + [Required] + [EncryptedString] + public string Value { get; set; } + + [Required] + [EncryptedString] + public string Note { get; set; } + + public Guid[] ProjectIds { get; set; } + + public Secret ToSecret(Guid id) + { + return new Secret() + { + Id = id, + Key = Key, + Value = Value, + Note = Note, + DeletedDate = null, + Projects = ProjectIds != null && ProjectIds.Any() ? ProjectIds.Select(x => new Project() { Id = x }).ToList() : null, + }; + } +} diff --git a/src/Api/SecretManagerFeatures/Models/Request/SerivceAccountUpdateRequestModel.cs b/src/Api/SecretManagerFeatures/Models/Request/SerivceAccountUpdateRequestModel.cs new file mode 100644 index 000000000..a3fff7062 --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Request/SerivceAccountUpdateRequestModel.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; +using Bit.Core.Utilities; + +namespace Bit.Api.SecretManagerFeatures.Models.Request; + +public class ServiceAccountUpdateRequestModel +{ + [Required] + [EncryptedString] + public string Name { get; set; } + + public ServiceAccount ToServiceAccount(Guid id) + { + return new ServiceAccount() + { + Id = id, + Name = Name, + }; + } +} diff --git a/src/Api/SecretManagerFeatures/Models/Request/ServiceAccountCreateRequestModel.cs b/src/Api/SecretManagerFeatures/Models/Request/ServiceAccountCreateRequestModel.cs new file mode 100644 index 000000000..9b64def78 --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Request/ServiceAccountCreateRequestModel.cs @@ -0,0 +1,21 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.Entities; +using Bit.Core.Utilities; + +namespace Bit.Api.SecretManagerFeatures.Models.Request; + +public class ServiceAccountCreateRequestModel +{ + [Required] + [EncryptedString] + public string Name { get; set; } + + public ServiceAccount ToServiceAccount(Guid organizationId) + { + return new ServiceAccount() + { + OrganizationId = organizationId, + Name = Name, + }; + } +} diff --git a/src/Api/SecretManagerFeatures/Models/Response/AccessTokenCreationResponseModel.cs b/src/Api/SecretManagerFeatures/Models/Response/AccessTokenCreationResponseModel.cs new file mode 100644 index 000000000..bead88317 --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Response/AccessTokenCreationResponseModel.cs @@ -0,0 +1,25 @@ +#nullable enable +using Bit.Core.Entities; +using Bit.Core.Models.Api; + +namespace Bit.Api.SecretManagerFeatures.Models.Response; + +public class AccessTokenCreationResponseModel : ResponseModel +{ + public AccessTokenCreationResponseModel(ApiKey apiKey, string obj = "accessTokenCreation") : base(obj) + { + Id = apiKey.Id; + Name = apiKey.Name; + ClientSecret = apiKey.ClientSecret; + ExpireAt = apiKey.ExpireAt; + CreationDate = apiKey.CreationDate; + RevisionDate = apiKey.RevisionDate; + } + + public Guid Id { get; } + public string Name { get; } + public string ClientSecret { get; } + public DateTime? ExpireAt { get; } + public DateTime CreationDate { get; } + public DateTime RevisionDate { get; } +} diff --git a/src/Api/SecretManagerFeatures/Models/Response/BulkDeleteResponseModel.cs b/src/Api/SecretManagerFeatures/Models/Response/BulkDeleteResponseModel.cs new file mode 100644 index 000000000..0fa4a471a --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Response/BulkDeleteResponseModel.cs @@ -0,0 +1,25 @@ +#nullable enable +using Bit.Core.Models.Api; + +namespace Bit.Api.SecretManagerFeatures.Models.Response; + +public class BulkDeleteResponseModel : ResponseModel +{ + public BulkDeleteResponseModel(Guid id, string error, string obj = "BulkDeleteResponseModel") : base(obj) + { + Id = id; + + if (string.IsNullOrWhiteSpace(error)) + { + Error = null; + } + else + { + Error = error; + } + } + + public Guid Id { get; set; } + + public string? Error { get; set; } +} diff --git a/src/Api/SecretManagerFeatures/Models/Response/ProjectResponseModel.cs b/src/Api/SecretManagerFeatures/Models/Response/ProjectResponseModel.cs new file mode 100644 index 000000000..a16505635 --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Response/ProjectResponseModel.cs @@ -0,0 +1,34 @@ +using Bit.Core.Entities; +using Bit.Core.Models.Api; + +namespace Bit.Api.SecretManagerFeatures.Models.Response; + +public class ProjectResponseModel : ResponseModel +{ + public ProjectResponseModel(Project project, string obj = "project") + : base(obj) + { + if (project == null) + { + throw new ArgumentNullException(nameof(project)); + } + + Id = project.Id.ToString(); + OrganizationId = project.OrganizationId.ToString(); + Name = project.Name; + CreationDate = project.CreationDate; + RevisionDate = project.RevisionDate; + } + + public string Id { get; set; } + + public string OrganizationId { get; set; } + + public string Name { get; set; } + + public DateTime CreationDate { get; set; } + + public DateTime RevisionDate { get; set; } + + public IEnumerable Secrets { get; set; } +} diff --git a/src/Api/SecretManagerFeatures/Models/Response/SecretResponseModel.cs b/src/Api/SecretManagerFeatures/Models/Response/SecretResponseModel.cs new file mode 100644 index 000000000..b2053d79a --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Response/SecretResponseModel.cs @@ -0,0 +1,53 @@ +using Bit.Core.Entities; +using Bit.Core.Models.Api; + +namespace Bit.Api.SecretManagerFeatures.Models.Response; + +public class SecretResponseModel : ResponseModel +{ + public SecretResponseModel(Secret secret, string obj = "secret") + : base(obj) + { + if (secret == null) + { + throw new ArgumentNullException(nameof(secret)); + } + + Id = secret.Id.ToString(); + OrganizationId = secret.OrganizationId.ToString(); + Key = secret.Key; + Value = secret.Value; + Note = secret.Note; + CreationDate = secret.CreationDate; + RevisionDate = secret.RevisionDate; + Projects = secret.Projects?.Select(p => new InnerProject(p)); + } + + public string Id { get; set; } + + public string OrganizationId { get; set; } + + public string Key { get; set; } + + public string Value { get; set; } + + public string Note { get; set; } + + public DateTime CreationDate { get; set; } + + public DateTime RevisionDate { get; set; } + + public IEnumerable Projects { get; set; } + + public class InnerProject + { + public InnerProject(Project project) + { + Id = project.Id; + Name = project.Name; + } + + public Guid Id { get; set; } + public string Name { get; set; } + } +} diff --git a/src/Api/SecretManagerFeatures/Models/Response/SecretWithProjectsListResponseModel.cs b/src/Api/SecretManagerFeatures/Models/Response/SecretWithProjectsListResponseModel.cs new file mode 100644 index 000000000..bd17933f8 --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Response/SecretWithProjectsListResponseModel.cs @@ -0,0 +1,55 @@ +using Bit.Core.Entities; +using Bit.Core.Models.Api; + +namespace Bit.Api.SecretManagerFeatures.Models.Response; + +public class SecretWithProjectsListResponseModel : ResponseModel +{ + public SecretWithProjectsListResponseModel(IEnumerable secrets, string obj = "SecretsWithProjectsList") : base(obj) + { + Secrets = secrets.Select(s => new InnerSecret(s)); + Projects = secrets.SelectMany(s => s.Projects).DistinctBy(p => p.Id).Select(p => new InnerProject(p)); + } + + public IEnumerable Secrets { get; set; } + public IEnumerable Projects { get; set; } + + public class InnerProject + { + public InnerProject(Project project) + { + Id = project.Id; + Name = project.Name; + } + + public Guid Id { get; set; } + public string Name { get; set; } + } + + public class InnerSecret + { + public InnerSecret(Secret secret) + { + Id = secret.Id.ToString(); + OrganizationId = secret.OrganizationId.ToString(); + Key = secret.Key; + CreationDate = secret.CreationDate; + RevisionDate = secret.RevisionDate; + Projects = secret.Projects?.Select(p => new InnerProject(p)); + } + + public string Id { get; set; } + + public string OrganizationId { get; set; } + + public string Key { get; set; } + + public DateTime CreationDate { get; set; } + + public DateTime RevisionDate { get; set; } + + public IEnumerable Projects { get; set; } + } +} + + diff --git a/src/Api/SecretManagerFeatures/Models/Response/ServiceAccountResponseModel.cs b/src/Api/SecretManagerFeatures/Models/Response/ServiceAccountResponseModel.cs new file mode 100644 index 000000000..f525d94be --- /dev/null +++ b/src/Api/SecretManagerFeatures/Models/Response/ServiceAccountResponseModel.cs @@ -0,0 +1,33 @@ +using Bit.Core.Entities; +using Bit.Core.Models.Api; + +namespace Bit.Api.SecretManagerFeatures.Models.Response; + +public class ServiceAccountResponseModel : ResponseModel +{ + public ServiceAccountResponseModel(ServiceAccount serviceAccount, string obj = "serviceAccount") + : base(obj) + { + if (serviceAccount == null) + { + throw new ArgumentNullException(nameof(serviceAccount)); + } + + Id = serviceAccount.Id.ToString(); + OrganizationId = serviceAccount.OrganizationId.ToString(); + Name = serviceAccount.Name; + CreationDate = serviceAccount.CreationDate; + RevisionDate = serviceAccount.RevisionDate; + } + + public string Id { get; set; } + + public string OrganizationId { get; set; } + + public string Name { get; set; } + + public DateTime CreationDate { get; set; } + + public DateTime RevisionDate { get; set; } +} + diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs index 86d130e1e..9475d2f5e 100644 --- a/src/Api/Startup.cs +++ b/src/Api/Startup.cs @@ -8,6 +8,7 @@ using Stripe; using Bit.Core.Utilities; using IdentityModel; using System.Globalization; +using Bit.Core.IdentityServer; using Microsoft.IdentityModel.Logging; using Microsoft.OpenApi.Models; using Bit.SharedWeb.Utilities; @@ -15,6 +16,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; #if !OSS using Bit.Commercial.Core.Utilities; +using Bit.Commercial.Infrastructure.EntityFramework; #endif namespace Bit.Api; @@ -84,34 +86,42 @@ public class Startup { policy.RequireAuthenticatedUser(); policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application", "external"); - policy.RequireClaim(JwtClaimTypes.Scope, "api"); + policy.RequireClaim(JwtClaimTypes.Scope, ApiScopes.Api); }); config.AddPolicy("Web", policy => { policy.RequireAuthenticatedUser(); policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application", "external"); - policy.RequireClaim(JwtClaimTypes.Scope, "api"); + policy.RequireClaim(JwtClaimTypes.Scope, ApiScopes.Api); policy.RequireClaim(JwtClaimTypes.ClientId, "web"); }); config.AddPolicy("Push", policy => { policy.RequireAuthenticatedUser(); - policy.RequireClaim(JwtClaimTypes.Scope, "api.push"); + policy.RequireClaim(JwtClaimTypes.Scope, ApiScopes.ApiPush); }); config.AddPolicy("Licensing", policy => { policy.RequireAuthenticatedUser(); - policy.RequireClaim(JwtClaimTypes.Scope, "api.licensing"); + policy.RequireClaim(JwtClaimTypes.Scope, ApiScopes.ApiLicensing); }); config.AddPolicy("Organization", policy => { policy.RequireAuthenticatedUser(); - policy.RequireClaim(JwtClaimTypes.Scope, "api.organization"); + policy.RequireClaim(JwtClaimTypes.Scope, ApiScopes.ApiOrganization); }); config.AddPolicy("Installation", policy => { policy.RequireAuthenticatedUser(); - policy.RequireClaim(JwtClaimTypes.Scope, "api.installation"); + policy.RequireClaim(JwtClaimTypes.Scope, ApiScopes.ApiInstallation); + }); + config.AddPolicy("Secrets", policy => + { + policy.RequireAuthenticatedUser(); + policy.RequireAssertion(ctx => ctx.User.HasClaim(c => + c.Type == JwtClaimTypes.Scope && + (c.Value.Contains(ApiScopes.Api) || c.Value.Contains(ApiScopes.ApiSecrets)) + )); }); }); @@ -125,7 +135,9 @@ public class Startup #if OSS services.AddOosServices(); #else - services.AddCommCoreServices(); + services.AddCommercialCoreServices(); + services.AddCommercialSecretsManagerServices(); + services.AddCommercialEFRepositories(); #endif // MVC diff --git a/src/Api/Utilities/SecretsManagerAttribute.cs b/src/Api/Utilities/SecretsManagerAttribute.cs index 87540c56e..13b1b0291 100644 --- a/src/Api/Utilities/SecretsManagerAttribute.cs +++ b/src/Api/Utilities/SecretsManagerAttribute.cs @@ -8,8 +8,9 @@ public class SecretsManagerAttribute : Attribute, IResourceFilter { public void OnResourceExecuting(ResourceExecutingContext context) { - var env = context.HttpContext.RequestServices.GetService(); - if (!env.IsDevelopment()) + var isDev = context.HttpContext.RequestServices.GetService().IsDevelopment(); + var isEE = Environment.GetEnvironmentVariable("EE_TESTING_ENV") != null; + if (!isDev && !isEE) { context.Result = new NotFoundResult(); } diff --git a/src/Api/Utilities/ServiceCollectionExtensions.cs b/src/Api/Utilities/ServiceCollectionExtensions.cs index be3c98be7..cf3f89092 100644 --- a/src/Api/Utilities/ServiceCollectionExtensions.cs +++ b/src/Api/Utilities/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ -using Bit.Core.Settings; +using Bit.Core.IdentityServer; +using Bit.Core.Settings; using Microsoft.OpenApi.Models; namespace Bit.Api.Utilities; @@ -38,7 +39,7 @@ public static class ServiceCollectionExtensions TokenUrl = new Uri($"{globalSettings.BaseServiceUri.Identity}/connect/token"), Scopes = new Dictionary { - { "api.organization", "Organization APIs" }, + { ApiScopes.ApiOrganization, "Organization APIs" }, }, } }, @@ -55,7 +56,7 @@ public static class ServiceCollectionExtensions Id = "oauth2-client-credentials" }, }, - new[] { "api.organization" } + new[] { ApiScopes.ApiOrganization } } }); diff --git a/src/Api/packages.lock.json b/src/Api/packages.lock.json index 7a6883c3e..5a6009eaa 100644 --- a/src/Api/packages.lock.json +++ b/src/Api/packages.lock.json @@ -562,6 +562,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.ApiDescription.Server": { "type": "Transitive", "resolved": "3.0.0", @@ -2761,6 +2770,14 @@ "Core": "[2022.12.0, )" } }, + "commercial.infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2022.12.0, )", + "Infrastructure.EntityFramework": "[2022.12.0, )" + } + }, "core": { "type": "Project", "dependencies": { @@ -2814,6 +2831,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/src/Billing/packages.lock.json b/src/Billing/packages.lock.json index dd9a82332..2ac70a59a 100644 --- a/src/Billing/packages.lock.json +++ b/src/Billing/packages.lock.json @@ -796,6 +796,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3273,6 +3282,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/src/Core/Context/CurrentContext.cs b/src/Core/Context/CurrentContext.cs index 6e9fa2971..5a74b35c9 100644 --- a/src/Core/Context/CurrentContext.cs +++ b/src/Core/Context/CurrentContext.cs @@ -2,6 +2,7 @@ using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Enums.Provider; +using Bit.Core.Identity; using Bit.Core.Models.Data; using Bit.Core.Repositories; using Bit.Core.Settings; @@ -137,7 +138,7 @@ public class CurrentContext : ICurrentContext } } - DeviceIdentifier = GetClaimValue(claimsDict, "device"); + DeviceIdentifier = GetClaimValue(claimsDict, Claims.Device); Organizations = GetOrganizations(claimsDict, orgApi); @@ -149,9 +150,9 @@ public class CurrentContext : ICurrentContext private List GetOrganizations(Dictionary> claimsDict, bool orgApi) { var organizations = new List(); - if (claimsDict.ContainsKey("orgowner")) + if (claimsDict.ContainsKey(Claims.OrganizationOwner)) { - organizations.AddRange(claimsDict["orgowner"].Select(c => + organizations.AddRange(claimsDict[Claims.OrganizationOwner].Select(c => new CurrentContentOrganization { Id = new Guid(c.Value), @@ -167,9 +168,9 @@ public class CurrentContext : ICurrentContext }); } - if (claimsDict.ContainsKey("orgadmin")) + if (claimsDict.ContainsKey(Claims.OrganizationAdmin)) { - organizations.AddRange(claimsDict["orgadmin"].Select(c => + organizations.AddRange(claimsDict[Claims.OrganizationAdmin].Select(c => new CurrentContentOrganization { Id = new Guid(c.Value), @@ -177,9 +178,9 @@ public class CurrentContext : ICurrentContext })); } - if (claimsDict.ContainsKey("orguser")) + if (claimsDict.ContainsKey(Claims.OrganizationUser)) { - organizations.AddRange(claimsDict["orguser"].Select(c => + organizations.AddRange(claimsDict[Claims.OrganizationUser].Select(c => new CurrentContentOrganization { Id = new Guid(c.Value), @@ -187,9 +188,9 @@ public class CurrentContext : ICurrentContext })); } - if (claimsDict.ContainsKey("orgmanager")) + if (claimsDict.ContainsKey(Claims.OrganizationManager)) { - organizations.AddRange(claimsDict["orgmanager"].Select(c => + organizations.AddRange(claimsDict[Claims.OrganizationManager].Select(c => new CurrentContentOrganization { Id = new Guid(c.Value), @@ -197,9 +198,9 @@ public class CurrentContext : ICurrentContext })); } - if (claimsDict.ContainsKey("orgcustom")) + if (claimsDict.ContainsKey(Claims.OrganizationCustom)) { - organizations.AddRange(claimsDict["orgcustom"].Select(c => + organizations.AddRange(claimsDict[Claims.OrganizationCustom].Select(c => new CurrentContentOrganization { Id = new Guid(c.Value), @@ -214,9 +215,9 @@ public class CurrentContext : ICurrentContext private List GetProviders(Dictionary> claimsDict) { var providers = new List(); - if (claimsDict.ContainsKey("providerprovideradmin")) + if (claimsDict.ContainsKey(Claims.ProviderAdmin)) { - providers.AddRange(claimsDict["providerprovideradmin"].Select(c => + providers.AddRange(claimsDict[Claims.ProviderAdmin].Select(c => new CurrentContentProvider { Id = new Guid(c.Value), @@ -224,9 +225,9 @@ public class CurrentContext : ICurrentContext })); } - if (claimsDict.ContainsKey("providerserviceuser")) + if (claimsDict.ContainsKey(Claims.ProviderServiceUser)) { - providers.AddRange(claimsDict["providerserviceuser"].Select(c => + providers.AddRange(claimsDict[Claims.ProviderServiceUser].Select(c => new CurrentContentProvider { Id = new Guid(c.Value), diff --git a/src/Core/Entities/AccessPolicy.cs b/src/Core/Entities/AccessPolicy.cs new file mode 100644 index 000000000..b90272fbc --- /dev/null +++ b/src/Core/Entities/AccessPolicy.cs @@ -0,0 +1,76 @@ +using Bit.Core.Utilities; + +namespace Bit.Core.Entities; + +public class AccessPolicy : ITableObject +{ + public Guid Id { get; set; } + + // Object to grant access from + public Guid? OrganizationUserId { get; set; } + public Guid? GroupId { get; set; } + public Guid? ServiceAccountId { get; set; } + + // Object to grant access to + public Guid? GrantedProjectId { get; set; } + public Guid? GrantedServiceAccountId { get; set; } + + // Access + public bool Read { get; set; } + public bool Write { get; set; } + + public DateTime CreationDate { get; set; } + public DateTime RevisionDate { get; set; } + + public void SetNewId() + { + Id = CoreHelpers.GenerateComb(); + } +} + +public abstract class BaseAccessPolicy +{ + public Guid Id { get; set; } + + // Access + public bool Read { get; set; } + public bool Write { get; set; } + + public DateTime CreationDate { get; set; } + public DateTime RevisionDate { get; set; } + + public void SetNewId() + { + Id = CoreHelpers.GenerateComb(); + } +} + +public class UserProjectAccessPolicy : BaseAccessPolicy +{ + public Guid? OrganizationUserId { get; set; } + public Guid? GrantedProjectId { get; set; } +} + +public class UserServiceAccountAccessPolicy : BaseAccessPolicy +{ + public Guid? OrganizationUserId { get; set; } + public Guid? GrantedServiceAccountId { get; set; } +} + +public class GroupProjectAccessPolicy : BaseAccessPolicy +{ + public Guid? GroupId { get; set; } + public Guid? GrantedProjectId { get; set; } +} + +public class GroupServiceAccountAccessPolicy : BaseAccessPolicy +{ + public Guid? GroupId { get; set; } + public Guid? GrantedServiceAccountId { get; set; } +} + +public class ServiceAccountProjectAccessPolicy : BaseAccessPolicy +{ + public Guid? ServiceAccountId { get; set; } + public Guid? GrantedProjectId { get; set; } +} diff --git a/src/Core/Entities/ApiKey.cs b/src/Core/Entities/ApiKey.cs new file mode 100644 index 000000000..e9c16da73 --- /dev/null +++ b/src/Core/Entities/ApiKey.cs @@ -0,0 +1,33 @@ +using System.ComponentModel.DataAnnotations; +using Bit.Core.Utilities; + +namespace Bit.Core.Entities; + +public class ApiKey : ITableObject +{ + public Guid Id { get; set; } + public Guid? ServiceAccountId { get; set; } + [MaxLength(200)] + public string Name { get; set; } + [MaxLength(30)] + public string ClientSecret { get; set; } + [MaxLength(4000)] + public string Scope { get; set; } + [MaxLength(4000)] + public string EncryptedPayload { get; set; } + // Key for decrypting `EncryptedPayload`. Encrypted using the organization key. + public string Key { get; set; } + public DateTime? ExpireAt { get; set; } + public DateTime CreationDate { get; internal set; } = DateTime.UtcNow; + public DateTime RevisionDate { get; internal set; } = DateTime.UtcNow; + + public void SetNewId() + { + Id = CoreHelpers.GenerateComb(); + } + + public ICollection GetScopes() + { + return CoreHelpers.LoadClassFromJsonData>(Scope); + } +} diff --git a/src/Core/Entities/Organization.cs b/src/Core/Entities/Organization.cs index 00232d050..cbb2fb64e 100644 --- a/src/Core/Entities/Organization.cs +++ b/src/Core/Entities/Organization.cs @@ -45,6 +45,7 @@ public class Organization : ITableObject, ISubscriber, IStorable, IStorabl public bool Use2fa { get; set; } public bool UseApi { get; set; } public bool UseResetPassword { get; set; } + public bool UseSecretsManager { get; set; } public bool SelfHost { get; set; } public bool UsersGetPremium { get; set; } public bool UseCustomPermissions { get; set; } diff --git a/src/Core/Entities/Project.cs b/src/Core/Entities/Project.cs new file mode 100644 index 000000000..6c4c4c07f --- /dev/null +++ b/src/Core/Entities/Project.cs @@ -0,0 +1,29 @@ +#nullable enable +using Bit.Core.Utilities; + +namespace Bit.Core.Entities; + +public class Project : ITableObject +{ + public Guid Id { get; set; } + + public Guid OrganizationId { get; set; } + + public string? Name { get; set; } + + public DateTime CreationDate { get; set; } = DateTime.UtcNow; + + public DateTime RevisionDate { get; set; } = DateTime.UtcNow; + + public DateTime? DeletedDate { get; set; } + + public virtual ICollection? Secrets { get; set; } + + public void SetNewId() + { + if (Id == default(Guid)) + { + Id = CoreHelpers.GenerateComb(); + } + } +} diff --git a/src/Core/Entities/Secret.cs b/src/Core/Entities/Secret.cs new file mode 100644 index 000000000..4470f36b9 --- /dev/null +++ b/src/Core/Entities/Secret.cs @@ -0,0 +1,33 @@ +#nullable enable +using Bit.Core.Utilities; + +namespace Bit.Core.Entities; + +public class Secret : ITableObject +{ + public Guid Id { get; set; } + + public Guid OrganizationId { get; set; } + + public string? Key { get; set; } + + public string? Value { get; set; } + + public string? Note { get; set; } + + public DateTime CreationDate { get; set; } = DateTime.UtcNow; + + public DateTime RevisionDate { get; set; } = DateTime.UtcNow; + + public DateTime? DeletedDate { get; set; } + + public ICollection? Projects { get; set; } + + public void SetNewId() + { + if (Id == default(Guid)) + { + Id = CoreHelpers.GenerateComb(); + } + } +} diff --git a/src/Core/Entities/ServiceAccount.cs b/src/Core/Entities/ServiceAccount.cs new file mode 100644 index 000000000..b835dbdb8 --- /dev/null +++ b/src/Core/Entities/ServiceAccount.cs @@ -0,0 +1,26 @@ +#nullable enable +using Bit.Core.Utilities; + +namespace Bit.Core.Entities; + +public class ServiceAccount : ITableObject +{ + public Guid Id { get; set; } + + public Guid OrganizationId { get; set; } + + public string? Name { get; set; } + + public DateTime CreationDate { get; set; } = DateTime.UtcNow; + + public DateTime RevisionDate { get; set; } = DateTime.UtcNow; + + public void SetNewId() + { + if (Id == default(Guid)) + { + Id = CoreHelpers.GenerateComb(); + } + } + +} diff --git a/src/Core/Enums/DeviceType.cs b/src/Core/Enums/DeviceType.cs index 361d9ac38..596a43b03 100644 --- a/src/Core/Enums/DeviceType.cs +++ b/src/Core/Enums/DeviceType.cs @@ -45,5 +45,7 @@ public enum DeviceType : byte [Display(Name = "Vivaldi Extension")] VivaldiExtension = 19, [Display(Name = "Safari Extension")] - SafariExtension = 20 + SafariExtension = 20, + [Display(Name = "SDK")] + SDK = 21, } diff --git a/src/Core/Identity/Claims.cs b/src/Core/Identity/Claims.cs new file mode 100644 index 000000000..d069e16ae --- /dev/null +++ b/src/Core/Identity/Claims.cs @@ -0,0 +1,19 @@ +namespace Bit.Core.Identity; + +public static class Claims +{ + // User + public const string SecurityStamp = "sstamp"; + public const string Premium = "premium"; + public const string Device = "device"; + public const string OrganizationOwner = "orgowner"; + public const string OrganizationAdmin = "orgadmin"; + public const string OrganizationManager = "orgmanager"; + public const string OrganizationUser = "orguser"; + public const string OrganizationCustom = "orgcustom"; + public const string ProviderAdmin = "providerprovideradmin"; + public const string ProviderServiceUser = "providerserviceuser"; + + // Service Account + public const string Organization = "organization"; +} diff --git a/src/Core/IdentityServer/ApiScopes.cs b/src/Core/IdentityServer/ApiScopes.cs new file mode 100644 index 000000000..ad2f242f7 --- /dev/null +++ b/src/Core/IdentityServer/ApiScopes.cs @@ -0,0 +1,28 @@ +using IdentityServer4.Models; + +namespace Bit.Core.IdentityServer; + +public static class ApiScopes +{ + public const string Api = "api"; + public const string ApiInstallation = "api.installation"; + public const string ApiLicensing = "api.licensing"; + public const string ApiOrganization = "api.organization"; + public const string ApiPush = "api.push"; + public const string ApiSecrets = "api.secrets"; + public const string Internal = "internal"; + + public static IEnumerable GetApiScopes() + { + return new List + { + new(Api, "API Access"), + new(ApiPush, "API Push Access"), + new(ApiLicensing, "API Licensing Access"), + new(ApiOrganization, "API Organization Access"), + new(ApiInstallation, "API Installation Access"), + new(Internal, "Internal Access"), + new(ApiSecrets, "Secrets Manager Access"), + }; + } +} diff --git a/src/Core/Models/Data/ApiKeyDetails.cs b/src/Core/Models/Data/ApiKeyDetails.cs new file mode 100644 index 000000000..3e1546889 --- /dev/null +++ b/src/Core/Models/Data/ApiKeyDetails.cs @@ -0,0 +1,37 @@ +using Bit.Core.Entities; + +namespace Bit.Core.Models.Data; + +public class ApiKeyDetails : ApiKey +{ + protected ApiKeyDetails() { } + + protected ApiKeyDetails(ApiKey apiKey) + { + Id = apiKey.Id; + ServiceAccountId = apiKey.ServiceAccountId; + Name = apiKey.Name; + ClientSecret = apiKey.ClientSecret; + Scope = apiKey.Scope; + EncryptedPayload = apiKey.EncryptedPayload; + Key = apiKey.Key; + ExpireAt = apiKey.ExpireAt; + CreationDate = apiKey.CreationDate; + RevisionDate = apiKey.RevisionDate; + } +} + +public class ServiceAccountApiKeyDetails : ApiKeyDetails +{ + public ServiceAccountApiKeyDetails() + { + + } + + public ServiceAccountApiKeyDetails(ApiKey apiKey, Guid organizationId) : base(apiKey) + { + ServiceAccountOrganizationId = organizationId; + } + + public Guid ServiceAccountOrganizationId { get; set; } +} diff --git a/src/Core/Models/Data/Organizations/OrganizationUsers/OrganizationUserOrganizationDetails.cs b/src/Core/Models/Data/Organizations/OrganizationUsers/OrganizationUserOrganizationDetails.cs index 6aa63a880..e104dd621 100644 --- a/src/Core/Models/Data/Organizations/OrganizationUsers/OrganizationUserOrganizationDetails.cs +++ b/src/Core/Models/Data/Organizations/OrganizationUsers/OrganizationUserOrganizationDetails.cs @@ -16,6 +16,7 @@ public class OrganizationUserOrganizationDetails public bool Use2fa { get; set; } public bool UseApi { get; set; } public bool UseResetPassword { get; set; } + public bool UseSecretsManager { get; set; } public bool SelfHost { get; set; } public bool UsersGetPremium { get; set; } public bool UseCustomPermissions { get; set; } diff --git a/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommand.cs b/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommand.cs index c1a3e97e8..eed143838 100644 --- a/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommand.cs +++ b/src/Core/OrganizationFeatures/OrganizationSponsorships/FamiliesForEnterprise/SelfHosted/SelfHostedSyncSponsorshipsCommand.cs @@ -1,5 +1,6 @@ using Bit.Core.Entities; using Bit.Core.Exceptions; +using Bit.Core.IdentityServer; using Bit.Core.Models.Api.Request.OrganizationSponsorships; using Bit.Core.Models.Api.Response.OrganizationSponsorships; using Bit.Core.Models.Data.Organizations.OrganizationSponsorships; @@ -30,7 +31,7 @@ public class SelfHostedSyncSponsorshipsCommand : BaseIdentityClientService, ISel httpFactory, globalSettings.Installation.ApiUri, globalSettings.Installation.IdentityUri, - "api.installation", + ApiScopes.ApiInstallation, $"installation.{globalSettings.Installation.Id}", globalSettings.Installation.Key, logger) diff --git a/src/Core/Repositories/IAccessPolicyRepository.cs b/src/Core/Repositories/IAccessPolicyRepository.cs new file mode 100644 index 000000000..cecee6f1c --- /dev/null +++ b/src/Core/Repositories/IAccessPolicyRepository.cs @@ -0,0 +1,7 @@ +using Bit.Core.Entities; + +namespace Bit.Core.Repositories; + +public interface IAccessPolicyRepository : IRepository +{ +} diff --git a/src/Core/Repositories/IApiKeyRepository.cs b/src/Core/Repositories/IApiKeyRepository.cs new file mode 100644 index 000000000..dd99c99a9 --- /dev/null +++ b/src/Core/Repositories/IApiKeyRepository.cs @@ -0,0 +1,10 @@ +using Bit.Core.Entities; +using Bit.Core.Models.Data; + +namespace Bit.Core.Repositories; + +public interface IApiKeyRepository : IRepository +{ + Task GetDetailsByIdAsync(Guid id); + Task> GetManyByServiceAccountIdAsync(Guid id); +} diff --git a/src/Core/Repositories/IProjectRepository.cs b/src/Core/Repositories/IProjectRepository.cs new file mode 100644 index 000000000..80a3a6242 --- /dev/null +++ b/src/Core/Repositories/IProjectRepository.cs @@ -0,0 +1,13 @@ +using Bit.Core.Entities; + +namespace Bit.Core.Repositories; + +public interface IProjectRepository +{ + Task> GetManyByOrganizationIdAsync(Guid organizationId, Guid userId); + Task> GetManyByIds(IEnumerable ids); + Task GetByIdAsync(Guid id); + Task CreateAsync(Project project); + Task ReplaceAsync(Project project); + Task DeleteManyByIdAsync(IEnumerable ids); +} diff --git a/src/Core/Repositories/ISecretRepository.cs b/src/Core/Repositories/ISecretRepository.cs new file mode 100644 index 000000000..d52e567a4 --- /dev/null +++ b/src/Core/Repositories/ISecretRepository.cs @@ -0,0 +1,14 @@ +using Bit.Core.Entities; + +namespace Bit.Core.Repositories; + +public interface ISecretRepository +{ + Task> GetManyByOrganizationIdAsync(Guid organizationId); + Task> GetManyByIds(IEnumerable ids); + Task> GetManyByProjectIdAsync(Guid projectId); + Task GetByIdAsync(Guid id); + Task CreateAsync(Secret secret); + Task UpdateAsync(Secret secret); + Task SoftDeleteManyByIdAsync(IEnumerable ids); +} diff --git a/src/Core/Repositories/IServiceAccountRepository.cs b/src/Core/Repositories/IServiceAccountRepository.cs new file mode 100644 index 000000000..83da33a15 --- /dev/null +++ b/src/Core/Repositories/IServiceAccountRepository.cs @@ -0,0 +1,11 @@ +using Bit.Core.Entities; + +namespace Bit.Core.Repositories; + +public interface IServiceAccountRepository +{ + Task> GetManyByOrganizationIdAsync(Guid organizationId); + Task GetByIdAsync(Guid id); + Task CreateAsync(ServiceAccount serviceAccount); + Task ReplaceAsync(ServiceAccount serviceAccount); +} diff --git a/src/Core/SecretManagerFeatures/AccessTokens/Interfaces/ICreateAccessTokenCommand.cs b/src/Core/SecretManagerFeatures/AccessTokens/Interfaces/ICreateAccessTokenCommand.cs new file mode 100644 index 000000000..d4af3a3dc --- /dev/null +++ b/src/Core/SecretManagerFeatures/AccessTokens/Interfaces/ICreateAccessTokenCommand.cs @@ -0,0 +1,8 @@ +using Bit.Core.Entities; + +namespace Bit.Core.SecretManagerFeatures.AccessTokens.Interfaces; + +public interface ICreateAccessTokenCommand +{ + Task CreateAsync(ApiKey apiKey); +} diff --git a/src/Core/SecretManagerFeatures/Projects/Interfaces/ICreateProjectCommand.cs b/src/Core/SecretManagerFeatures/Projects/Interfaces/ICreateProjectCommand.cs new file mode 100644 index 000000000..8b2cb705f --- /dev/null +++ b/src/Core/SecretManagerFeatures/Projects/Interfaces/ICreateProjectCommand.cs @@ -0,0 +1,8 @@ +using Bit.Core.Entities; + +namespace Bit.Core.SecretManagerFeatures.Projects.Interfaces; + +public interface ICreateProjectCommand +{ + Task CreateAsync(Project project); +} diff --git a/src/Core/SecretManagerFeatures/Projects/Interfaces/IDeleteProjectCommand.cs b/src/Core/SecretManagerFeatures/Projects/Interfaces/IDeleteProjectCommand.cs new file mode 100644 index 000000000..c587fd5c7 --- /dev/null +++ b/src/Core/SecretManagerFeatures/Projects/Interfaces/IDeleteProjectCommand.cs @@ -0,0 +1,9 @@ +using Bit.Core.Entities; + +namespace Bit.Core.SecretManagerFeatures.Projects.Interfaces; + +public interface IDeleteProjectCommand +{ + Task>> DeleteProjects(List ids); +} + diff --git a/src/Core/SecretManagerFeatures/Projects/Interfaces/IUpdateProjectCommand.cs b/src/Core/SecretManagerFeatures/Projects/Interfaces/IUpdateProjectCommand.cs new file mode 100644 index 000000000..06058cdd8 --- /dev/null +++ b/src/Core/SecretManagerFeatures/Projects/Interfaces/IUpdateProjectCommand.cs @@ -0,0 +1,8 @@ +using Bit.Core.Entities; + +namespace Bit.Core.SecretManagerFeatures.Projects.Interfaces; + +public interface IUpdateProjectCommand +{ + Task UpdateAsync(Project project); +} diff --git a/src/Core/SecretManagerFeatures/Secrets/Interfaces/ICreateSecretCommand.cs b/src/Core/SecretManagerFeatures/Secrets/Interfaces/ICreateSecretCommand.cs new file mode 100644 index 000000000..c457cc149 --- /dev/null +++ b/src/Core/SecretManagerFeatures/Secrets/Interfaces/ICreateSecretCommand.cs @@ -0,0 +1,8 @@ +using Bit.Core.Entities; + +namespace Bit.Core.SecretManagerFeatures.Secrets.Interfaces; + +public interface ICreateSecretCommand +{ + Task CreateAsync(Secret secret); +} diff --git a/src/Core/SecretManagerFeatures/Secrets/Interfaces/IDeleteSecretCommand.cs b/src/Core/SecretManagerFeatures/Secrets/Interfaces/IDeleteSecretCommand.cs new file mode 100644 index 000000000..ee7c12da3 --- /dev/null +++ b/src/Core/SecretManagerFeatures/Secrets/Interfaces/IDeleteSecretCommand.cs @@ -0,0 +1,9 @@ +using Bit.Core.Entities; + +namespace Bit.Core.SecretManagerFeatures.Secrets.Interfaces; + +public interface IDeleteSecretCommand +{ + Task>> DeleteSecrets(List ids); +} + diff --git a/src/Core/SecretManagerFeatures/Secrets/Interfaces/IUpdateSecretCommand.cs b/src/Core/SecretManagerFeatures/Secrets/Interfaces/IUpdateSecretCommand.cs new file mode 100644 index 000000000..7b02fc4e4 --- /dev/null +++ b/src/Core/SecretManagerFeatures/Secrets/Interfaces/IUpdateSecretCommand.cs @@ -0,0 +1,8 @@ +using Bit.Core.Entities; + +namespace Bit.Core.SecretManagerFeatures.Secrets.Interfaces; + +public interface IUpdateSecretCommand +{ + Task UpdateAsync(Secret secret); +} diff --git a/src/Core/SecretManagerFeatures/ServiceAccounts/Interfaces/ICreateServiceAccountCommand.cs b/src/Core/SecretManagerFeatures/ServiceAccounts/Interfaces/ICreateServiceAccountCommand.cs new file mode 100644 index 000000000..b236889ed --- /dev/null +++ b/src/Core/SecretManagerFeatures/ServiceAccounts/Interfaces/ICreateServiceAccountCommand.cs @@ -0,0 +1,8 @@ +using Bit.Core.Entities; + +namespace Bit.Core.SecretManagerFeatures.ServiceAccounts.Interfaces; + +public interface ICreateServiceAccountCommand +{ + Task CreateAsync(ServiceAccount serviceAccount); +} diff --git a/src/Core/SecretManagerFeatures/ServiceAccounts/Interfaces/IUpdateServiceAccountCommand.cs b/src/Core/SecretManagerFeatures/ServiceAccounts/Interfaces/IUpdateServiceAccountCommand.cs new file mode 100644 index 000000000..5d7f65261 --- /dev/null +++ b/src/Core/SecretManagerFeatures/ServiceAccounts/Interfaces/IUpdateServiceAccountCommand.cs @@ -0,0 +1,8 @@ +using Bit.Core.Entities; + +namespace Bit.Core.SecretManagerFeatures.ServiceAccounts.Interfaces; + +public interface IUpdateServiceAccountCommand +{ + Task UpdateAsync(ServiceAccount serviceAccount); +} diff --git a/src/Core/Services/Implementations/RelayPushNotificationService.cs b/src/Core/Services/Implementations/RelayPushNotificationService.cs index 17dae8709..e44707192 100644 --- a/src/Core/Services/Implementations/RelayPushNotificationService.cs +++ b/src/Core/Services/Implementations/RelayPushNotificationService.cs @@ -1,6 +1,7 @@ using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Enums; +using Bit.Core.IdentityServer; using Bit.Core.Models; using Bit.Core.Models.Api; using Bit.Core.Repositories; @@ -25,7 +26,7 @@ public class RelayPushNotificationService : BaseIdentityClientService, IPushNoti httpFactory, globalSettings.PushRelayBaseUri, globalSettings.Installation.IdentityUri, - "api.push", + ApiScopes.ApiPush, $"installation.{globalSettings.Installation.Id}", globalSettings.Installation.Key, logger) diff --git a/src/Core/Services/Implementations/RelayPushRegistrationService.cs b/src/Core/Services/Implementations/RelayPushRegistrationService.cs index 2e3087421..f661af537 100644 --- a/src/Core/Services/Implementations/RelayPushRegistrationService.cs +++ b/src/Core/Services/Implementations/RelayPushRegistrationService.cs @@ -1,4 +1,5 @@ using Bit.Core.Enums; +using Bit.Core.IdentityServer; using Bit.Core.Models.Api; using Bit.Core.Settings; using Microsoft.Extensions.Logging; @@ -16,7 +17,7 @@ public class RelayPushRegistrationService : BaseIdentityClientService, IPushRegi httpFactory, globalSettings.PushRelayBaseUri, globalSettings.Installation.IdentityUri, - "api.push", + ApiScopes.ApiPush, $"installation.{globalSettings.Installation.Id}", globalSettings.Installation.Key, logger) diff --git a/src/Core/Utilities/CoreHelpers.cs b/src/Core/Utilities/CoreHelpers.cs index b35bf7684..b925550d7 100644 --- a/src/Core/Utilities/CoreHelpers.cs +++ b/src/Core/Utilities/CoreHelpers.cs @@ -14,6 +14,7 @@ using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Enums; using Bit.Core.Enums.Provider; +using Bit.Core.Identity; using Bit.Core.Settings; using IdentityModel; using Microsoft.AspNetCore.DataProtection; @@ -631,10 +632,10 @@ public static class CoreHelpers { var claims = new List>() { - new KeyValuePair("premium", isPremium ? "true" : "false"), - new KeyValuePair(JwtClaimTypes.Email, user.Email), - new KeyValuePair(JwtClaimTypes.EmailVerified, user.EmailVerified ? "true" : "false"), - new KeyValuePair("sstamp", user.SecurityStamp) + new(Claims.Premium, isPremium ? "true" : "false"), + new(JwtClaimTypes.Email, user.Email), + new(JwtClaimTypes.EmailVerified, user.EmailVerified ? "true" : "false"), + new(Claims.SecurityStamp, user.SecurityStamp), }; if (!string.IsNullOrWhiteSpace(user.Name)) @@ -652,31 +653,31 @@ public static class CoreHelpers case Enums.OrganizationUserType.Owner: foreach (var org in group) { - claims.Add(new KeyValuePair("orgowner", org.Id.ToString())); + claims.Add(new KeyValuePair(Claims.OrganizationOwner, org.Id.ToString())); } break; case Enums.OrganizationUserType.Admin: foreach (var org in group) { - claims.Add(new KeyValuePair("orgadmin", org.Id.ToString())); + claims.Add(new KeyValuePair(Claims.OrganizationAdmin, org.Id.ToString())); } break; case Enums.OrganizationUserType.Manager: foreach (var org in group) { - claims.Add(new KeyValuePair("orgmanager", org.Id.ToString())); + claims.Add(new KeyValuePair(Claims.OrganizationManager, org.Id.ToString())); } break; case Enums.OrganizationUserType.User: foreach (var org in group) { - claims.Add(new KeyValuePair("orguser", org.Id.ToString())); + claims.Add(new KeyValuePair(Claims.OrganizationUser, org.Id.ToString())); } break; case Enums.OrganizationUserType.Custom: foreach (var org in group) { - claims.Add(new KeyValuePair("orgcustom", org.Id.ToString())); + claims.Add(new KeyValuePair(Claims.OrganizationCustom, org.Id.ToString())); foreach (var (permission, claimName) in org.Permissions.ClaimsMap) { if (!permission) @@ -703,13 +704,13 @@ public static class CoreHelpers case ProviderUserType.ProviderAdmin: foreach (var provider in group) { - claims.Add(new KeyValuePair("providerprovideradmin", provider.Id.ToString())); + claims.Add(new KeyValuePair(Claims.ProviderAdmin, provider.Id.ToString())); } break; case ProviderUserType.ServiceUser: foreach (var provider in group) { - claims.Add(new KeyValuePair("providerserviceuser", provider.Id.ToString())); + claims.Add(new KeyValuePair(Claims.ProviderServiceUser, provider.Id.ToString())); } break; } diff --git a/src/Events/Startup.cs b/src/Events/Startup.cs index 197cbdf18..9aee5425c 100644 --- a/src/Events/Startup.cs +++ b/src/Events/Startup.cs @@ -1,5 +1,6 @@ using System.Globalization; using Bit.Core.Context; +using Bit.Core.IdentityServer; using Bit.Core.Services; using Bit.Core.Settings; using Bit.Core.Utilities; @@ -41,7 +42,7 @@ public class Startup { policy.RequireAuthenticatedUser(); policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application", "external"); - policy.RequireClaim(JwtClaimTypes.Scope, "api"); + policy.RequireClaim(JwtClaimTypes.Scope, ApiScopes.Api); }); }); diff --git a/src/Events/packages.lock.json b/src/Events/packages.lock.json index 028ea2e00..ca2e9c172 100644 --- a/src/Events/packages.lock.json +++ b/src/Events/packages.lock.json @@ -539,6 +539,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2754,6 +2763,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/src/EventsProcessor/packages.lock.json b/src/EventsProcessor/packages.lock.json index 028ea2e00..ca2e9c172 100644 --- a/src/EventsProcessor/packages.lock.json +++ b/src/EventsProcessor/packages.lock.json @@ -539,6 +539,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2754,6 +2763,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/src/Icons/packages.lock.json b/src/Icons/packages.lock.json index 4a2542b1e..f71f57a08 100644 --- a/src/Icons/packages.lock.json +++ b/src/Icons/packages.lock.json @@ -549,6 +549,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2764,6 +2773,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/src/Identity/IdentityServer/ApiResources.cs b/src/Identity/IdentityServer/ApiResources.cs index 07cb7b501..5d212f99b 100644 --- a/src/Identity/IdentityServer/ApiResources.cs +++ b/src/Identity/IdentityServer/ApiResources.cs @@ -1,4 +1,6 @@ -using IdentityModel; +using Bit.Core.Identity; +using Bit.Core.IdentityServer; +using IdentityModel; using IdentityServer4.Models; namespace Bit.Identity.IdentityServer; @@ -9,27 +11,27 @@ public class ApiResources { return new List { - new ApiResource("api", new string[] { + new("api", new[] { JwtClaimTypes.Name, JwtClaimTypes.Email, JwtClaimTypes.EmailVerified, - "sstamp", // security stamp - "premium", - "device", - "orgowner", - "orgadmin", - "orgmanager", - "orguser", - "orgcustom", - "providerprovideradmin", - "providerserviceuser", + Claims.SecurityStamp, + Claims.Premium, + Claims.Device, + Claims.OrganizationOwner, + Claims.OrganizationAdmin, + Claims.OrganizationManager, + Claims.OrganizationUser, + Claims.OrganizationCustom, + Claims.ProviderAdmin, + Claims.ProviderServiceUser, }), - new ApiResource("internal", new string[] { JwtClaimTypes.Subject }), - new ApiResource("api.push", new string[] { JwtClaimTypes.Subject }), - new ApiResource("api.licensing", new string[] { JwtClaimTypes.Subject }), - new ApiResource("api.organization", new string[] { JwtClaimTypes.Subject }), - new ApiResource("api.provider", new string[] { JwtClaimTypes.Subject }), - new ApiResource("api.installation", new string[] { JwtClaimTypes.Subject }), + new(ApiScopes.Internal, new[] { JwtClaimTypes.Subject }), + new(ApiScopes.ApiPush, new[] { JwtClaimTypes.Subject }), + new(ApiScopes.ApiLicensing, new[] { JwtClaimTypes.Subject }), + new(ApiScopes.ApiOrganization, new[] { JwtClaimTypes.Subject }), + new(ApiScopes.ApiInstallation, new[] { JwtClaimTypes.Subject }), + new(ApiScopes.ApiSecrets, new[] { JwtClaimTypes.Subject, Claims.Organization }), }; } } diff --git a/src/Identity/IdentityServer/ApiScopes.cs b/src/Identity/IdentityServer/ApiScopes.cs deleted file mode 100644 index 2e8fe983e..000000000 --- a/src/Identity/IdentityServer/ApiScopes.cs +++ /dev/null @@ -1,19 +0,0 @@ -using IdentityServer4.Models; - -namespace Bit.Identity.IdentityServer; - -public class ApiScopes -{ - public static IEnumerable GetApiScopes() - { - return new List - { - new ApiScope("api", "API Access"), - new ApiScope("api.push", "API Push Access"), - new ApiScope("api.licensing", "API Licensing Access"), - new ApiScope("api.organization", "API Organization Access"), - new ApiScope("api.installation", "API Installation Access"), - new ApiScope("internal", "Internal Access") - }; - } -} diff --git a/src/Identity/IdentityServer/BaseRequestValidator.cs b/src/Identity/IdentityServer/BaseRequestValidator.cs index 93828d4db..d9fbc32f3 100644 --- a/src/Identity/IdentityServer/BaseRequestValidator.cs +++ b/src/Identity/IdentityServer/BaseRequestValidator.cs @@ -31,12 +31,11 @@ public abstract class BaseRequestValidator where T : class private readonly IOrganizationUserRepository _organizationUserRepository; private readonly IApplicationCacheService _applicationCacheService; private readonly IMailService _mailService; - private readonly ILogger _logger; + private readonly ILogger _logger; private readonly ICurrentContext _currentContext; private readonly GlobalSettings _globalSettings; private readonly IPolicyRepository _policyRepository; private readonly IUserRepository _userRepository; - private readonly ICaptchaValidationService _captchaValidationService; public BaseRequestValidator( UserManager userManager, @@ -49,12 +48,11 @@ public abstract class BaseRequestValidator where T : class IOrganizationUserRepository organizationUserRepository, IApplicationCacheService applicationCacheService, IMailService mailService, - ILogger logger, + ILogger logger, ICurrentContext currentContext, GlobalSettings globalSettings, IPolicyRepository policyRepository, - IUserRepository userRepository, - ICaptchaValidationService captchaValidationService) + IUserRepository userRepository) { _userManager = userManager; _deviceRepository = deviceRepository; @@ -71,7 +69,6 @@ public abstract class BaseRequestValidator where T : class _globalSettings = globalSettings; _policyRepository = policyRepository; _userRepository = userRepository; - _captchaValidationService = captchaValidationService; } protected async Task ValidateAsync(T context, ValidatedTokenRequest request, @@ -172,7 +169,7 @@ public abstract class BaseRequestValidator where T : class if (device != null) { - claims.Add(new Claim("device", device.Identifier)); + claims.Add(new Claim(Claims.Device, device.Identifier)); } var customResponse = new Dictionary(); diff --git a/src/Identity/IdentityServer/ClientStore.cs b/src/Identity/IdentityServer/ClientStore.cs index b8fa2e421..b73498f9c 100644 --- a/src/Identity/IdentityServer/ClientStore.cs +++ b/src/Identity/IdentityServer/ClientStore.cs @@ -2,6 +2,9 @@ using System.Security.Claims; using Bit.Core.Context; using Bit.Core.Enums; +using Bit.Core.Identity; +using Bit.Core.IdentityServer; +using Bit.Core.Models.Data; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Settings; @@ -23,8 +26,8 @@ public class ClientStore : IClientStore private readonly ICurrentContext _currentContext; private readonly IOrganizationUserRepository _organizationUserRepository; private readonly IProviderUserRepository _providerUserRepository; - private readonly IProviderOrganizationRepository _providerOrganizationRepository; private readonly IOrganizationApiKeyRepository _organizationApiKeyRepository; + private readonly IApiKeyRepository _apiKeyRepository; public ClientStore( IInstallationRepository installationRepository, @@ -36,8 +39,8 @@ public class ClientStore : IClientStore ICurrentContext currentContext, IOrganizationUserRepository organizationUserRepository, IProviderUserRepository providerUserRepository, - IProviderOrganizationRepository providerOrganizationRepository, - IOrganizationApiKeyRepository organizationApiKeyRepository) + IOrganizationApiKeyRepository organizationApiKeyRepository, + IApiKeyRepository apiKeyRepository) { _installationRepository = installationRepository; _organizationRepository = organizationRepository; @@ -48,133 +51,219 @@ public class ClientStore : IClientStore _currentContext = currentContext; _organizationUserRepository = organizationUserRepository; _providerUserRepository = providerUserRepository; - _providerOrganizationRepository = providerOrganizationRepository; _organizationApiKeyRepository = organizationApiKeyRepository; + _apiKeyRepository = apiKeyRepository; } public async Task FindClientByIdAsync(string clientId) { if (!_globalSettings.SelfHosted && clientId.StartsWith("installation.")) { - var idParts = clientId.Split('.'); - if (idParts.Length > 1 && Guid.TryParse(idParts[1], out Guid id)) - { - var installation = await _installationRepository.GetByIdAsync(id); - if (installation != null) - { - return new Client - { - ClientId = $"installation.{installation.Id}", - RequireClientSecret = true, - ClientSecrets = { new Secret(installation.Key.Sha256()) }, - AllowedScopes = new string[] { "api.push", "api.licensing", "api.installation" }, - AllowedGrantTypes = GrantTypes.ClientCredentials, - AccessTokenLifetime = 3600 * 24, - Enabled = installation.Enabled, - Claims = new List - { - new ClientClaim(JwtClaimTypes.Subject, installation.Id.ToString()) - } - }; - } - } + return await CreateInstallationClientAsync(clientId); } - else if (_globalSettings.SelfHosted && clientId.StartsWith("internal.") && + + if (_globalSettings.SelfHosted && clientId.StartsWith("internal.") && CoreHelpers.SettingHasValue(_globalSettings.InternalIdentityKey)) { - var idParts = clientId.Split('.'); - if (idParts.Length > 1) - { - var id = idParts[1]; - if (!string.IsNullOrWhiteSpace(id)) - { - return new Client - { - ClientId = $"internal.{id}", - RequireClientSecret = true, - ClientSecrets = { new Secret(_globalSettings.InternalIdentityKey.Sha256()) }, - AllowedScopes = new string[] { "internal" }, - AllowedGrantTypes = GrantTypes.ClientCredentials, - AccessTokenLifetime = 3600 * 24, - Enabled = true, - Claims = new List - { - new ClientClaim(JwtClaimTypes.Subject, id) - } - }; - } - } - } - else if (clientId.StartsWith("organization.")) - { - var idParts = clientId.Split('.'); - if (idParts.Length > 1 && Guid.TryParse(idParts[1], out var id)) - { - var org = await _organizationRepository.GetByIdAsync(id); - if (org != null) - { - var orgApiKey = (await _organizationApiKeyRepository - .GetManyByOrganizationIdTypeAsync(org.Id, OrganizationApiKeyType.Default)) - .First(); - return new Client - { - ClientId = $"organization.{org.Id}", - RequireClientSecret = true, - ClientSecrets = { new Secret(orgApiKey.ApiKey.Sha256()) }, - AllowedScopes = new string[] { "api.organization" }, - AllowedGrantTypes = GrantTypes.ClientCredentials, - AccessTokenLifetime = 3600 * 1, - Enabled = org.Enabled && org.UseApi, - Claims = new List - { - new ClientClaim(JwtClaimTypes.Subject, org.Id.ToString()) - } - }; - } - } - } - else if (clientId.StartsWith("user.")) - { - var idParts = clientId.Split('.'); - if (idParts.Length > 1 && Guid.TryParse(idParts[1], out var id)) - { - var user = await _userRepository.GetByIdAsync(id); - if (user != null) - { - var claims = new Collection() - { - new ClientClaim(JwtClaimTypes.Subject, user.Id.ToString()), - new ClientClaim(JwtClaimTypes.AuthenticationMethod, "Application", "external") - }; - var orgs = await _currentContext.OrganizationMembershipAsync(_organizationUserRepository, user.Id); - var providers = await _currentContext.ProviderMembershipAsync(_providerUserRepository, user.Id); - var isPremium = await _licensingService.ValidateUserPremiumAsync(user); - foreach (var claim in CoreHelpers.BuildIdentityClaims(user, orgs, providers, isPremium)) - { - var upperValue = claim.Value.ToUpperInvariant(); - var isBool = upperValue == "TRUE" || upperValue == "FALSE"; - claims.Add(isBool ? - new ClientClaim(claim.Key, claim.Value, ClaimValueTypes.Boolean) : - new ClientClaim(claim.Key, claim.Value) - ); - } - - return new Client - { - ClientId = clientId, - RequireClientSecret = true, - ClientSecrets = { new Secret(user.ApiKey.Sha256()) }, - AllowedScopes = new string[] { "api" }, - AllowedGrantTypes = GrantTypes.ClientCredentials, - AccessTokenLifetime = 3600 * 1, - ClientClaimsPrefix = null, - Claims = claims - }; - } - } + return CreateInternalClient(clientId); } - return _staticClientStore.ApiClients.ContainsKey(clientId) ? - _staticClientStore.ApiClients[clientId] : null; + if (clientId.StartsWith("organization.")) + { + return await CreateOrganizationClientAsync(clientId); + } + + if (clientId.StartsWith("user.")) + { + return await CreateUserClientAsync(clientId); + } + + if (_staticClientStore.ApiClients.ContainsKey(clientId)) + { + return _staticClientStore.ApiClients[clientId]; + } + + return await CreateApiKeyClientAsync(clientId); + } + + private async Task CreateApiKeyClientAsync(string clientId) + { + var apiKey = await _apiKeyRepository.GetDetailsByIdAsync(new Guid(clientId)); + + if (apiKey == null || apiKey.ExpireAt <= DateTime.Now) + { + return null; + } + + var client = new Client + { + ClientId = clientId, + RequireClientSecret = true, + ClientSecrets = { new Secret(apiKey.ClientSecret.Sha256()) }, + AllowedScopes = apiKey.GetScopes(), + AllowedGrantTypes = GrantTypes.ClientCredentials, + AccessTokenLifetime = 3600 * 1, + ClientClaimsPrefix = null, + Properties = new Dictionary { + {"encryptedPayload", apiKey.EncryptedPayload}, + }, + Claims = new List + { + new(JwtClaimTypes.Subject, apiKey.ServiceAccountId.ToString()), + }, + }; + + switch (apiKey) + { + case ServiceAccountApiKeyDetails key: + client.Claims.Add(new ClientClaim(Claims.Organization, key.ServiceAccountOrganizationId.ToString())); + break; + } + + return client; + } + + private async Task CreateUserClientAsync(string clientId) + { + var idParts = clientId.Split('.'); + if (idParts.Length <= 1 || !Guid.TryParse(idParts[1], out var id)) + { + return null; + } + + var user = await _userRepository.GetByIdAsync(id); + if (user == null) + { + return null; + } + + var claims = new Collection + { + new(JwtClaimTypes.Subject, user.Id.ToString()), + new(JwtClaimTypes.AuthenticationMethod, "Application", "external"), + }; + var orgs = await _currentContext.OrganizationMembershipAsync(_organizationUserRepository, user.Id); + var providers = await _currentContext.ProviderMembershipAsync(_providerUserRepository, user.Id); + var isPremium = await _licensingService.ValidateUserPremiumAsync(user); + foreach (var claim in CoreHelpers.BuildIdentityClaims(user, orgs, providers, isPremium)) + { + var upperValue = claim.Value.ToUpperInvariant(); + var isBool = upperValue is "TRUE" or "FALSE"; + claims.Add(isBool + ? new ClientClaim(claim.Key, claim.Value, ClaimValueTypes.Boolean) + : new ClientClaim(claim.Key, claim.Value) + ); + } + + return new Client + { + ClientId = clientId, + RequireClientSecret = true, + ClientSecrets = { new Secret(user.ApiKey.Sha256()) }, + AllowedScopes = new[] { "api" }, + AllowedGrantTypes = GrantTypes.ClientCredentials, + AccessTokenLifetime = 3600 * 1, + ClientClaimsPrefix = null, + Claims = claims, + }; + } + + private async Task CreateOrganizationClientAsync(string clientId) + { + var idParts = clientId.Split('.'); + if (idParts.Length <= 1 || !Guid.TryParse(idParts[1], out var id)) + { + return null; + } + + var org = await _organizationRepository.GetByIdAsync(id); + if (org == null) + { + return null; + } + + var orgApiKey = (await _organizationApiKeyRepository + .GetManyByOrganizationIdTypeAsync(org.Id, OrganizationApiKeyType.Default)) + .First(); + + return new Client + { + ClientId = $"organization.{org.Id}", + RequireClientSecret = true, + ClientSecrets = { new Secret(orgApiKey.ApiKey.Sha256()) }, + AllowedScopes = new[] { ApiScopes.ApiOrganization }, + AllowedGrantTypes = GrantTypes.ClientCredentials, + AccessTokenLifetime = 3600 * 1, + Enabled = org.Enabled && org.UseApi, + Claims = new List + { + new(JwtClaimTypes.Subject, org.Id.ToString()), + }, + }; + } + + private Client CreateInternalClient(string clientId) + { + var idParts = clientId.Split('.'); + if (idParts.Length <= 1) + { + return null; + } + + var id = idParts[1]; + if (string.IsNullOrWhiteSpace(id)) + { + return null; + } + + return new Client + { + ClientId = $"internal.{id}", + RequireClientSecret = true, + ClientSecrets = { new Secret(_globalSettings.InternalIdentityKey.Sha256()) }, + AllowedScopes = new[] { ApiScopes.Internal }, + AllowedGrantTypes = GrantTypes.ClientCredentials, + AccessTokenLifetime = 3600 * 24, + Enabled = true, + Claims = new List + { + new(JwtClaimTypes.Subject, id), + }, + }; + } + + private async Task CreateInstallationClientAsync(string clientId) + { + var idParts = clientId.Split('.'); + if (idParts.Length <= 1 || !Guid.TryParse(idParts[1], out Guid id)) + { + return null; + } + + var installation = await _installationRepository.GetByIdAsync(id); + if (installation == null) + { + return null; + } + + return new Client + { + ClientId = $"installation.{installation.Id}", + RequireClientSecret = true, + ClientSecrets = { new Secret(installation.Key.Sha256()) }, + AllowedScopes = new[] + { + ApiScopes.ApiPush, + ApiScopes.ApiLicensing, + ApiScopes.ApiInstallation, + }, + AllowedGrantTypes = GrantTypes.ClientCredentials, + AccessTokenLifetime = 3600 * 24, + Enabled = installation.Enabled, + Claims = new List + { + new(JwtClaimTypes.Subject, installation.Id.ToString()), + }, + }; } } diff --git a/src/Identity/IdentityServer/CustomTokenRequestValidator.cs b/src/Identity/IdentityServer/CustomTokenRequestValidator.cs index c817acd68..05db3314c 100644 --- a/src/Identity/IdentityServer/CustomTokenRequestValidator.cs +++ b/src/Identity/IdentityServer/CustomTokenRequestValidator.cs @@ -2,6 +2,7 @@ using Bit.Core.Context; using Bit.Core.Entities; using Bit.Core.Identity; +using Bit.Core.IdentityServer; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Settings; @@ -17,7 +18,6 @@ public class CustomTokenRequestValidator : BaseRequestValidator _userManager; private readonly ISsoConfigRepository _ssoConfigRepository; - private readonly IOrganizationRepository _organizationRepository; public CustomTokenRequestValidator( UserManager userManager, @@ -30,21 +30,19 @@ public class CustomTokenRequestValidator : BaseRequestValidator logger, + ILogger logger, ICurrentContext currentContext, GlobalSettings globalSettings, IPolicyRepository policyRepository, ISsoConfigRepository ssoConfigRepository, - IUserRepository userRepository, - ICaptchaValidationService captchaValidationService) + IUserRepository userRepository) : base(userManager, deviceRepository, deviceService, userService, eventService, organizationDuoWebTokenProvider, organizationRepository, organizationUserRepository, applicationCacheService, mailService, logger, currentContext, globalSettings, policyRepository, - userRepository, captchaValidationService) + userRepository) { _userManager = userManager; _ssoConfigRepository = ssoConfigRepository; - _organizationRepository = organizationRepository; } public async Task ValidateAsync(CustomTokenRequestValidationContext context) @@ -53,10 +51,18 @@ public class CustomTokenRequestValidator : BaseRequestValidator { { "encrypted_payload", payload } }; + } + return; } + await ValidateAsync(context, context.Result.ValidatedRequest, new CustomValidatorRequestContext { KnownDevice = true }); } diff --git a/src/Identity/IdentityServer/ProfileService.cs b/src/Identity/IdentityServer/ProfileService.cs index 6b66b1850..e8cad3c01 100644 --- a/src/Identity/IdentityServer/ProfileService.cs +++ b/src/Identity/IdentityServer/ProfileService.cs @@ -1,5 +1,6 @@ using System.Security.Claims; using Bit.Core.Context; +using Bit.Core.Identity; using Bit.Core.Repositories; using Bit.Core.Services; using Bit.Core.Utilities; @@ -70,7 +71,7 @@ public class ProfileService : IProfileService public async Task IsActiveAsync(IsActiveContext context) { - var securityTokenClaim = context.Subject?.Claims.FirstOrDefault(c => c.Type == "sstamp"); + var securityTokenClaim = context.Subject?.Claims.FirstOrDefault(c => c.Type == Claims.SecurityStamp); var user = await _userService.GetUserByPrincipalAsync(context.Subject); if (user != null && securityTokenClaim != null) diff --git a/src/Identity/IdentityServer/ResourceOwnerPasswordValidator.cs b/src/Identity/IdentityServer/ResourceOwnerPasswordValidator.cs index 65e676c4d..40a3de3d9 100644 --- a/src/Identity/IdentityServer/ResourceOwnerPasswordValidator.cs +++ b/src/Identity/IdentityServer/ResourceOwnerPasswordValidator.cs @@ -41,7 +41,7 @@ public class ResourceOwnerPasswordValidator : BaseRequestValidator(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); if (selfHosted) { diff --git a/src/Infrastructure.Dapper/Repositories/ApiKeyRepository.cs b/src/Infrastructure.Dapper/Repositories/ApiKeyRepository.cs new file mode 100644 index 000000000..52194d388 --- /dev/null +++ b/src/Infrastructure.Dapper/Repositories/ApiKeyRepository.cs @@ -0,0 +1,44 @@ +using System.Data; +using System.Data.SqlClient; +using Bit.Core.Entities; +using Bit.Core.Models.Data; +using Bit.Core.Repositories; +using Bit.Core.Settings; +using Dapper; + +namespace Bit.Infrastructure.Dapper.Repositories; + +public class ApiKeyRepository : Repository, IApiKeyRepository +{ + public ApiKeyRepository(GlobalSettings globalSettings) + : this(globalSettings.SqlServer.ConnectionString, globalSettings.SqlServer.ReadOnlyConnectionString) + { } + + public ApiKeyRepository(string connectionString, string readOnlyConnectionString) + : base(connectionString, readOnlyConnectionString) + { } + + public async Task GetDetailsByIdAsync(Guid id) + { + using var connection = new SqlConnection(ConnectionString); + // When adding different key details, we should change the QueryAsync type to match the database data, + // but cast it to the appropriate data model. + var results = await connection.QueryAsync( + $"[{Schema}].[ApiKeyDetails_ReadById]", + new { Id = id }, + commandType: CommandType.StoredProcedure); + + return results.SingleOrDefault(); + } + + public async Task> GetManyByServiceAccountIdAsync(Guid serviceAccountId) + { + using var connection = new SqlConnection(ConnectionString); + var results = await connection.QueryAsync( + $"[{Schema}].[ApiKey_ReadByServiceAccountId]", + new { ServiceAccountId = serviceAccountId }, + commandType: CommandType.StoredProcedure); + + return results.ToList(); + } +} diff --git a/src/Infrastructure.EntityFramework/Configurations/AccessPolicyEntityTypeConfiguration.cs b/src/Infrastructure.EntityFramework/Configurations/AccessPolicyEntityTypeConfiguration.cs new file mode 100644 index 000000000..0a815dda6 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Configurations/AccessPolicyEntityTypeConfiguration.cs @@ -0,0 +1,99 @@ +using Bit.Infrastructure.EntityFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Bit.Infrastructure.EntityFramework.Configurations; + +public class AccessPolicyEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .HasDiscriminator("Discriminator") + .HasValue("user_project") + .HasValue("user_service_account") + .HasValue("group_project") + .HasValue("group_service_account") + .HasValue("service_account_project"); + + builder + .Property(s => s.Id) + .ValueGeneratedNever(); + + builder + .HasKey(s => s.Id) + .IsClustered(); + + builder.ToTable(nameof(AccessPolicy)); + } +} + +public class UserProjectAccessPolicyEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(e => e.OrganizationUserId) + .HasColumnName(nameof(UserProjectAccessPolicy.OrganizationUserId)); + + builder + .Property(e => e.GrantedProjectId) + .HasColumnName(nameof(UserProjectAccessPolicy.GrantedProjectId)); + } +} + +public class UserServiceAccountAccessPolicyEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(e => e.OrganizationUserId) + .HasColumnName(nameof(UserServiceAccountAccessPolicy.OrganizationUserId)); + + builder + .Property(e => e.GrantedServiceAccountId) + .HasColumnName(nameof(UserServiceAccountAccessPolicy.GrantedServiceAccountId)); + } +} + +public class GroupProjectAccessPolicyEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(e => e.GroupId) + .HasColumnName(nameof(GroupProjectAccessPolicy.GroupId)); + + builder + .Property(e => e.GrantedProjectId) + .HasColumnName(nameof(GroupProjectAccessPolicy.GrantedProjectId)); + } +} + +public class GroupServiceAccountAccessPolicyEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(e => e.GroupId) + .HasColumnName(nameof(GroupServiceAccountAccessPolicy.GroupId)); + + builder + .Property(e => e.GrantedServiceAccountId) + .HasColumnName(nameof(GroupServiceAccountAccessPolicy.GrantedServiceAccountId)); + } +} + +public class ServiceAccountProjectAccessPolicyEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(e => e.ServiceAccountId) + .HasColumnName(nameof(ServiceAccountProjectAccessPolicy.ServiceAccountId)); + + builder + .Property(e => e.GrantedProjectId) + .HasColumnName(nameof(ServiceAccountProjectAccessPolicy.GrantedProjectId)); + } +} diff --git a/src/Infrastructure.EntityFramework/Configurations/ApiKeyEntityTypeConfiguration.cs b/src/Infrastructure.EntityFramework/Configurations/ApiKeyEntityTypeConfiguration.cs new file mode 100644 index 000000000..c42e0d553 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Configurations/ApiKeyEntityTypeConfiguration.cs @@ -0,0 +1,25 @@ +using Bit.Infrastructure.EntityFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Bit.Infrastructure.EntityFramework.Configurations; + +public class ApiKeyEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(s => s.Id) + .ValueGeneratedNever(); + + builder + .HasKey(s => s.Id) + .IsClustered(); + + builder + .HasIndex(s => s.ServiceAccountId) + .IsClustered(false); + + builder.ToTable(nameof(ApiKey)); + } +} diff --git a/src/Infrastructure.EntityFramework/Configurations/ProjectEntityTypeConfiguration.cs b/src/Infrastructure.EntityFramework/Configurations/ProjectEntityTypeConfiguration.cs new file mode 100644 index 000000000..d8ed63e46 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Configurations/ProjectEntityTypeConfiguration.cs @@ -0,0 +1,29 @@ +using Bit.Infrastructure.EntityFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Bit.Infrastructure.EntityFramework.Configurations; + +public class ProjectEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(s => s.Id) + .ValueGeneratedNever(); + + builder + .HasKey(s => s.Id) + .IsClustered(); + + builder + .HasIndex(s => s.DeletedDate) + .IsClustered(false); + + builder + .HasIndex(s => s.OrganizationId) + .IsClustered(false); + + builder.ToTable(nameof(Project)); + } +} diff --git a/src/Infrastructure.EntityFramework/Configurations/SecretEntityTypeConfiguration.cs b/src/Infrastructure.EntityFramework/Configurations/SecretEntityTypeConfiguration.cs new file mode 100644 index 000000000..6c10dfc45 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Configurations/SecretEntityTypeConfiguration.cs @@ -0,0 +1,29 @@ +using Bit.Infrastructure.EntityFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +namespace Bit.Infrastructure.EntityFramework.Configurations; + +public class SecretEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(s => s.Id) + .ValueGeneratedNever(); + + builder + .HasKey(s => s.Id) + .IsClustered(); + + builder + .HasIndex(s => s.DeletedDate) + .IsClustered(false); + + builder + .HasIndex(s => s.OrganizationId) + .IsClustered(false); + + builder.ToTable(nameof(Secret)); + } +} diff --git a/src/Infrastructure.EntityFramework/Configurations/ServiceAccountEntityTypeConfiguration.cs b/src/Infrastructure.EntityFramework/Configurations/ServiceAccountEntityTypeConfiguration.cs new file mode 100644 index 000000000..11c3b8511 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Configurations/ServiceAccountEntityTypeConfiguration.cs @@ -0,0 +1,23 @@ +using Bit.Infrastructure.EntityFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +public class ServiceAccountEntityTypeConfiguration : IEntityTypeConfiguration +{ + public void Configure(EntityTypeBuilder builder) + { + builder + .Property(s => s.Id) + .ValueGeneratedNever(); + + builder + .HasKey(s => s.Id) + .IsClustered(); + + builder + .HasIndex(s => s.OrganizationId) + .IsClustered(false); + + builder.ToTable(nameof(ServiceAccount)); + } +} diff --git a/src/Infrastructure.EntityFramework/EfExtensions.cs b/src/Infrastructure.EntityFramework/EfExtensions.cs new file mode 100644 index 000000000..50cd700ed --- /dev/null +++ b/src/Infrastructure.EntityFramework/EfExtensions.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore; + +namespace Bit.Infrastructure.EntityFramework; + +public static class EfExtensions +{ + public static T AttachToOrGet(this DbContext context, Func predicate, Func factory) + where T : class, new() + { + var match = context.Set().Local.FirstOrDefault(predicate); + if (match == null) + { + match = factory(); + context.Attach(match); + } + + return match; + } +} diff --git a/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs b/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs index cd139ad10..d246ea9fc 100644 --- a/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs +++ b/src/Infrastructure.EntityFramework/EntityFrameworkServiceCollectionExtensions.cs @@ -5,18 +5,18 @@ using LinqToDB.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; -namespace Bit.Infrastructure.EntityFramework; - public static class EntityFrameworkServiceCollectionExtensions { - public static void AddEFRepositories(this IServiceCollection services, bool selfHosted, string connectionString, - SupportedDatabaseProviders provider) + public static void SetupEntityFramework(this IServiceCollection services, string connectionString, SupportedDatabaseProviders provider) { if (string.IsNullOrWhiteSpace(connectionString)) { throw new Exception($"Database provider type {provider} was selected but no connection string was found."); } + + // TODO: We should move away from using LINQ syntax for EF (TDL-48). LinqToDBForEFTools.Initialize(); + services.AddAutoMapper(typeof(UserRepository)); services.AddDbContext(options => { @@ -35,7 +35,17 @@ public static class EntityFrameworkServiceCollectionExtensions { options.UseSqlite(connectionString, b => b.MigrationsAssembly("SqliteMigrations")); } + else if (provider == SupportedDatabaseProviders.SqlServer) + { + options.UseSqlServer(connectionString); + } }); + } + + public static void AddPasswordManagerEFRepositories(this IServiceCollection services, bool selfHosted) + { + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -46,22 +56,21 @@ public static class EntityFrameworkServiceCollectionExtensions services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); if (selfHosted) { diff --git a/src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj b/src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj index 1baf19e84..5aaac6649 100644 --- a/src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj +++ b/src/Infrastructure.EntityFramework/Infrastructure.EntityFramework.csproj @@ -2,15 +2,15 @@ - + + - diff --git a/src/Infrastructure.EntityFramework/Models/AccessPolicy.cs b/src/Infrastructure.EntityFramework/Models/AccessPolicy.cs new file mode 100644 index 000000000..f69d95b38 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Models/AccessPolicy.cs @@ -0,0 +1,60 @@ +using AutoMapper; + +namespace Bit.Infrastructure.EntityFramework.Models; + +public class BaseAccessPolicy : Core.Entities.BaseAccessPolicy +{ + public string Discriminator { get; set; } +} + +public class AccessPolicyMapperProfile : Profile +{ + public AccessPolicyMapperProfile() + { + CreateMap().ReverseMap(); + } +} + +public class AccessPolicy : BaseAccessPolicy +{ +} + +public class UserProjectAccessPolicy : AccessPolicy +{ + public Guid? OrganizationUserId { get; set; } + public virtual OrganizationUser OrganizationUser { get; set; } + public Guid? GrantedProjectId { get; set; } + public virtual Project GrantedProject { get; set; } +} + +public class UserServiceAccountAccessPolicy : AccessPolicy +{ + public Guid? OrganizationUserId { get; set; } + public virtual OrganizationUser OrganizationUser { get; set; } + public Guid? GrantedServiceAccountId { get; set; } + public virtual ServiceAccount GrantedServiceAccount { get; set; } +} + +public class GroupProjectAccessPolicy : AccessPolicy +{ + public Guid? GroupId { get; set; } + public virtual Group Group { get; set; } + public Guid? GrantedProjectId { get; set; } + public virtual Project GrantedProject { get; set; } +} + +public class GroupServiceAccountAccessPolicy : AccessPolicy +{ + public Guid? GroupId { get; set; } + public virtual Group Group { get; set; } + public Guid? GrantedServiceAccountId { get; set; } + public virtual ServiceAccount GrantedServiceAccount { get; set; } +} + +public class ServiceAccountProjectAccessPolicy : AccessPolicy +{ + public Guid? ServiceAccountId { get; set; } + public virtual ServiceAccount ServiceAccount { get; set; } + public Guid? GrantedProjectId { get; set; } + public virtual Project GrantedProject { get; set; } +} diff --git a/src/Infrastructure.EntityFramework/Models/ApiKey.cs b/src/Infrastructure.EntityFramework/Models/ApiKey.cs new file mode 100644 index 000000000..0713bfb0d --- /dev/null +++ b/src/Infrastructure.EntityFramework/Models/ApiKey.cs @@ -0,0 +1,16 @@ +using AutoMapper; + +namespace Bit.Infrastructure.EntityFramework.Models; + +public class ApiKey : Core.Entities.ApiKey +{ + public virtual ServiceAccount ServiceAccount { get; set; } +} + +public class ApiKeyMapperProfile : Profile +{ + public ApiKeyMapperProfile() + { + CreateMap().ReverseMap(); + } +} diff --git a/src/Infrastructure.EntityFramework/Models/Project.cs b/src/Infrastructure.EntityFramework/Models/Project.cs new file mode 100644 index 000000000..47fc51c94 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Models/Project.cs @@ -0,0 +1,22 @@ +using AutoMapper; + +namespace Bit.Infrastructure.EntityFramework.Models; + +public class Project : Core.Entities.Project +{ + public virtual new ICollection Secrets { get; set; } + public virtual Organization Organization { get; set; } + public virtual ICollection GroupAccessPolicies { get; set; } + public virtual ICollection UserAccessPolicies { get; set; } + public virtual ICollection ServiceAccountAccessPolicies { get; set; } +} + +public class ProjectMapperProfile : Profile +{ + public ProjectMapperProfile() + { + CreateMap() + .PreserveReferences() + .ReverseMap(); + } +} diff --git a/src/Infrastructure.EntityFramework/Models/Secret.cs b/src/Infrastructure.EntityFramework/Models/Secret.cs new file mode 100644 index 000000000..7c6c6b697 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Models/Secret.cs @@ -0,0 +1,19 @@ +using AutoMapper; + +namespace Bit.Infrastructure.EntityFramework.Models; + +public class Secret : Core.Entities.Secret +{ + public virtual new ICollection Projects { get; set; } + public virtual Organization Organization { get; set; } +} + +public class SecretMapperProfile : Profile +{ + public SecretMapperProfile() + { + CreateMap() + .PreserveReferences() + .ReverseMap(); + } +} diff --git a/src/Infrastructure.EntityFramework/Models/ServiceAccount.cs b/src/Infrastructure.EntityFramework/Models/ServiceAccount.cs new file mode 100644 index 000000000..2b4992f52 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Models/ServiceAccount.cs @@ -0,0 +1,16 @@ +using AutoMapper; + +namespace Bit.Infrastructure.EntityFramework.Models; + +public class ServiceAccount : Core.Entities.ServiceAccount +{ + public virtual Organization Organization { get; set; } +} + +public class ServiceAccountMapperProfile : Profile +{ + public ServiceAccountMapperProfile() + { + CreateMap().ReverseMap(); + } +} diff --git a/src/Infrastructure.EntityFramework/Repositories/AccessPolicyRepository.cs b/src/Infrastructure.EntityFramework/Repositories/AccessPolicyRepository.cs new file mode 100644 index 000000000..a34c28426 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Repositories/AccessPolicyRepository.cs @@ -0,0 +1,27 @@ +using AutoMapper; +using Bit.Core.Repositories; +using Bit.Infrastructure.EntityFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using CoreAccessPolicy = Bit.Core.Entities.AccessPolicy; + +namespace Bit.Infrastructure.EntityFramework.Repositories; + +public class AccessPolicyRepository : IAccessPolicyRepository +{ + public AccessPolicyRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) + { + } + + protected Func> GetDbSet { get; private set; } + + public Task GetByIdAsync(Guid id) => throw new NotImplementedException(); + + public Task CreateAsync(CoreAccessPolicy obj) => throw new NotImplementedException(); + + public Task ReplaceAsync(CoreAccessPolicy obj) => throw new NotImplementedException(); + + public Task UpsertAsync(CoreAccessPolicy obj) => throw new NotImplementedException(); + + public Task DeleteAsync(CoreAccessPolicy obj) => throw new NotImplementedException(); +} diff --git a/src/Infrastructure.EntityFramework/Repositories/ApiKeyRepository.cs b/src/Infrastructure.EntityFramework/Repositories/ApiKeyRepository.cs new file mode 100644 index 000000000..df569e124 --- /dev/null +++ b/src/Infrastructure.EntityFramework/Repositories/ApiKeyRepository.cs @@ -0,0 +1,38 @@ +using AutoMapper; +using Bit.Core.Models.Data; +using Bit.Core.Repositories; +using Bit.Infrastructure.EntityFramework.Models; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace Bit.Infrastructure.EntityFramework.Repositories; + +public class ApiKeyRepository : Repository, IApiKeyRepository +{ + public ApiKeyRepository(IServiceScopeFactory serviceScopeFactory, IMapper mapper) + : base(serviceScopeFactory, mapper, (DatabaseContext context) => context.ApiKeys) + { + } + + public async Task GetDetailsByIdAsync(Guid id) + { + using var scope = ServiceScopeFactory.CreateScope(); + var dbContext = GetDatabaseContext(scope); + var entity = await GetDbSet(dbContext) + .Where(apiKey => apiKey.Id == id) + .Include(apiKey => apiKey.ServiceAccount) + .Select(apiKey => new ServiceAccountApiKeyDetails(apiKey, apiKey.ServiceAccount.OrganizationId)) + .FirstOrDefaultAsync(); + + return Mapper.Map(entity); + } + + public async Task> GetManyByServiceAccountIdAsync(Guid id) + { + using var scope = ServiceScopeFactory.CreateScope(); + var dbContext = GetDatabaseContext(scope); + var apiKeys = await GetDbSet(dbContext).Where(e => e.ServiceAccountId == id).ToListAsync(); + + return Mapper.Map>(apiKeys); + } +} diff --git a/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs b/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs index e6cb64ec9..c4a79d0a1 100644 --- a/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs +++ b/src/Infrastructure.EntityFramework/Repositories/DatabaseContext.cs @@ -12,6 +12,8 @@ public class DatabaseContext : DbContext : base(options) { } + public DbSet AccessPolicies { get; set; } + public DbSet ApiKeys { get; set; } public DbSet Ciphers { get; set; } public DbSet Collections { get; set; } public DbSet CollectionCiphers { get; set; } @@ -32,6 +34,9 @@ public class DatabaseContext : DbContext public DbSet OrganizationUsers { get; set; } public DbSet Policies { get; set; } public DbSet Providers { get; set; } + public DbSet Secret { get; set; } + public DbSet ServiceAccount { get; set; } + public DbSet Project { get; set; } public DbSet ProviderUsers { get; set; } public DbSet ProviderOrganizations { get; set; } public DbSet Sends { get; set; } @@ -44,6 +49,13 @@ public class DatabaseContext : DbContext protected override void OnModelCreating(ModelBuilder builder) { + // Scans and loads all configurations implementing the `IEntityTypeConfiguration` from the + // `Infrastructure.EntityFramework` Module. Note to get the assembly we can use a random class + // from this module. + builder.ApplyConfigurationsFromAssembly(typeof(DatabaseContext).Assembly); + + // Going forward use `IEntityTypeConfiguration` in the Configurations folder for managing + // Entity Framework code first database configurations. var eCipher = builder.Entity(); var eCollection = builder.Entity(); var eCollectionCipher = builder.Entity(); @@ -101,7 +113,6 @@ public class DatabaseContext : DbContext eGrant.HasKey(x => x.Key); eGroupUser.HasKey(gu => new { gu.GroupId, gu.OrganizationUserId }); - if (Database.IsNpgsql()) { // the postgres provider doesn't currently support database level non-deterministic collations. diff --git a/src/Infrastructure.EntityFramework/packages.lock.json b/src/Infrastructure.EntityFramework/packages.lock.json index 48d900aa7..16b6228a1 100644 --- a/src/Infrastructure.EntityFramework/packages.lock.json +++ b/src/Infrastructure.EntityFramework/packages.lock.json @@ -42,6 +42,16 @@ "SQLitePCLRaw.bundle_e_sqlite3": "2.1.2" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Direct", + "requested": "[6.0.12, )", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Npgsql.EntityFrameworkCore.PostgreSQL": { "type": "Direct", "requested": "[6.0.8, )", diff --git a/src/Notifications/Startup.cs b/src/Notifications/Startup.cs index 14f88f7b2..2468e078b 100644 --- a/src/Notifications/Startup.cs +++ b/src/Notifications/Startup.cs @@ -1,4 +1,5 @@ using System.Globalization; +using Bit.Core.IdentityServer; using Bit.Core.Settings; using Bit.Core.Utilities; using Bit.SharedWeb.Utilities; @@ -35,12 +36,12 @@ public class Startup { policy.RequireAuthenticatedUser(); policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application", "external"); - policy.RequireClaim(JwtClaimTypes.Scope, "api"); + policy.RequireClaim(JwtClaimTypes.Scope, ApiScopes.Api); }); config.AddPolicy("Internal", policy => { policy.RequireAuthenticatedUser(); - policy.RequireClaim(JwtClaimTypes.Scope, "internal"); + policy.RequireClaim(JwtClaimTypes.Scope, ApiScopes.Internal); }); }); diff --git a/src/Notifications/packages.lock.json b/src/Notifications/packages.lock.json index 617430e25..6367bddc9 100644 --- a/src/Notifications/packages.lock.json +++ b/src/Notifications/packages.lock.json @@ -597,6 +597,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2804,6 +2813,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs index e2d05050d..9d7220101 100644 --- a/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs +++ b/src/SharedWeb/Utilities/ServiceCollectionExtensions.cs @@ -17,7 +17,6 @@ using Bit.Core.Settings; using Bit.Core.Tokens; using Bit.Core.Utilities; using Bit.Infrastructure.Dapper; -using Bit.Infrastructure.EntityFramework; using IdentityModel; using IdentityServer4.AccessTokenValidation; using IdentityServer4.Configuration; @@ -52,6 +51,7 @@ public static class ServiceCollectionExtensions var selectedDatabaseProvider = globalSettings.DatabaseProvider; var provider = SupportedDatabaseProviders.SqlServer; var connectionString = string.Empty; + if (!string.IsNullOrWhiteSpace(selectedDatabaseProvider)) { switch (selectedDatabaseProvider.ToLowerInvariant()) @@ -70,16 +70,24 @@ public static class ServiceCollectionExtensions provider = SupportedDatabaseProviders.Sqlite; connectionString = globalSettings.Sqlite.ConnectionString; break; + case "sqlserver": + connectionString = globalSettings.SqlServer.ConnectionString; + break; default: break; } } - - var useEf = (provider != SupportedDatabaseProviders.SqlServer); - - if (useEf) + else { - services.AddEFRepositories(globalSettings.SelfHosted, connectionString, provider); + // Default to attempting to use SqlServer connection string if globalSettings.DatabaseProvider has no value. + connectionString = globalSettings.SqlServer.ConnectionString; + } + + services.SetupEntityFramework(connectionString, provider); + + if (provider != SupportedDatabaseProviders.SqlServer) + { + services.AddPasswordManagerEFRepositories(globalSettings.SelfHosted); } else { @@ -337,9 +345,9 @@ public static class ServiceCollectionExtensions }; options.ClaimsIdentity = new ClaimsIdentityOptions { - SecurityStampClaimType = "sstamp", + SecurityStampClaimType = Claims.SecurityStamp, UserNameClaimType = JwtClaimTypes.Email, - UserIdClaimType = JwtClaimTypes.Subject + UserIdClaimType = JwtClaimTypes.Subject, }; options.Tokens.ChangeEmailTokenProvider = TokenOptions.DefaultEmailProvider; }); @@ -623,7 +631,7 @@ public static class ServiceCollectionExtensions services.AddSingleton( _ => ConnectionMultiplexer.Connect(globalSettings.Redis.ConnectionString)); - // Explicitly register IDistributedCache to re-use existing IConnectionMultiplexer + // Explicitly register IDistributedCache to re-use existing IConnectionMultiplexer // to reduce the number of redundant connections to the Redis instance services.AddSingleton(s => { diff --git a/src/SharedWeb/packages.lock.json b/src/SharedWeb/packages.lock.json index 5d2824e43..fbe49984b 100644 --- a/src/SharedWeb/packages.lock.json +++ b/src/SharedWeb/packages.lock.json @@ -539,6 +539,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2754,6 +2763,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index 99f09ccbf..36bbbaeb6 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -73,6 +73,9 @@ + + + @@ -350,6 +353,8 @@ + + @@ -370,10 +375,14 @@ + + + + @@ -385,6 +394,8 @@ + + diff --git a/src/Sql/dbo/Stored Procedures/ApiKey/ApiKeyDetails_ReadById.sql b/src/Sql/dbo/Stored Procedures/ApiKey/ApiKeyDetails_ReadById.sql new file mode 100644 index 000000000..62b09d49e --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/ApiKey/ApiKeyDetails_ReadById.sql @@ -0,0 +1,13 @@ +CREATE PROCEDURE [dbo].[ApiKeyDetails_ReadById] + @Id UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + * + FROM + [dbo].[ApiKeyDetailsView] + WHERE + [Id] = @Id +END diff --git a/src/Sql/dbo/Stored Procedures/ApiKey/ApiKey_Create.sql b/src/Sql/dbo/Stored Procedures/ApiKey/ApiKey_Create.sql new file mode 100644 index 000000000..57d983a43 --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/ApiKey/ApiKey_Create.sql @@ -0,0 +1,42 @@ +CREATE PROCEDURE [dbo].[ApiKey_Create] + @Id UNIQUEIDENTIFIER OUTPUT, + @ServiceAccountId UNIQUEIDENTIFIER, + @Name VARCHAR(200), + @ClientSecret VARCHAR(30), + @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], + [ClientSecret], + [Scope], + [EncryptedPayload], + [Key], + [ExpireAt], + [CreationDate], + [RevisionDate] + ) + VALUES + ( + @Id, + @ServiceAccountId, + @Name, + @ClientSecret, + @Scope, + @EncryptedPayload, + @Key, + @ExpireAt, + @CreationDate, + @RevisionDate + ) +END diff --git a/src/Sql/dbo/Stored Procedures/ApiKey/ApiKey_ReadByServiceAccountId.sql b/src/Sql/dbo/Stored Procedures/ApiKey/ApiKey_ReadByServiceAccountId.sql new file mode 100644 index 000000000..75a94bc3a --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/ApiKey/ApiKey_ReadByServiceAccountId.sql @@ -0,0 +1,13 @@ +CREATE PROCEDURE [dbo].[ApiKey_ReadByServiceAccountId] + @ServiceAccountId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + * + FROM + [dbo].[ApiKeyView] + WHERE + [ServiceAccountId] = @ServiceAccountId +END diff --git a/src/Sql/dbo/Stored Procedures/OrganizationUser_DeleteById.sql b/src/Sql/dbo/Stored Procedures/OrganizationUser_DeleteById.sql index 9b7f8187e..d706bd4d7 100644 --- a/src/Sql/dbo/Stored Procedures/OrganizationUser_DeleteById.sql +++ b/src/Sql/dbo/Stored Procedures/OrganizationUser_DeleteById.sql @@ -3,9 +3,9 @@ AS BEGIN SET NOCOUNT ON - + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationUserId] @Id - + DECLARE @OrganizationId UNIQUEIDENTIFIER DECLARE @UserId UNIQUEIDENTIFIER @@ -34,6 +34,12 @@ BEGIN WHERE [OrganizationUserId] = @Id + DELETE + FROM + [dbo].[AccessPolicy] + WHERE + [OrganizationUserId] = @Id + EXEC [dbo].[OrganizationSponsorship_OrganizationUserDeleted] @Id DELETE diff --git a/src/Sql/dbo/Stored Procedures/Organization_Create.sql b/src/Sql/dbo/Stored Procedures/Organization_Create.sql index 1d9b02f9b..2cf67d10d 100644 --- a/src/Sql/dbo/Stored Procedures/Organization_Create.sql +++ b/src/Sql/dbo/Stored Procedures/Organization_Create.sql @@ -42,7 +42,8 @@ @MaxAutoscaleSeats INT, @UseKeyConnector BIT = 0, @UseScim BIT = 0, - @UseCustomPermissions BIT = 0 + @UseCustomPermissions BIT = 0, + @UseSecretsManager BIT = 0 AS BEGIN SET NOCOUNT ON @@ -92,7 +93,8 @@ BEGIN [MaxAutoscaleSeats], [UseKeyConnector], [UseScim], - [UseCustomPermissions] + [UseCustomPermissions], + [UseSecretsManager] ) VALUES ( @@ -139,6 +141,7 @@ BEGIN @MaxAutoscaleSeats, @UseKeyConnector, @UseScim, - @UseCustomPermissions + @UseCustomPermissions, + @UseSecretsManager ) END \ No newline at end of file diff --git a/src/Sql/dbo/Stored Procedures/Organization_DeleteById.sql b/src/Sql/dbo/Stored Procedures/Organization_DeleteById.sql index ab5217a12..c54a08c02 100644 --- a/src/Sql/dbo/Stored Procedures/Organization_DeleteById.sql +++ b/src/Sql/dbo/Stored Procedures/Organization_DeleteById.sql @@ -61,6 +61,32 @@ BEGIN EXEC [dbo].[OrganizationConnection_OrganizationDeleted] @Id EXEC [dbo].[OrganizationSponsorship_OrganizationDeleted] @Id + DELETE + FROM + [dbo].[Project] + WHERE + [OrganizationId] = @Id + + DELETE + FROM + [dbo].[Secret] + WHERE + [OrganizationId] = @Id + + DELETE AK + FROM + [dbo].[ApiKey] AK + INNER JOIN + [dbo].[ServiceAccount] SA ON [AK].[ServiceAccountId] = [SA].[Id] + WHERE + [SA].[OrganizationId] = @Id + + DELETE + FROM + [dbo].[ServiceAccount] + WHERE + [OrganizationId] = @Id + DELETE FROM [dbo].[Organization] diff --git a/src/Sql/dbo/Stored Procedures/Organization_Update.sql b/src/Sql/dbo/Stored Procedures/Organization_Update.sql index 4e65fc91a..2b754d1cb 100644 --- a/src/Sql/dbo/Stored Procedures/Organization_Update.sql +++ b/src/Sql/dbo/Stored Procedures/Organization_Update.sql @@ -42,7 +42,8 @@ @MaxAutoscaleSeats INT, @UseKeyConnector BIT = 0, @UseScim BIT = 0, - @UseCustomPermissions BIT = 0 + @UseCustomPermissions BIT = 0, + @UseSecretsManager BIT = 0 AS BEGIN SET NOCOUNT ON @@ -92,7 +93,8 @@ BEGIN [MaxAutoscaleSeats] = @MaxAutoscaleSeats, [UseKeyConnector] = @UseKeyConnector, [UseScim] = @UseScim, - [UseCustomPermissions] = @UseCustomPermissions + [UseCustomPermissions] = @UseCustomPermissions, + [UseSecretsManager] = @UseSecretsManager WHERE [Id] = @Id END diff --git a/src/Sql/dbo/Stored Procedures/User_DeleteById.sql b/src/Sql/dbo/Stored Procedures/User_DeleteById.sql index 726b7cb58..ce32f2f24 100644 --- a/src/Sql/dbo/Stored Procedures/User_DeleteById.sql +++ b/src/Sql/dbo/Stored Procedures/User_DeleteById.sql @@ -58,6 +58,16 @@ BEGIN WHERE OU.[UserId] = @Id + -- Delete AccessPolicy + DELETE + AP + FROM + [dbo].[AccessPolicy] AP + INNER JOIN + [dbo].[OrganizationUser] OU ON OU.[Id] = AP.[OrganizationUserId] + WHERE + [UserId] = @Id + -- Delete organization users DELETE FROM diff --git a/src/Sql/dbo/Tables/AccessPolicy.sql b/src/Sql/dbo/Tables/AccessPolicy.sql new file mode 100644 index 000000000..e31ea249e --- /dev/null +++ b/src/Sql/dbo/Tables/AccessPolicy.sql @@ -0,0 +1,34 @@ +CREATE TABLE [AccessPolicy] ( + [Id] UNIQUEIDENTIFIER NOT NULL, + [Discriminator] NVARCHAR(50) NOT NULL, + [OrganizationUserId] UNIQUEIDENTIFIER NULL, + [GroupId] UNIQUEIDENTIFIER NULL, + [ServiceAccountId] UNIQUEIDENTIFIER NULL, + [GrantedProjectId] UNIQUEIDENTIFIER NULL, + [GrantedServiceAccountId] UNIQUEIDENTIFIER NULL, + [Read] BIT NOT NULL, + [Write] BIT NOT NULL, + [CreationDate] DATETIME2 NOT NULL, + [RevisionDate] DATETIME2 NOT NULL, + CONSTRAINT [PK_AccessPolicy] PRIMARY KEY CLUSTERED ([Id]), + CONSTRAINT [FK_AccessPolicy_Group_GroupId] FOREIGN KEY ([GroupId]) REFERENCES [Group] ([Id]) ON DELETE CASCADE, + CONSTRAINT [FK_AccessPolicy_OrganizationUser_OrganizationUserId] FOREIGN KEY ([OrganizationUserId]) REFERENCES [OrganizationUser] ([Id]), + CONSTRAINT [FK_AccessPolicy_Project_GrantedProjectId] FOREIGN KEY ([GrantedProjectId]) REFERENCES [Project] ([Id]) ON DELETE CASCADE, + CONSTRAINT [FK_AccessPolicy_ServiceAccount_GrantedServiceAccountId] FOREIGN KEY ([GrantedServiceAccountId]) REFERENCES [ServiceAccount] ([Id]), + CONSTRAINT [FK_AccessPolicy_ServiceAccount_ServiceAccountId] FOREIGN KEY ([ServiceAccountId]) REFERENCES [ServiceAccount] ([Id]) +); + +GO +CREATE NONCLUSTERED INDEX [IX_AccessPolicy_GroupId] ON [AccessPolicy] ([GroupId]); + +GO +CREATE NONCLUSTERED INDEX [IX_AccessPolicy_OrganizationUserId] ON [AccessPolicy] ([OrganizationUserId]); + +GO +CREATE NONCLUSTERED INDEX [IX_AccessPolicy_GrantedProjectId] ON [AccessPolicy] ([GrantedProjectId]); + +GO +CREATE NONCLUSTERED INDEX [IX_AccessPolicy_ServiceAccountId] ON [AccessPolicy] ([ServiceAccountId]); + +GO +CREATE NONCLUSTERED INDEX [IX_AccessPolicy_GrantedServiceAccountId] ON [AccessPolicy] ([GrantedServiceAccountId]); diff --git a/src/Sql/dbo/Tables/ApiKey.sql b/src/Sql/dbo/Tables/ApiKey.sql new file mode 100644 index 000000000..506da9c10 --- /dev/null +++ b/src/Sql/dbo/Tables/ApiKey.sql @@ -0,0 +1,18 @@ +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, + 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/src/Sql/dbo/Tables/Organization.sql b/src/Sql/dbo/Tables/Organization.sql index 77a99a1f4..87b1c2ff2 100644 --- a/src/Sql/dbo/Tables/Organization.sql +++ b/src/Sql/dbo/Tables/Organization.sql @@ -43,6 +43,7 @@ [UseKeyConnector] BIT NOT NULL, [UseScim] BIT NOT NULL CONSTRAINT [DF_Organization_UseScim] DEFAULT (0), [UseCustomPermissions] BIT NOT NULL CONSTRAINT [DF_Organization_UseCustomPermissions] DEFAULT (0), + [UseSecretsManager] BIT NOT NULL CONSTRAINT [DF_Organization_UseSecretsManager] DEFAULT (0), CONSTRAINT [PK_Organization] PRIMARY KEY CLUSTERED ([Id] ASC) ); diff --git a/src/Sql/dbo/Tables/Project.sql b/src/Sql/dbo/Tables/Project.sql new file mode 100644 index 000000000..fe1663947 --- /dev/null +++ b/src/Sql/dbo/Tables/Project.sql @@ -0,0 +1,16 @@ +CREATE TABLE [dbo].[Project] ( + [Id] UNIQUEIDENTIFIER NOT NULL, + [OrganizationId] UNIQUEIDENTIFIER NOT NULL, + [Name] NVARCHAR(MAX) NULL, + [CreationDate] DATETIME2 (7), + [RevisionDate] DATETIME2 (7), + [DeletedDate] DATETIME2 (7) NULL, + CONSTRAINT [PK_Project] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_Project_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) +); + +GO +CREATE NONCLUSTERED INDEX [IX_Project_OrganizationId] ON [dbo].[Project] ([OrganizationId] ASC); + +GO +CREATE NONCLUSTERED INDEX [IX_Project_DeletedDate] ON [dbo].[Project] ([DeletedDate] ASC); diff --git a/src/Sql/dbo/Tables/ProjectSecret.sql b/src/Sql/dbo/Tables/ProjectSecret.sql new file mode 100644 index 000000000..6162dc728 --- /dev/null +++ b/src/Sql/dbo/Tables/ProjectSecret.sql @@ -0,0 +1,10 @@ +CREATE TABLE [dbo].[ProjectSecret] ( + [ProjectsId] uniqueidentifier NOT NULL, + [SecretsId] uniqueidentifier NOT NULL, + CONSTRAINT [PK_ProjectSecret] PRIMARY KEY ([ProjectsId], [SecretsId]), + CONSTRAINT [FK_ProjectSecret_Project_ProjectsId] FOREIGN KEY ([ProjectsId]) REFERENCES [Project] ([Id]) ON DELETE CASCADE, + CONSTRAINT [FK_ProjectSecret_Secret_SecretsId] FOREIGN KEY ([SecretsId]) REFERENCES [Secret] ([Id]) ON DELETE CASCADE +); + +GO +CREATE NONCLUSTERED INDEX [IX_ProjectSecret_SecretsId] ON [ProjectSecret] ([SecretsId]); diff --git a/src/Sql/dbo/Tables/Secret.sql b/src/Sql/dbo/Tables/Secret.sql new file mode 100644 index 000000000..52d5e1d44 --- /dev/null +++ b/src/Sql/dbo/Tables/Secret.sql @@ -0,0 +1,19 @@ +CREATE TABLE [dbo].[Secret] +( + [Id] UNIQUEIDENTIFIER NOT NULL, + [OrganizationId] UNIQUEIDENTIFIER NOT NULL, + [Key] NVARCHAR(MAX) NULL, + [Value] NVARCHAR(MAX) NULL, + [Note] NVARCHAR(MAX) NULL, + [CreationDate] DATETIME2(7) NOT NULL, + [RevisionDate] DATETIME2(7) NOT NULL, + [DeletedDate] DATETIME2(7) NULL, + CONSTRAINT [PK_Secret] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_Secret_OrganizationId] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization]([Id]) +); + +GO +CREATE NONCLUSTERED INDEX [IX_Secret_OrganizationId] ON [dbo].[Secret] ([OrganizationId] ASC); + +GO +CREATE NONCLUSTERED INDEX [IX_Secret_DeletedDate] ON [dbo].[Secret] ([DeletedDate] ASC); diff --git a/src/Sql/dbo/Tables/ServiceAccount.sql b/src/Sql/dbo/Tables/ServiceAccount.sql new file mode 100644 index 000000000..e48059250 --- /dev/null +++ b/src/Sql/dbo/Tables/ServiceAccount.sql @@ -0,0 +1,13 @@ +CREATE TABLE [dbo].[ServiceAccount] +( + [Id] UNIQUEIDENTIFIER NOT NULL, + [OrganizationId] UNIQUEIDENTIFIER NOT NULL, + [Name] NVARCHAR(MAX) NULL, + [CreationDate] DATETIME2(7) NOT NULL, + [RevisionDate] DATETIME2(7) NOT NULL, + CONSTRAINT [PK_ServiceAccount] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_ServiceAccount_OrganizationId] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization]([Id]) +); + +GO +CREATE NONCLUSTERED INDEX [IX_ServiceAccount_OrganizationId] ON [dbo].[ServiceAccount] ([OrganizationId] ASC); diff --git a/src/Sql/dbo/Views/ApiKeyDetailsView.sql b/src/Sql/dbo/Views/ApiKeyDetailsView.sql new file mode 100644 index 000000000..dd3555929 --- /dev/null +++ b/src/Sql/dbo/Views/ApiKeyDetailsView.sql @@ -0,0 +1,9 @@ +CREATE VIEW [dbo].[ApiKeyDetailsView] +AS +SELECT + AK.*, + SA.[OrganizationId] ServiceAccountOrganizationId +FROM + [dbo].[ApiKey] AS AK +LEFT JOIN + [dbo].[ServiceAccount] SA ON SA.[Id] = AK.[ServiceAccountId] diff --git a/src/Sql/dbo/Views/ApiKeyView.sql b/src/Sql/dbo/Views/ApiKeyView.sql new file mode 100644 index 000000000..8f1228da1 --- /dev/null +++ b/src/Sql/dbo/Views/ApiKeyView.sql @@ -0,0 +1,6 @@ +CREATE VIEW [dbo].[ApiKeyView] +AS +SELECT + * +FROM + [dbo].[ApiKey] diff --git a/src/Sql/dbo/Views/OrganizationUserOrganizationDetailsView.sql b/src/Sql/dbo/Views/OrganizationUserOrganizationDetailsView.sql index 7130005ed..5c93a181b 100644 --- a/src/Sql/dbo/Views/OrganizationUserOrganizationDetailsView.sql +++ b/src/Sql/dbo/Views/OrganizationUserOrganizationDetailsView.sql @@ -20,6 +20,7 @@ SELECT O.[SelfHost], O.[UsersGetPremium], O.[UseCustomPermissions], + O.[UseSecretsManager], O.[Seats], O.[MaxCollections], O.[MaxStorageGb], diff --git a/test/Api.IntegrationTest/Controllers/AccountsControllerTests.cs b/test/Api.IntegrationTest/Controllers/AccountsControllerTest.cs similarity index 100% rename from test/Api.IntegrationTest/Controllers/AccountsControllerTests.cs rename to test/Api.IntegrationTest/Controllers/AccountsControllerTest.cs diff --git a/test/Api.IntegrationTest/Controllers/ProjectsControllerTest.cs b/test/Api.IntegrationTest/Controllers/ProjectsControllerTest.cs new file mode 100644 index 000000000..67da80278 --- /dev/null +++ b/test/Api.IntegrationTest/Controllers/ProjectsControllerTest.cs @@ -0,0 +1,181 @@ +using System.Net.Http.Headers; +using System.Text.Json; +using Bit.Api.IntegrationTest.Factories; +using Bit.Api.IntegrationTest.Helpers; +using Bit.Api.SecretManagerFeatures.Models.Request; +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Test.Common.Helpers; +using Xunit; + +namespace Bit.Api.IntegrationTest.Controllers; + +public class ProjectsControllerTest : IClassFixture, IAsyncLifetime +{ + private readonly string _mockEncryptedString = + "2.3Uk+WNBIoU5xzmVFNcoWzz==|1MsPIYuRfdOHfu/0uY6H2Q==|/98sp4wb6pHP1VTZ9JcNCYgQjEUMFPlqJgCwRk1YXKg="; + + private readonly HttpClient _client; + private readonly ApiApplicationFactory _factory; + private readonly IProjectRepository _projectRepository; + private Organization _organization = null!; + + public ProjectsControllerTest(ApiApplicationFactory factory) + { + _factory = factory; + _client = _factory.CreateClient(); + _projectRepository = _factory.GetService(); + } + + public async Task InitializeAsync() + { + var ownerEmail = $"integration-test{Guid.NewGuid()}@bitwarden.com"; + var tokens = await _factory.LoginWithNewAccount(ownerEmail); + var (organization, _) = await OrganizationTestHelpers.SignUpAsync(_factory, ownerEmail: ownerEmail, billingEmail: ownerEmail); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokens.Token); + _organization = organization; + } + + public Task DisposeAsync() + { + _client.Dispose(); + return Task.CompletedTask; + } + + [Fact] + public async Task CreateProject() + { + var request = new ProjectCreateRequestModel() + { + Name = _mockEncryptedString + }; + + var response = await _client.PostAsJsonAsync($"/organizations/{_organization.Id}/projects", request); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + + Assert.NotNull(result); + Assert.Equal(request.Name, result!.Name); + AssertHelper.AssertRecent(result.RevisionDate); + AssertHelper.AssertRecent(result.CreationDate); + Assert.Null(result.DeletedDate); + + var createdProject = await _projectRepository.GetByIdAsync(result.Id); + Assert.NotNull(result); + Assert.Equal(request.Name, createdProject.Name); + AssertHelper.AssertRecent(createdProject.RevisionDate); + AssertHelper.AssertRecent(createdProject.CreationDate); + Assert.Null(createdProject.DeletedDate); + } + + [Fact] + public async Task UpdateProject() + { + var initialProject = await _projectRepository.CreateAsync(new Project + { + OrganizationId = _organization.Id, + Name = _mockEncryptedString + }); + + var mockEncryptedString2 = "2.3Uk+WNBIoU5xzmVFNcoWzz==|1MsPIYuRfdOHfu/0uY6H2Q==|/98xy4wb6pHP1VTZ9JcNCYgQjEUMFPlqJgCwRk1YXKg="; + + var request = new ProjectUpdateRequestModel() + { + Name = mockEncryptedString2 + }; + + var response = await _client.PutAsJsonAsync($"/projects/{initialProject.Id}", request); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + Assert.NotEqual(initialProject.Name, result!.Name); + AssertHelper.AssertRecent(result.RevisionDate); + Assert.NotEqual(initialProject.RevisionDate, result.RevisionDate); + Assert.Null(result.DeletedDate); + + var updatedProject = await _projectRepository.GetByIdAsync(result.Id); + Assert.NotNull(result); + Assert.Equal(request.Name, updatedProject.Name); + AssertHelper.AssertRecent(updatedProject.RevisionDate); + AssertHelper.AssertRecent(updatedProject.CreationDate); + Assert.Null(updatedProject.DeletedDate); + Assert.NotEqual(initialProject.Name, updatedProject.Name); + Assert.NotEqual(initialProject.RevisionDate, updatedProject.RevisionDate); + } + + [Fact] + public async Task GetProject() + { + var createdProject = await _projectRepository.CreateAsync(new Project + { + OrganizationId = _organization.Id, + Name = _mockEncryptedString + }); + + var response = await _client.GetAsync($"/projects/{createdProject.Id}"); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + Assert.Equal(createdProject.Name, result!.Name); + Assert.Equal(createdProject.RevisionDate, result.RevisionDate); + Assert.Equal(createdProject.CreationDate, result.CreationDate); + Assert.Null(result.DeletedDate); + } + + [Fact] + public async Task GetProjectsByOrganization() + { + var projectsToCreate = 3; + var projectIds = new List(); + for (var i = 0; i < projectsToCreate; i++) + { + var project = await _projectRepository.CreateAsync(new Project + { + OrganizationId = _organization.Id, + Name = _mockEncryptedString + }); + projectIds.Add(project.Id); + } + + var response = await _client.GetAsync($"/organizations/{_organization.Id}/projects"); + response.EnsureSuccessStatusCode(); + var content = await response.Content.ReadAsStringAsync(); + + var jsonResult = JsonDocument.Parse(content); + + Assert.NotEmpty(jsonResult.RootElement.GetProperty("data").EnumerateArray()); + Assert.Equal(projectIds.Count(), jsonResult.RootElement.GetProperty("data").EnumerateArray().Count()); + } + + [Fact] + public async Task DeleteProjects() + { + var projectsToDelete = 3; + var projectIds = new List(); + for (var i = 0; i < projectsToDelete; i++) + { + var project = await _projectRepository.CreateAsync(new Project + { + OrganizationId = _organization.Id, + Name = _mockEncryptedString, + }); + projectIds.Add(project.Id); + } + + var response = await _client.PostAsync("/projects/delete", JsonContent.Create(projectIds)); + response.EnsureSuccessStatusCode(); + + var content = await response.Content.ReadAsStringAsync(); + Assert.NotEmpty(content); + + var jsonResult = JsonDocument.Parse(content); + var index = 0; + foreach (var element in jsonResult.RootElement.GetProperty("data").EnumerateArray()) + { + Assert.Equal(projectIds[index].ToString(), element.GetProperty("id").ToString()); + Assert.Empty(element.GetProperty("error").ToString()); + index++; + } + + var projects = await _projectRepository.GetManyByIds(projectIds); + Assert.Empty(projects); + } +} diff --git a/test/Api.IntegrationTest/Controllers/SecretsControllerTest.cs b/test/Api.IntegrationTest/Controllers/SecretsControllerTest.cs new file mode 100644 index 000000000..ee4b44ce8 --- /dev/null +++ b/test/Api.IntegrationTest/Controllers/SecretsControllerTest.cs @@ -0,0 +1,237 @@ +using System.Net.Http.Headers; +using System.Text.Json; +using Bit.Api.IntegrationTest.Factories; +using Bit.Api.IntegrationTest.Helpers; +using Bit.Api.SecretManagerFeatures.Models.Request; +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Test.Common.Helpers; +using Xunit; + +namespace Bit.Api.IntegrationTest.Controllers; + +public class SecretsControllerTest : IClassFixture, IAsyncLifetime +{ + private readonly string _mockEncryptedString = + "2.3Uk+WNBIoU5xzmVFNcoWzz==|1MsPIYuRfdOHfu/0uY6H2Q==|/98sp4wb6pHP1VTZ9JcNCYgQjEUMFPlqJgCwRk1YXKg="; + + private readonly HttpClient _client; + private readonly ApiApplicationFactory _factory; + private readonly ISecretRepository _secretRepository; + private readonly IProjectRepository _projectRepository; + private Organization _organization = null!; + + public SecretsControllerTest(ApiApplicationFactory factory) + { + _factory = factory; + _client = _factory.CreateClient(); + _secretRepository = _factory.GetService(); + _projectRepository = _factory.GetService(); + } + + public async Task InitializeAsync() + { + var ownerEmail = $"integration-test{Guid.NewGuid()}@bitwarden.com"; + var tokens = await _factory.LoginWithNewAccount(ownerEmail); + var (organization, _) = await OrganizationTestHelpers.SignUpAsync(_factory, ownerEmail: ownerEmail, billingEmail: ownerEmail); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokens.Token); + _organization = organization; + } + + public Task DisposeAsync() + { + return Task.CompletedTask; + } + + [Fact] + public async Task CreateSecret() + { + var request = new SecretCreateRequestModel() + { + Key = _mockEncryptedString, + Value = _mockEncryptedString, + Note = _mockEncryptedString + }; + + var response = await _client.PostAsJsonAsync($"/organizations/{_organization.Id}/secrets", request); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + + Assert.NotNull(result); + Assert.Equal(request.Key, result!.Key); + Assert.Equal(request.Value, result.Value); + Assert.Equal(request.Note, result.Note); + AssertHelper.AssertRecent(result.RevisionDate); + AssertHelper.AssertRecent(result.CreationDate); + Assert.Null(result.DeletedDate); + + var createdSecret = await _secretRepository.GetByIdAsync(result.Id); + Assert.NotNull(result); + Assert.Equal(request.Key, createdSecret.Key); + Assert.Equal(request.Value, createdSecret.Value); + Assert.Equal(request.Note, createdSecret.Note); + AssertHelper.AssertRecent(createdSecret.RevisionDate); + AssertHelper.AssertRecent(createdSecret.CreationDate); + Assert.Null(createdSecret.DeletedDate); + } + + [Fact] + public async Task CreateSecretWithProject() + { + var project = await _projectRepository.CreateAsync(new Project() + { + Id = new Guid(), + OrganizationId = _organization.Id, + Name = _mockEncryptedString + }); + var projectIds = new[] { project.Id }; + var secretRequest = new SecretCreateRequestModel() + { + Key = _mockEncryptedString, + Value = _mockEncryptedString, + Note = _mockEncryptedString, + ProjectIds = projectIds, + }; + var secretResponse = await _client.PostAsJsonAsync($"/organizations/{_organization.Id}/secrets", secretRequest); + secretResponse.EnsureSuccessStatusCode(); + var secretResult = await secretResponse.Content.ReadFromJsonAsync(); + + var secret = (await _secretRepository.GetManyByProjectIdAsync(project.Id)).First(); + + Assert.NotNull(secretResult); + Assert.Equal(secret.Id, secretResult!.Id); + Assert.Equal(secret.OrganizationId, secretResult.OrganizationId); + Assert.Equal(secret.Key, secretResult.Key); + Assert.Equal(secret.Value, secretResult.Value); + Assert.Equal(secret.Note, secretResult.Note); + Assert.Equal(secret.CreationDate, secretResult.CreationDate); + Assert.Equal(secret.RevisionDate, secretResult.RevisionDate); + } + + [Fact] + public async Task UpdateSecret() + { + var initialSecret = await _secretRepository.CreateAsync(new Secret + { + OrganizationId = _organization.Id, + Key = _mockEncryptedString, + Value = _mockEncryptedString, + Note = _mockEncryptedString + }); + + var request = new SecretUpdateRequestModel() + { + Key = _mockEncryptedString, + Value = "2.3Uk+WNBIoU5xzmVFNcoWzz==|1MsPIYuRfdOHfu/0uY6H2Q==|/98xy4wb6pHP1VTZ9JcNCYgQjEUMFPlqJgCwRk1YXKg=", + Note = _mockEncryptedString + }; + + var response = await _client.PutAsJsonAsync($"/secrets/{initialSecret.Id}", request); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + Assert.Equal(request.Key, result!.Key); + Assert.Equal(request.Value, result.Value); + Assert.NotEqual(initialSecret.Value, result.Value); + Assert.Equal(request.Note, result.Note); + AssertHelper.AssertRecent(result.RevisionDate); + Assert.NotEqual(initialSecret.RevisionDate, result.RevisionDate); + Assert.Null(result.DeletedDate); + + var updatedSecret = await _secretRepository.GetByIdAsync(result.Id); + Assert.NotNull(result); + Assert.Equal(request.Key, updatedSecret.Key); + Assert.Equal(request.Value, updatedSecret.Value); + Assert.Equal(request.Note, updatedSecret.Note); + AssertHelper.AssertRecent(updatedSecret.RevisionDate); + AssertHelper.AssertRecent(updatedSecret.CreationDate); + Assert.Null(updatedSecret.DeletedDate); + Assert.NotEqual(initialSecret.Value, updatedSecret.Value); + Assert.NotEqual(initialSecret.RevisionDate, updatedSecret.RevisionDate); + } + + [Fact] + public async Task DeleteSecrets() + { + var secretsToDelete = 3; + var secretIds = new List(); + for (var i = 0; i < secretsToDelete; i++) + { + var secret = await _secretRepository.CreateAsync(new Secret + { + OrganizationId = _organization.Id, + Key = _mockEncryptedString, + Value = _mockEncryptedString, + Note = _mockEncryptedString + }); + secretIds.Add(secret.Id); + } + + var response = await _client.PostAsync("/secrets/delete", JsonContent.Create(secretIds)); + response.EnsureSuccessStatusCode(); + + var content = await response.Content.ReadAsStringAsync(); + Assert.NotEmpty(content); + + var jsonResult = JsonDocument.Parse(content); + var index = 0; + foreach (var element in jsonResult.RootElement.GetProperty("data").EnumerateArray()) + { + Assert.Equal(secretIds[index].ToString(), element.GetProperty("id").ToString()); + Assert.Empty(element.GetProperty("error").ToString()); + index++; + } + + var secrets = await _secretRepository.GetManyByIds(secretIds); + Assert.Empty(secrets); + } + + [Fact] + public async Task GetSecret() + { + var createdSecret = await _secretRepository.CreateAsync(new Secret + { + OrganizationId = _organization.Id, + Key = _mockEncryptedString, + Value = _mockEncryptedString, + Note = _mockEncryptedString + }); + + + var response = await _client.GetAsync($"/secrets/{createdSecret.Id}"); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + Assert.Equal(createdSecret.Key, result!.Key); + Assert.Equal(createdSecret.Value, result.Value); + Assert.Equal(createdSecret.Note, result.Note); + Assert.Equal(createdSecret.RevisionDate, result.RevisionDate); + Assert.Equal(createdSecret.CreationDate, result.CreationDate); + Assert.Null(result.DeletedDate); + } + + [Fact] + public async Task GetSecretsByOrganization() + { + var secretsToCreate = 3; + var secretIds = new List(); + for (var i = 0; i < secretsToCreate; i++) + { + var secret = await _secretRepository.CreateAsync(new Secret + { + OrganizationId = _organization.Id, + Key = _mockEncryptedString, + Value = _mockEncryptedString, + Note = _mockEncryptedString + }); + secretIds.Add(secret.Id); + } + + var response = await _client.GetAsync($"/organizations/{_organization.Id}/secrets"); + response.EnsureSuccessStatusCode(); + var content = await response.Content.ReadAsStringAsync(); + + var jsonResult = JsonDocument.Parse(content); + + Assert.NotEmpty(jsonResult.RootElement.GetProperty("secrets").EnumerateArray()); + Assert.Equal(secretIds.Count(), jsonResult.RootElement.GetProperty("secrets").EnumerateArray().Count()); + } +} diff --git a/test/Api.IntegrationTest/Controllers/ServiceAccountsControllerTests.cs b/test/Api.IntegrationTest/Controllers/ServiceAccountsControllerTests.cs new file mode 100644 index 000000000..1b997feee --- /dev/null +++ b/test/Api.IntegrationTest/Controllers/ServiceAccountsControllerTests.cs @@ -0,0 +1,183 @@ +using System.Net.Http.Headers; +using System.Text.Json; +using Bit.Api.IntegrationTest.Factories; +using Bit.Api.IntegrationTest.Helpers; +using Bit.Api.SecretManagerFeatures.Models.Request; +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Test.Common.Helpers; +using Xunit; + +namespace Bit.Api.IntegrationTest.Controllers; + +public class ServiceAccountsControllerTest : IClassFixture, IAsyncLifetime +{ + private readonly string _mockEncryptedString = + "2.3Uk+WNBIoU5xzmVFNcoWzz==|1MsPIYuRfdOHfu/0uY6H2Q==|/98sp4wb6pHP1VTZ9JcNCYgQjEUMFPlqJgCwRk1YXKg="; + + private readonly HttpClient _client; + private readonly ApiApplicationFactory _factory; + private readonly IServiceAccountRepository _serviceAccountRepository; + private Organization _organization = null!; + + public ServiceAccountsControllerTest(ApiApplicationFactory factory) + { + _factory = factory; + _client = _factory.CreateClient(); + _serviceAccountRepository = _factory.GetService(); + } + + public async Task InitializeAsync() + { + var ownerEmail = $"integration-test{Guid.NewGuid()}@bitwarden.com"; + var tokens = await _factory.LoginWithNewAccount(ownerEmail); + var (organization, _) = await OrganizationTestHelpers.SignUpAsync(_factory, ownerEmail: ownerEmail, billingEmail: ownerEmail); + _client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", tokens.Token); + _organization = organization; + } + + public Task DisposeAsync() + { + return Task.CompletedTask; + } + + [Fact] + public async Task GetServiceAccountsByOrganization() + { + var serviceAccountsToCreate = 3; + var serviceAccountIds = new List(); + for (var i = 0; i < serviceAccountsToCreate; i++) + { + var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount + { + OrganizationId = _organization.Id, + Name = _mockEncryptedString, + }); + serviceAccountIds.Add(serviceAccount.Id); + } + + var response = await _client.GetAsync($"/organizations/{_organization.Id}/service-accounts"); + response.EnsureSuccessStatusCode(); + var content = await response.Content.ReadAsStringAsync(); + + var jsonResult = JsonDocument.Parse(content); + + Assert.NotEmpty(jsonResult.RootElement.GetProperty("data").EnumerateArray()); + Assert.Equal(serviceAccountIds.Count(), jsonResult.RootElement.GetProperty("data").EnumerateArray().Count()); + } + + [Fact] + public async Task CreateServiceAccount() + { + var request = new ServiceAccountCreateRequestModel() + { + Name = _mockEncryptedString, + }; + + var response = await _client.PostAsJsonAsync($"/organizations/{_organization.Id}/service-accounts", request); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + + Assert.NotNull(result); + Assert.Equal(request.Name, result!.Name); + AssertHelper.AssertRecent(result.RevisionDate); + AssertHelper.AssertRecent(result.CreationDate); + + var createdServiceAccount = await _serviceAccountRepository.GetByIdAsync(result.Id); + Assert.NotNull(result); + Assert.Equal(request.Name, createdServiceAccount.Name); + AssertHelper.AssertRecent(createdServiceAccount.RevisionDate); + AssertHelper.AssertRecent(createdServiceAccount.CreationDate); + } + + [Fact] + public async Task UpdateServiceAccount() + { + var initialServiceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount + { + OrganizationId = _organization.Id, + Name = _mockEncryptedString, + }); + + var request = new ServiceAccountUpdateRequestModel() + { + Name = "2.3Uk+WNBIoU5xzmVFNcoWzz==|1MsPIYuRfdOHfu/0uY6H2Q==|/98xy4wb6pHP1VTZ9JcNCYgQjEUMFPlqJgCwRk1YXKg=", + }; + + var response = await _client.PutAsJsonAsync($"/service-accounts/{initialServiceAccount.Id}", request); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + Assert.NotNull(result); + Assert.Equal(request.Name, result!.Name); + Assert.NotEqual(initialServiceAccount.Name, result.Name); + AssertHelper.AssertRecent(result.RevisionDate); + Assert.NotEqual(initialServiceAccount.RevisionDate, result.RevisionDate); + + var updatedServiceAccount = await _serviceAccountRepository.GetByIdAsync(initialServiceAccount.Id); + Assert.NotNull(result); + Assert.Equal(request.Name, updatedServiceAccount.Name); + AssertHelper.AssertRecent(updatedServiceAccount.RevisionDate); + AssertHelper.AssertRecent(updatedServiceAccount.CreationDate); + Assert.NotEqual(initialServiceAccount.Name, updatedServiceAccount.Name); + Assert.NotEqual(initialServiceAccount.RevisionDate, updatedServiceAccount.RevisionDate); + } + + [Fact] + public async Task CreateServiceAccountAccessToken() + { + var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount + { + OrganizationId = _organization.Id, + Name = _mockEncryptedString, + }); + + var mockExpiresAt = DateTime.UtcNow.AddDays(30); + var request = new AccessTokenCreateRequestModel() + { + Name = _mockEncryptedString, + EncryptedPayload = _mockEncryptedString, + Key = _mockEncryptedString, + ExpireAt = mockExpiresAt + }; + + var response = await _client.PostAsJsonAsync($"/service-accounts/{serviceAccount.Id}/access-tokens", request); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + + Assert.NotNull(result); + Assert.Equal(request.Name, result!.Name); + Assert.NotNull(result.ClientSecret); + Assert.Equal(mockExpiresAt, result.ExpireAt); + AssertHelper.AssertRecent(result.RevisionDate); + AssertHelper.AssertRecent(result.CreationDate); + } + + [Fact] + public async Task CreateServiceAccountAccessTokenExpireAtNullAsync() + { + var serviceAccount = await _serviceAccountRepository.CreateAsync(new ServiceAccount + { + OrganizationId = _organization.Id, + Name = _mockEncryptedString, + }); + + var request = new AccessTokenCreateRequestModel() + { + Name = _mockEncryptedString, + EncryptedPayload = _mockEncryptedString, + Key = _mockEncryptedString, + ExpireAt = null + }; + + var response = await _client.PostAsJsonAsync($"/service-accounts/{serviceAccount.Id}/access-tokens", request); + response.EnsureSuccessStatusCode(); + var result = await response.Content.ReadFromJsonAsync(); + + Assert.NotNull(result); + Assert.Equal(request.Name, result!.Name); + Assert.NotNull(result.ClientSecret); + Assert.Null(result.ExpireAt); + AssertHelper.AssertRecent(result.RevisionDate); + AssertHelper.AssertRecent(result.CreationDate); + } +} diff --git a/test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs b/test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs index 693e53083..94f5568f4 100644 --- a/test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs +++ b/test/Api.IntegrationTest/Factories/ApiApplicationFactory.cs @@ -12,6 +12,7 @@ public class ApiApplicationFactory : WebApplicationFactoryBase public ApiApplicationFactory() { _identityApplicationFactory = new IdentityApplicationFactory(); + _identityApplicationFactory.DatabaseName = DatabaseName; } protected override void ConfigureWebHost(IWebHostBuilder builder) @@ -20,6 +21,10 @@ public class ApiApplicationFactory : WebApplicationFactoryBase builder.ConfigureTestServices(services => { + // Remove scheduled background jobs to prevent errors in parallel test execution + var jobService = services.First(sd => sd.ServiceType == typeof(Microsoft.Extensions.Hosting.IHostedService) && sd.ImplementationType == typeof(Bit.Api.Jobs.JobsHostedService)); + services.Remove(jobService); + services.PostConfigure(IdentityServerAuthenticationDefaults.AuthenticationScheme, options => { options.JwtBackChannelHandler = _identityApplicationFactory.Server.CreateHandler(); diff --git a/test/Api.IntegrationTest/Helpers/OrganizationTestHelpers.cs b/test/Api.IntegrationTest/Helpers/OrganizationTestHelpers.cs new file mode 100644 index 000000000..ac2317cf4 --- /dev/null +++ b/test/Api.IntegrationTest/Helpers/OrganizationTestHelpers.cs @@ -0,0 +1,33 @@ +using Bit.Core.Entities; +using Bit.Core.Enums; +using Bit.Core.Models.Business; +using Bit.Core.Repositories; +using Bit.Core.Services; +using Bit.IntegrationTestCommon.Factories; + +namespace Bit.Api.IntegrationTest.Helpers; + +public static class OrganizationTestHelpers +{ + public static async Task> SignUpAsync(WebApplicationFactoryBase factory, + PlanType plan = PlanType.Free, + string ownerEmail = "integration-test@bitwarden.com", + string name = "Integration Test Org", + string billingEmail = "integration-test@bitwarden.com", + string ownerKey = "test-key") where T : class + { + var userRepository = factory.GetService(); + var organizationService = factory.GetService(); + + var owner = await userRepository.GetByEmailAsync(ownerEmail); + + return await organizationService.SignUpAsync(new OrganizationSignup + { + Name = name, + BillingEmail = billingEmail, + Plan = plan, + OwnerKey = ownerKey, + Owner = owner, + }); + } +} diff --git a/test/Api.IntegrationTest/packages.lock.json b/test/Api.IntegrationTest/packages.lock.json index c5f57fcfb..973b8a57b 100644 --- a/test/Api.IntegrationTest/packages.lock.json +++ b/test/Api.IntegrationTest/packages.lock.json @@ -674,6 +674,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.ApiDescription.Server": { "type": "Transitive", "resolved": "3.0.0", @@ -3132,6 +3141,7 @@ "dependencies": { "Azure.Messaging.EventGrid": "[4.10.0, )", "Commercial.Core": "[2022.12.0, )", + "Commercial.Infrastructure.EntityFramework": "[2022.12.0, )", "Core": "[2022.12.0, )", "SharedWeb": "[2022.12.0, )", "Swashbuckle.AspNetCore": "[6.3.1, )" @@ -3143,6 +3153,14 @@ "Core": "[2022.12.0, )" } }, + "commercial.infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2022.12.0, )", + "Infrastructure.EntityFramework": "[2022.12.0, )" + } + }, "common": { "type": "Project", "dependencies": { @@ -3216,6 +3234,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/test/Api.Test/Api.Test.csproj b/test/Api.Test/Api.Test.csproj index 344c66333..564e90c22 100644 --- a/test/Api.Test/Api.Test.csproj +++ b/test/Api.Test/Api.Test.csproj @@ -23,6 +23,7 @@ + diff --git a/test/Api.Test/Controllers/ProjectsControllerTests.cs b/test/Api.Test/Controllers/ProjectsControllerTests.cs new file mode 100644 index 000000000..f81713704 --- /dev/null +++ b/test/Api.Test/Controllers/ProjectsControllerTests.cs @@ -0,0 +1,42 @@ +using Bit.Api.Controllers; +using Bit.Core.Entities; +using Bit.Core.SecretManagerFeatures.Projects.Interfaces; +using Bit.Core.Test.AutoFixture.ProjectsFixture; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using NSubstitute; +using Xunit; + +namespace Bit.Api.Test.Controllers; + +[ControllerCustomize(typeof(ProjectsController))] +[SutProviderCustomize] +[ProjectCustomize] +[JsonDocumentCustomize] +public class ProjectsControllerTests +{ + [Theory] + [BitAutoData] + public async void BulkDeleteProjects_Success(SutProvider sutProvider, List data) + { + var ids = data.Select(project => project.Id).ToList(); + var mockResult = new List>(); + foreach (var project in data) + { + mockResult.Add(new Tuple(project, "")); + } + sutProvider.GetDependency().DeleteProjects(ids).ReturnsForAnyArgs(mockResult); + + var results = await sutProvider.Sut.BulkDeleteProjectsAsync(ids); + await sutProvider.GetDependency().Received(1) + .DeleteProjects(Arg.Is(ids)); + Assert.Equal(data.Count, results.Data.Count()); + } + + [Theory] + [BitAutoData] + public async void BulkDeleteProjects_NoGuids_ThrowsArgumentNullException(SutProvider sutProvider) + { + await Assert.ThrowsAsync(() => sutProvider.Sut.BulkDeleteProjectsAsync(new List())); + } +} diff --git a/test/Api.Test/Controllers/SecretsControllerTests.cs b/test/Api.Test/Controllers/SecretsControllerTests.cs new file mode 100644 index 000000000..49a4f937c --- /dev/null +++ b/test/Api.Test/Controllers/SecretsControllerTests.cs @@ -0,0 +1,114 @@ +using Bit.Api.Controllers; +using Bit.Api.SecretManagerFeatures.Models.Request; +using Bit.Core.Entities; +using Bit.Core.Exceptions; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.Secrets.Interfaces; +using Bit.Core.Test.AutoFixture.SecretsFixture; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Api.Test.Controllers; + +[ControllerCustomize(typeof(SecretsController))] +[SutProviderCustomize] +[JsonDocumentCustomize] +[SecretCustomize] +public class SecretsControllerTests +{ + [Theory] + [BitAutoData] + public async void GetSecretsByOrganization_ReturnsEmptyList(SutProvider sutProvider, Guid id) + { + var result = await sutProvider.Sut.GetSecretsByOrganizationAsync(id); + + await sutProvider.GetDependency().Received(1) + .GetManyByOrganizationIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); + + Assert.Empty(result.Secrets); + } + + [Theory] + [BitAutoData] + public async void GetSecret_NotFound(SutProvider sutProvider) + { + await Assert.ThrowsAsync(() => sutProvider.Sut.GetSecretAsync(Guid.NewGuid())); + } + + [Theory] + [BitAutoData] + public async void GetSecret_Success(SutProvider sutProvider, Secret resultSecret) + { + sutProvider.GetDependency().GetByIdAsync(default).ReturnsForAnyArgs(resultSecret); + + var result = await sutProvider.Sut.GetSecretAsync(resultSecret.Id); + + await sutProvider.GetDependency().Received(1) + .GetByIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(resultSecret.Id))); + } + + [Theory] + [BitAutoData] + public async void GetSecretsByOrganization_Success(SutProvider sutProvider, Secret resultSecret) + { + sutProvider.GetDependency().GetManyByOrganizationIdAsync(default).ReturnsForAnyArgs(new List() { resultSecret }); + + var result = await sutProvider.Sut.GetSecretsByOrganizationAsync(resultSecret.OrganizationId); + + await sutProvider.GetDependency().Received(1) + .GetManyByOrganizationIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(resultSecret.OrganizationId))); + } + + [Theory] + [BitAutoData] + public async void CreateSecret_Success(SutProvider sutProvider, SecretCreateRequestModel data, Guid organizationId) + { + var resultSecret = data.ToSecret(organizationId); + + sutProvider.GetDependency().CreateAsync(default).ReturnsForAnyArgs(resultSecret); + + var result = await sutProvider.Sut.CreateSecretAsync(organizationId, data); + await sutProvider.GetDependency().Received(1) + .CreateAsync(Arg.Any()); + } + + [Theory] + [BitAutoData] + public async void UpdateSecret_Success(SutProvider sutProvider, SecretUpdateRequestModel data, Guid secretId) + { + var resultSecret = data.ToSecret(secretId); + sutProvider.GetDependency().UpdateAsync(default).ReturnsForAnyArgs(resultSecret); + + var result = await sutProvider.Sut.UpdateSecretAsync(secretId, data); + await sutProvider.GetDependency().Received(1) + .UpdateAsync(Arg.Any()); + } + + [Theory] + [BitAutoData] + public async void BulkDeleteSecret_Success(SutProvider sutProvider, List data) + { + 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).ReturnsForAnyArgs(mockResult); + + var results = await sutProvider.Sut.BulkDeleteAsync(ids); + await sutProvider.GetDependency().Received(1) + .DeleteSecrets(Arg.Is(ids)); + Assert.Equal(data.Count, results.Data.Count()); + } + + [Theory] + [BitAutoData] + public async void BulkDeleteSecret_NoGuids_ThrowsArgumentNullException(SutProvider sutProvider) + { + await Assert.ThrowsAsync(() => sutProvider.Sut.BulkDeleteAsync(new List())); + } +} diff --git a/test/Api.Test/Controllers/ServiceAccountsControllerTests.cs b/test/Api.Test/Controllers/ServiceAccountsControllerTests.cs new file mode 100644 index 000000000..720088e9a --- /dev/null +++ b/test/Api.Test/Controllers/ServiceAccountsControllerTests.cs @@ -0,0 +1,82 @@ +using Bit.Api.Controllers; +using Bit.Api.SecretManagerFeatures.Models.Request; +using Bit.Core.Entities; +using Bit.Core.Repositories; +using Bit.Core.SecretManagerFeatures.AccessTokens.Interfaces; +using Bit.Core.SecretManagerFeatures.ServiceAccounts.Interfaces; +using Bit.Test.Common.AutoFixture; +using Bit.Test.Common.AutoFixture.Attributes; +using Bit.Test.Common.Helpers; +using NSubstitute; +using Xunit; + +namespace Bit.Api.Test.Controllers; + +[ControllerCustomize(typeof(ServiceAccountsController))] +[SutProviderCustomize] +[JsonDocumentCustomize] +public class ServiceAccountsControllerTests +{ + [Theory] + [BitAutoData] + public async void GetServiceAccountsByOrganization_ReturnsEmptyList(SutProvider sutProvider, Guid id) + { + var result = await sutProvider.Sut.GetServiceAccountsByOrganizationAsync(id); + + await sutProvider.GetDependency().Received(1) + .GetManyByOrganizationIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(id))); + + Assert.Empty(result.Data); + } + + [Theory] + [BitAutoData] + public async void GetServiceAccountsByOrganization_Success(SutProvider sutProvider, ServiceAccount resultServiceAccount) + { + sutProvider.GetDependency().GetManyByOrganizationIdAsync(default).ReturnsForAnyArgs(new List() { resultServiceAccount }); + + var result = await sutProvider.Sut.GetServiceAccountsByOrganizationAsync(resultServiceAccount.OrganizationId); + + await sutProvider.GetDependency().Received(1) + .GetManyByOrganizationIdAsync(Arg.Is(AssertHelper.AssertPropertyEqual(resultServiceAccount.OrganizationId))); + } + + + [Theory] + [BitAutoData] + public async void CreateServiceAccount_Success(SutProvider sutProvider, ServiceAccountCreateRequestModel data, Guid organizationId) + { + var resultServiceAccount = data.ToServiceAccount(organizationId); + + sutProvider.GetDependency().CreateAsync(default).ReturnsForAnyArgs(resultServiceAccount); + + var result = await sutProvider.Sut.CreateServiceAccountAsync(organizationId, data); + await sutProvider.GetDependency().Received(1) + .CreateAsync(Arg.Any()); + } + + [Theory] + [BitAutoData] + public async void UpdateServiceAccount_Success(SutProvider sutProvider, ServiceAccountUpdateRequestModel data, Guid serviceAccountId) + { + var resultServiceAccount = data.ToServiceAccount(serviceAccountId); + sutProvider.GetDependency().UpdateAsync(default).ReturnsForAnyArgs(resultServiceAccount); + + var result = await sutProvider.Sut.UpdateServiceAccountAsync(serviceAccountId, data); + await sutProvider.GetDependency().Received(1) + .UpdateAsync(Arg.Any()); + } + + [Theory] + [BitAutoData] + public async void CreateAccessToken_Success(SutProvider sutProvider, AccessTokenCreateRequestModel data, Guid serviceAccountId) + { + var resultAccessToken = data.ToApiKey(serviceAccountId); + + sutProvider.GetDependency().CreateAsync(default).ReturnsForAnyArgs(resultAccessToken); + + var result = await sutProvider.Sut.CreateAccessTokenAsync(serviceAccountId, data); + await sutProvider.GetDependency().Received(1) + .CreateAsync(Arg.Any()); + } +} diff --git a/test/Api.Test/packages.lock.json b/test/Api.Test/packages.lock.json index dbb86ea18..2f40c3688 100644 --- a/test/Api.Test/packages.lock.json +++ b/test/Api.Test/packages.lock.json @@ -658,6 +658,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.ApiDescription.Server": { "type": "Transitive", "resolved": "3.0.0", @@ -1053,6 +1062,15 @@ "System.Security.Cryptography.Pkcs": "6.0.0" } }, + "Moq": { + "type": "Transitive", + "resolved": "4.17.2", + "contentHash": "HytUPJ3/uks2UgJ9hIcyXm3YxpFAR4OJzbQwTHltbKGun3lFLhEHs97hiiPj1dY8jV/kasXeihTzDxct6Zf3iQ==", + "dependencies": { + "Castle.Core": "4.4.1", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, "MySqlConnector": { "type": "Transitive", "resolved": "2.1.2", @@ -3002,6 +3020,7 @@ "dependencies": { "Azure.Messaging.EventGrid": "[4.10.0, )", "Commercial.Core": "[2022.12.0, )", + "Commercial.Infrastructure.EntityFramework": "[2022.12.0, )", "Core": "[2022.12.0, )", "SharedWeb": "[2022.12.0, )", "Swashbuckle.AspNetCore": "[6.3.1, )" @@ -3013,6 +3032,14 @@ "Core": "[2022.12.0, )" } }, + "commercial.infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2022.12.0, )", + "Infrastructure.EntityFramework": "[2022.12.0, )" + } + }, "common": { "type": "Project", "dependencies": { @@ -3065,6 +3092,20 @@ "YubicoDotNetClient": "[1.2.0, )" } }, + "core.test": { + "type": "Project", + "dependencies": { + "AutoFixture.AutoNSubstitute": "[4.17.0, )", + "AutoFixture.Xunit2": "[4.17.0, )", + "Common": "[2022.12.0, )", + "Core": "[2022.12.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": { @@ -3078,6 +3119,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/test/Billing.Test/packages.lock.json b/test/Billing.Test/packages.lock.json index a9d77a735..3ce017296 100644 --- a/test/Billing.Test/packages.lock.json +++ b/test/Billing.Test/packages.lock.json @@ -893,6 +893,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3526,6 +3535,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/test/Core.Test/AutoFixture/ProjectFixtures.cs b/test/Core.Test/AutoFixture/ProjectFixtures.cs new file mode 100644 index 000000000..7ab92fa47 --- /dev/null +++ b/test/Core.Test/AutoFixture/ProjectFixtures.cs @@ -0,0 +1,22 @@ +using AutoFixture; +using Bit.Core.Entities; +using Bit.Test.Common.AutoFixture.Attributes; + +namespace Bit.Core.Test.AutoFixture.ProjectsFixture; + +public class ProjectCustomization : ICustomization +{ + public void Customize(IFixture fixture) + { + var projectId = Guid.NewGuid(); + + fixture.Customize(composer => composer + .With(p => p.Id, projectId) + .Without(s => s.Secrets)); + } +} + +public class ProjectCustomizeAttribute : BitCustomizeAttribute +{ + public override ICustomization GetCustomization() => new ProjectCustomization(); +} diff --git a/test/Core.Test/AutoFixture/SecretFixtures.cs b/test/Core.Test/AutoFixture/SecretFixtures.cs new file mode 100644 index 000000000..16838986b --- /dev/null +++ b/test/Core.Test/AutoFixture/SecretFixtures.cs @@ -0,0 +1,22 @@ +using AutoFixture; +using Bit.Core.Entities; +using Bit.Test.Common.AutoFixture.Attributes; + +namespace Bit.Core.Test.AutoFixture.SecretsFixture; + +public class SecretCustomization : ICustomization +{ + public void Customize(IFixture fixture) + { + var secretId = Guid.NewGuid(); + + fixture.Customize(composer => composer + .With(o => o.Id, secretId) + .Without(s => s.Projects)); + } +} + +public class SecretCustomizeAttribute : BitCustomizeAttribute +{ + public override ICustomization GetCustomization() => new SecretCustomization(); +} diff --git a/test/Icons.Test/packages.lock.json b/test/Icons.Test/packages.lock.json index 7b30efdda..74073e4f6 100644 --- a/test/Icons.Test/packages.lock.json +++ b/test/Icons.Test/packages.lock.json @@ -612,6 +612,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2947,6 +2956,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/test/Identity.IntegrationTest/openid-configuration.json b/test/Identity.IntegrationTest/openid-configuration.json index 3ff8a5d7a..1e95c93db 100644 --- a/test/Identity.IntegrationTest/openid-configuration.json +++ b/test/Identity.IntegrationTest/openid-configuration.json @@ -11,6 +11,7 @@ "api.organization", "api.installation", "internal", + "api.secrets", "offline_access" ], "claims_supported": [ @@ -27,7 +28,8 @@ "orgcustom", "providerprovideradmin", "providerserviceuser", - "sub" + "sub", + "organization" ], "grant_types_supported": [ "authorization_code", diff --git a/test/Identity.IntegrationTest/packages.lock.json b/test/Identity.IntegrationTest/packages.lock.json index 4633093b5..7a92e69c7 100644 --- a/test/Identity.IntegrationTest/packages.lock.json +++ b/test/Identity.IntegrationTest/packages.lock.json @@ -675,6 +675,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3172,6 +3181,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/test/Identity.Test/packages.lock.json b/test/Identity.Test/packages.lock.json index bb4800147..3d43d6efb 100644 --- a/test/Identity.Test/packages.lock.json +++ b/test/Identity.Test/packages.lock.json @@ -648,6 +648,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3039,6 +3048,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/test/Infrastructure.EFIntegration.Test/Repositories/CipherRepositoryTests.cs b/test/Infrastructure.EFIntegration.Test/Repositories/CipherRepositoryTests.cs index 2e5bf69cc..91832c313 100644 --- a/test/Infrastructure.EFIntegration.Test/Repositories/CipherRepositoryTests.cs +++ b/test/Infrastructure.EFIntegration.Test/Repositories/CipherRepositoryTests.cs @@ -24,20 +24,20 @@ public class CipherRepositoryTests } [CiSkippedTheory, EfUserCipherCustomize, BitAutoData] - public void UserCipher_CreateAsync_Works_DataMatches(Cipher cipher, User user, Organization org, + public Task UserCipher_CreateAsync_Works_DataMatches(Cipher cipher, User user, Organization org, CipherCompare equalityComparer, List suts, List efUserRepos, List efOrgRepos, SqlRepo.CipherRepository sqlCipherRepo, SqlRepo.UserRepository sqlUserRepo, SqlRepo.OrganizationRepository sqlOrgRepo) => CreateAsync_Works_DataMatches( cipher, user, org, equalityComparer, suts, efUserRepos, efOrgRepos, sqlCipherRepo, sqlUserRepo, sqlOrgRepo); [CiSkippedTheory, EfOrganizationCipherCustomize, BitAutoData] - public void OrganizationCipher_CreateAsync_Works_DataMatches(Cipher cipher, User user, Organization org, + public Task OrganizationCipher_CreateAsync_Works_DataMatches(Cipher cipher, User user, Organization org, CipherCompare equalityComparer, List suts, List efUserRepos, List efOrgRepos, SqlRepo.CipherRepository sqlCipherRepo, SqlRepo.UserRepository sqlUserRepo, SqlRepo.OrganizationRepository sqlOrgRepo) => CreateAsync_Works_DataMatches( cipher, user, org, equalityComparer, suts, efUserRepos, efOrgRepos, sqlCipherRepo, sqlUserRepo, sqlOrgRepo); - private async void CreateAsync_Works_DataMatches(Cipher cipher, User user, Organization org, + private async Task CreateAsync_Works_DataMatches(Cipher cipher, User user, Organization org, CipherCompare equalityComparer, List suts, List efUserRepos, List efOrgRepos, SqlRepo.CipherRepository sqlCipherRepo, SqlRepo.UserRepository sqlUserRepo, SqlRepo.OrganizationRepository sqlOrgRepo) @@ -184,7 +184,11 @@ public class CipherRepositoryTests List suts, List efUserRepos, List efOrgRepos - ) => DeleteAsync_CipherIsDeleted(cipher, user, org, suts, efUserRepos, efOrgRepos); + ) + { + DeleteAsync_CipherIsDeleted(cipher, user, org, suts, efUserRepos, efOrgRepos); + return Task.CompletedTask; + } private async Task DeleteAsync_CipherIsDeleted( Cipher cipher, diff --git a/test/Infrastructure.EFIntegration.Test/packages.lock.json b/test/Infrastructure.EFIntegration.Test/packages.lock.json index a2c60ec6e..24f94ef90 100644 --- a/test/Infrastructure.EFIntegration.Test/packages.lock.json +++ b/test/Infrastructure.EFIntegration.Test/packages.lock.json @@ -659,6 +659,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3035,6 +3044,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/test/Infrastructure.IntegrationTest/DatabaseDataAttribute.cs b/test/Infrastructure.IntegrationTest/DatabaseDataAttribute.cs index 8710ba309..0f47a0e69 100644 --- a/test/Infrastructure.IntegrationTest/DatabaseDataAttribute.cs +++ b/test/Infrastructure.IntegrationTest/DatabaseDataAttribute.cs @@ -2,7 +2,6 @@ using Bit.Core.Enums; using Bit.Core.Settings; using Bit.Infrastructure.Dapper; -using Bit.Infrastructure.EntityFramework; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -67,7 +66,8 @@ public class DatabaseDataAttribute : DataAttribute { var efPostgresCollection = new ServiceCollection(); efPostgresCollection.AddLogging(configureLogging); - efPostgresCollection.AddEFRepositories(SelfHosted, efPostgresConnectionString, SupportedDatabaseProviders.Postgres); + efPostgresCollection.SetupEntityFramework(efPostgresConnectionString, SupportedDatabaseProviders.Postgres); + efPostgresCollection.AddPasswordManagerEFRepositories(SelfHosted); efPostgresCollection.AddTransient(); yield return efPostgresCollection.BuildServiceProvider(); } @@ -76,7 +76,8 @@ public class DatabaseDataAttribute : DataAttribute { var efMySqlCollection = new ServiceCollection(); efMySqlCollection.AddLogging(configureLogging); - efMySqlCollection.AddEFRepositories(SelfHosted, efMySqlConnectionString, SupportedDatabaseProviders.MySql); + efMySqlCollection.SetupEntityFramework(efMySqlConnectionString, SupportedDatabaseProviders.MySql); + efMySqlCollection.AddPasswordManagerEFRepositories(SelfHosted); efMySqlCollection.AddTransient(); yield return efMySqlCollection.BuildServiceProvider(); } diff --git a/test/Infrastructure.IntegrationTest/packages.lock.json b/test/Infrastructure.IntegrationTest/packages.lock.json index bbd253bca..7d651d9d3 100644 --- a/test/Infrastructure.IntegrationTest/packages.lock.json +++ b/test/Infrastructure.IntegrationTest/packages.lock.json @@ -616,6 +616,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2869,6 +2878,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/test/IntegrationTestCommon/Factories/WebApplicationFactoryBase.cs b/test/IntegrationTestCommon/Factories/WebApplicationFactoryBase.cs index 45ad410ee..9c32a46e7 100644 --- a/test/IntegrationTestCommon/Factories/WebApplicationFactoryBase.cs +++ b/test/IntegrationTestCommon/Factories/WebApplicationFactoryBase.cs @@ -26,7 +26,7 @@ public abstract class WebApplicationFactoryBase : WebApplicationFactory /// /// This will need to be set BEFORE using the Server property /// - public string DatabaseName { get; set; } = FactoryConstants.DefaultDatabaseName; + public string DatabaseName { get; set; } = Guid.NewGuid().ToString(); /// /// Configure the web host to use an EF in memory database @@ -115,4 +115,10 @@ public abstract class WebApplicationFactoryBase : WebApplicationFactory var scope = Services.CreateScope(); return scope.ServiceProvider.GetRequiredService(); } + + public T GetService() + { + var scope = Services.CreateScope(); + return scope.ServiceProvider.GetRequiredService(); + } } diff --git a/test/IntegrationTestCommon/packages.lock.json b/test/IntegrationTestCommon/packages.lock.json index dcda8d8b9..66b6c7eda 100644 --- a/test/IntegrationTestCommon/packages.lock.json +++ b/test/IntegrationTestCommon/packages.lock.json @@ -643,6 +643,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -3158,6 +3167,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/util/Migrator/DbScripts/2023-01-06_00_SecretsManager.sql b/util/Migrator/DbScripts/2023-01-06_00_SecretsManager.sql new file mode 100644 index 000000000..6a178e375 --- /dev/null +++ b/util/Migrator/DbScripts/2023-01-06_00_SecretsManager.sql @@ -0,0 +1,807 @@ +IF COL_LENGTH('[dbo].[Organization]', 'UseSecretsManager') IS NULL +BEGIN + ALTER TABLE + [dbo].[Organization] + ADD + [UseSecretsManager] BIT NOT NULL CONSTRAINT [DF_Organization_UseSecretsManager] DEFAULT (0) +END +GO + +CREATE OR ALTER VIEW [dbo].[OrganizationUserOrganizationDetailsView] +AS +SELECT + OU.[UserId], + OU.[OrganizationId], + O.[Name], + O.[Enabled], + O.[PlanType], + O.[UsePolicies], + O.[UseSso], + O.[UseKeyConnector], + O.[UseScim], + O.[UseGroups], + O.[UseDirectory], + O.[UseEvents], + O.[UseTotp], + O.[Use2fa], + O.[UseApi], + O.[UseResetPassword], + O.[SelfHost], + O.[UsersGetPremium], + O.[UseCustomPermissions], + O.[UseSecretsManager], + O.[Seats], + O.[MaxCollections], + O.[MaxStorageGb], + O.[Identifier], + OU.[Key], + OU.[ResetPasswordKey], + O.[PublicKey], + O.[PrivateKey], + OU.[Status], + OU.[Type], + SU.[ExternalId] SsoExternalId, + OU.[Permissions], + PO.[ProviderId], + P.[Name] ProviderName, + SS.[Data] SsoConfig, + OS.[FriendlyName] FamilySponsorshipFriendlyName, + OS.[LastSyncDate] FamilySponsorshipLastSyncDate, + OS.[ToDelete] FamilySponsorshipToDelete, + OS.[ValidUntil] FamilySponsorshipValidUntil +FROM + [dbo].[OrganizationUser] OU +LEFT JOIN + [dbo].[Organization] O ON O.[Id] = OU.[OrganizationId] +LEFT JOIN + [dbo].[SsoUser] SU ON SU.[UserId] = OU.[UserId] AND SU.[OrganizationId] = OU.[OrganizationId] +LEFT JOIN + [dbo].[ProviderOrganization] PO ON PO.[OrganizationId] = O.[Id] +LEFT JOIN + [dbo].[Provider] P ON P.[Id] = PO.[ProviderId] +LEFT JOIN + [dbo].[SsoConfig] SS ON SS.[OrganizationId] = OU.[OrganizationId] +LEFT JOIN + [dbo].[OrganizationSponsorship] OS ON OS.[SponsoringOrganizationUserID] = OU.[Id] +GO + +CREATE OR ALTER PROCEDURE [dbo].[Organization_Create] + @Id UNIQUEIDENTIFIER OUTPUT, + @Identifier NVARCHAR(50), + @Name NVARCHAR(50), + @BusinessName NVARCHAR(50), + @BusinessAddress1 NVARCHAR(50), + @BusinessAddress2 NVARCHAR(50), + @BusinessAddress3 NVARCHAR(50), + @BusinessCountry VARCHAR(2), + @BusinessTaxNumber NVARCHAR(30), + @BillingEmail NVARCHAR(256), + @Plan NVARCHAR(50), + @PlanType TINYINT, + @Seats INT, + @MaxCollections SMALLINT, + @UsePolicies BIT, + @UseSso BIT, + @UseGroups BIT, + @UseDirectory BIT, + @UseEvents BIT, + @UseTotp BIT, + @Use2fa BIT, + @UseApi BIT, + @UseResetPassword BIT, + @SelfHost BIT, + @UsersGetPremium BIT, + @Storage BIGINT, + @MaxStorageGb SMALLINT, + @Gateway TINYINT, + @GatewayCustomerId VARCHAR(50), + @GatewaySubscriptionId VARCHAR(50), + @ReferenceData VARCHAR(MAX), + @Enabled BIT, + @LicenseKey VARCHAR(100), + @PublicKey VARCHAR(MAX), + @PrivateKey VARCHAR(MAX), + @TwoFactorProviders NVARCHAR(MAX), + @ExpirationDate DATETIME2(7), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @OwnersNotifiedOfAutoscaling DATETIME2(7), + @MaxAutoscaleSeats INT, + @UseKeyConnector BIT = 0, + @UseScim BIT = 0, + @UseCustomPermissions BIT = 0, + @UseSecretsManager BIT = 0 +AS +BEGIN + SET NOCOUNT ON + + INSERT INTO [dbo].[Organization] + ( + [Id], + [Identifier], + [Name], + [BusinessName], + [BusinessAddress1], + [BusinessAddress2], + [BusinessAddress3], + [BusinessCountry], + [BusinessTaxNumber], + [BillingEmail], + [Plan], + [PlanType], + [Seats], + [MaxCollections], + [UsePolicies], + [UseSso], + [UseGroups], + [UseDirectory], + [UseEvents], + [UseTotp], + [Use2fa], + [UseApi], + [UseResetPassword], + [SelfHost], + [UsersGetPremium], + [Storage], + [MaxStorageGb], + [Gateway], + [GatewayCustomerId], + [GatewaySubscriptionId], + [ReferenceData], + [Enabled], + [LicenseKey], + [PublicKey], + [PrivateKey], + [TwoFactorProviders], + [ExpirationDate], + [CreationDate], + [RevisionDate], + [OwnersNotifiedOfAutoscaling], + [MaxAutoscaleSeats], + [UseKeyConnector], + [UseScim], + [UseCustomPermissions], + [UseSecretsManager] + ) + VALUES + ( + @Id, + @Identifier, + @Name, + @BusinessName, + @BusinessAddress1, + @BusinessAddress2, + @BusinessAddress3, + @BusinessCountry, + @BusinessTaxNumber, + @BillingEmail, + @Plan, + @PlanType, + @Seats, + @MaxCollections, + @UsePolicies, + @UseSso, + @UseGroups, + @UseDirectory, + @UseEvents, + @UseTotp, + @Use2fa, + @UseApi, + @UseResetPassword, + @SelfHost, + @UsersGetPremium, + @Storage, + @MaxStorageGb, + @Gateway, + @GatewayCustomerId, + @GatewaySubscriptionId, + @ReferenceData, + @Enabled, + @LicenseKey, + @PublicKey, + @PrivateKey, + @TwoFactorProviders, + @ExpirationDate, + @CreationDate, + @RevisionDate, + @OwnersNotifiedOfAutoscaling, + @MaxAutoscaleSeats, + @UseKeyConnector, + @UseScim, + @UseCustomPermissions, + @UseSecretsManager + ) +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[Organization_Update] + @Id UNIQUEIDENTIFIER, + @Identifier NVARCHAR(50), + @Name NVARCHAR(50), + @BusinessName NVARCHAR(50), + @BusinessAddress1 NVARCHAR(50), + @BusinessAddress2 NVARCHAR(50), + @BusinessAddress3 NVARCHAR(50), + @BusinessCountry VARCHAR(2), + @BusinessTaxNumber NVARCHAR(30), + @BillingEmail NVARCHAR(256), + @Plan NVARCHAR(50), + @PlanType TINYINT, + @Seats INT, + @MaxCollections SMALLINT, + @UsePolicies BIT, + @UseSso BIT, + @UseGroups BIT, + @UseDirectory BIT, + @UseEvents BIT, + @UseTotp BIT, + @Use2fa BIT, + @UseApi BIT, + @UseResetPassword BIT, + @SelfHost BIT, + @UsersGetPremium BIT, + @Storage BIGINT, + @MaxStorageGb SMALLINT, + @Gateway TINYINT, + @GatewayCustomerId VARCHAR(50), + @GatewaySubscriptionId VARCHAR(50), + @ReferenceData VARCHAR(MAX), + @Enabled BIT, + @LicenseKey VARCHAR(100), + @PublicKey VARCHAR(MAX), + @PrivateKey VARCHAR(MAX), + @TwoFactorProviders NVARCHAR(MAX), + @ExpirationDate DATETIME2(7), + @CreationDate DATETIME2(7), + @RevisionDate DATETIME2(7), + @OwnersNotifiedOfAutoscaling DATETIME2(7), + @MaxAutoscaleSeats INT, + @UseKeyConnector BIT = 0, + @UseScim BIT = 0, + @UseCustomPermissions BIT = 0, + @UseSecretsManager BIT = 0 +AS +BEGIN + SET NOCOUNT ON + + UPDATE + [dbo].[Organization] + SET + [Identifier] = @Identifier, + [Name] = @Name, + [BusinessName] = @BusinessName, + [BusinessAddress1] = @BusinessAddress1, + [BusinessAddress2] = @BusinessAddress2, + [BusinessAddress3] = @BusinessAddress3, + [BusinessCountry] = @BusinessCountry, + [BusinessTaxNumber] = @BusinessTaxNumber, + [BillingEmail] = @BillingEmail, + [Plan] = @Plan, + [PlanType] = @PlanType, + [Seats] = @Seats, + [MaxCollections] = @MaxCollections, + [UsePolicies] = @UsePolicies, + [UseSso] = @UseSso, + [UseGroups] = @UseGroups, + [UseDirectory] = @UseDirectory, + [UseEvents] = @UseEvents, + [UseTotp] = @UseTotp, + [Use2fa] = @Use2fa, + [UseApi] = @UseApi, + [UseResetPassword] = @UseResetPassword, + [SelfHost] = @SelfHost, + [UsersGetPremium] = @UsersGetPremium, + [Storage] = @Storage, + [MaxStorageGb] = @MaxStorageGb, + [Gateway] = @Gateway, + [GatewayCustomerId] = @GatewayCustomerId, + [GatewaySubscriptionId] = @GatewaySubscriptionId, + [ReferenceData] = @ReferenceData, + [Enabled] = @Enabled, + [LicenseKey] = @LicenseKey, + [PublicKey] = @PublicKey, + [PrivateKey] = @PrivateKey, + [TwoFactorProviders] = @TwoFactorProviders, + [ExpirationDate] = @ExpirationDate, + [CreationDate] = @CreationDate, + [RevisionDate] = @RevisionDate, + [OwnersNotifiedOfAutoscaling] = @OwnersNotifiedOfAutoscaling, + [MaxAutoscaleSeats] = @MaxAutoscaleSeats, + [UseKeyConnector] = @UseKeyConnector, + [UseScim] = @UseScim, + [UseCustomPermissions] = @UseCustomPermissions, + [UseSecretsManager] = @UseSecretsManager + WHERE + [Id] = @Id +END +GO + +IF OBJECT_ID('[dbo].[Secret]') IS NULL +BEGIN + CREATE TABLE [dbo].[Secret] + ( + [Id] UNIQUEIDENTIFIER NOT NULL, + [OrganizationId] UNIQUEIDENTIFIER NOT NULL, + [Key] NVARCHAR(MAX) NULL, + [Value] NVARCHAR(MAX) NULL, + [Note] NVARCHAR(MAX) NULL, + [CreationDate] DATETIME2(7) NOT NULL, + [RevisionDate] DATETIME2(7) NOT NULL, + [DeletedDate] DATETIME2(7) NULL, + CONSTRAINT [PK_Secret] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_Secret_OrganizationId] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization]([Id]) + ); + + CREATE NONCLUSTERED INDEX [IX_Secret_OrganizationId] ON [dbo].[Secret] ([OrganizationId] ASC); + + CREATE NONCLUSTERED INDEX [IX_Secret_DeletedDate] ON [dbo].[Secret] ([DeletedDate] ASC); +END +GO + +IF OBJECT_ID('[dbo].[Project]') IS NULL +BEGIN + CREATE TABLE [dbo].[Project] ( + [Id] UNIQUEIDENTIFIER NOT NULL, + [OrganizationId] UNIQUEIDENTIFIER NOT NULL, + [Name] NVARCHAR(MAX) NULL, + [CreationDate] DATETIME2 (7), + [RevisionDate] DATETIME2 (7), + [DeletedDate] DATETIME2 (7) NULL, + CONSTRAINT [PK_Project] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_Project_Organization] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization] ([Id]) + ); + + CREATE NONCLUSTERED INDEX [IX_Project_OrganizationId] ON [dbo].[Project] ([OrganizationId] ASC); + + CREATE NONCLUSTERED INDEX [IX_Project_DeletedDate] ON [dbo].[Project] ([DeletedDate] ASC); +END +GO + +IF OBJECT_ID('[dbo].[ProjectSecret]') IS NULL +BEGIN + CREATE TABLE [dbo].[ProjectSecret] ( + [ProjectsId] uniqueidentifier NOT NULL, + [SecretsId] uniqueidentifier NOT NULL, + CONSTRAINT [PK_ProjectSecret] PRIMARY KEY ([ProjectsId], [SecretsId]), + CONSTRAINT [FK_ProjectSecret_Project_ProjectsId] FOREIGN KEY ([ProjectsId]) REFERENCES [Project] ([Id]) ON DELETE CASCADE, + CONSTRAINT [FK_ProjectSecret_Secret_SecretsId] FOREIGN KEY ([SecretsId]) REFERENCES [Secret] ([Id]) ON DELETE CASCADE + ); + + CREATE NONCLUSTERED INDEX [IX_ProjectSecret_SecretsId] ON [ProjectSecret] ([SecretsId]); +END +GO + +IF OBJECT_ID('[dbo].[ServiceAccount]') IS NULL +BEGIN + CREATE TABLE [dbo].[ServiceAccount] + ( + [Id] UNIQUEIDENTIFIER NOT NULL, + [OrganizationId] UNIQUEIDENTIFIER NOT NULL, + [Name] NVARCHAR(MAX) NULL, + [CreationDate] DATETIME2(7) NOT NULL, + [RevisionDate] DATETIME2(7) NOT NULL, + CONSTRAINT [PK_ServiceAccount] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_ServiceAccount_OrganizationId] FOREIGN KEY ([OrganizationId]) REFERENCES [dbo].[Organization]([Id]) + ); + + CREATE NONCLUSTERED INDEX [IX_ServiceAccount_OrganizationId] ON [dbo].[ServiceAccount] ([OrganizationId] ASC); +END +GO + +IF OBJECT_ID('[dbo].[ApiKey]') IS NULL +BEGIN + 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, + CONSTRAINT [PK_ApiKey] PRIMARY KEY CLUSTERED ([Id] ASC), + CONSTRAINT [FK_ApiKey_ServiceAccountId] FOREIGN KEY ([ServiceAccountId]) REFERENCES [dbo].[ServiceAccount] ([Id]) + ); + + CREATE NONCLUSTERED INDEX [IX_ApiKey_ServiceAccountId] + ON [dbo].[ApiKey]([ServiceAccountId] ASC); +END +GO + +CREATE OR ALTER VIEW [dbo].[ApiKeyDetailsView] +AS +SELECT + AK.*, + SA.[OrganizationId] ServiceAccountOrganizationId +FROM + [dbo].[ApiKey] AS AK +LEFT JOIN + [dbo].[ServiceAccount] SA ON SA.[Id] = AK.[ServiceAccountId] +GO + +CREATE OR ALTER VIEW [dbo].[ApiKeyView] +AS +SELECT + * +FROM + [dbo].[ApiKey] +GO + +CREATE OR ALTER PROCEDURE [dbo].[ApiKey_Create] + @Id UNIQUEIDENTIFIER OUTPUT, + @ServiceAccountId UNIQUEIDENTIFIER, + @Name VARCHAR(200), + @ClientSecret VARCHAR(30), + @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], + [ClientSecret], + [Scope], + [EncryptedPayload], + [Key], + [ExpireAt], + [CreationDate], + [RevisionDate] + ) + VALUES + ( + @Id, + @ServiceAccountId, + @Name, + @ClientSecret, + @Scope, + @EncryptedPayload, + @Key, + @ExpireAt, + @CreationDate, + @RevisionDate + ) +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[ApiKey_ReadByServiceAccountId] + @ServiceAccountId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + * + FROM + [dbo].[ApiKeyView] + WHERE + [ServiceAccountId] = @ServiceAccountId +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[ApiKeyDetails_ReadById] + @Id UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + SELECT + * + FROM + [dbo].[ApiKeyDetailsView] + WHERE + [Id] = @Id +END +GO + +IF OBJECT_ID('[dbo].[AccessPolicy]') IS NULL +BEGIN + CREATE TABLE [AccessPolicy] ( + [Id] UNIQUEIDENTIFIER NOT NULL, + [Discriminator] NVARCHAR(50) NOT NULL, + [OrganizationUserId] UNIQUEIDENTIFIER NULL, + [GroupId] UNIQUEIDENTIFIER NULL, + [ServiceAccountId] UNIQUEIDENTIFIER NULL, + [GrantedProjectId] UNIQUEIDENTIFIER NULL, + [GrantedServiceAccountId] UNIQUEIDENTIFIER NULL, + [Read] BIT NOT NULL, + [Write] BIT NOT NULL, + [CreationDate] DATETIME2 NOT NULL, + [RevisionDate] DATETIME2 NOT NULL, + CONSTRAINT [PK_AccessPolicy] PRIMARY KEY CLUSTERED ([Id]), + CONSTRAINT [FK_AccessPolicy_Group_GroupId] FOREIGN KEY ([GroupId]) REFERENCES [Group] ([Id]) ON DELETE CASCADE, + CONSTRAINT [FK_AccessPolicy_OrganizationUser_OrganizationUserId] FOREIGN KEY ([OrganizationUserId]) REFERENCES [OrganizationUser] ([Id]), + CONSTRAINT [FK_AccessPolicy_Project_GrantedProjectId] FOREIGN KEY ([GrantedProjectId]) REFERENCES [Project] ([Id]) ON DELETE CASCADE, + CONSTRAINT [FK_AccessPolicy_ServiceAccount_GrantedServiceAccountId] FOREIGN KEY ([GrantedServiceAccountId]) REFERENCES [ServiceAccount] ([Id]), + CONSTRAINT [FK_AccessPolicy_ServiceAccount_ServiceAccountId] FOREIGN KEY ([ServiceAccountId]) REFERENCES [ServiceAccount] ([Id]) + ); + + CREATE NONCLUSTERED INDEX [IX_AccessPolicy_GroupId] ON [AccessPolicy] ([GroupId]); + + CREATE NONCLUSTERED INDEX [IX_AccessPolicy_OrganizationUserId] ON [AccessPolicy] ([OrganizationUserId]); + + CREATE NONCLUSTERED INDEX [IX_AccessPolicy_GrantedProjectId] ON [AccessPolicy] ([GrantedProjectId]); + + CREATE NONCLUSTERED INDEX [IX_AccessPolicy_ServiceAccountId] ON [AccessPolicy] ([ServiceAccountId]); + + CREATE NONCLUSTERED INDEX [IX_AccessPolicy_GrantedServiceAccountId] ON [AccessPolicy] ([GrantedServiceAccountId]); +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[User_DeleteById] + @Id UNIQUEIDENTIFIER +WITH RECOMPILE +AS +BEGIN + SET NOCOUNT ON + DECLARE @BatchSize INT = 100 + + -- Delete ciphers + WHILE @BatchSize > 0 + BEGIN + BEGIN TRANSACTION User_DeleteById_Ciphers + + DELETE TOP(@BatchSize) + FROM + [dbo].[Cipher] + WHERE + [UserId] = @Id + + SET @BatchSize = @@ROWCOUNT + + COMMIT TRANSACTION User_DeleteById_Ciphers + END + + BEGIN TRANSACTION User_DeleteById + + -- Delete folders + DELETE + FROM + [dbo].[Folder] + WHERE + [UserId] = @Id + + -- Delete devices + DELETE + FROM + [dbo].[Device] + WHERE + [UserId] = @Id + + -- Delete collection users + DELETE + CU + FROM + [dbo].[CollectionUser] CU + INNER JOIN + [dbo].[OrganizationUser] OU ON OU.[Id] = CU.[OrganizationUserId] + WHERE + OU.[UserId] = @Id + + -- Delete group users + DELETE + GU + FROM + [dbo].[GroupUser] GU + INNER JOIN + [dbo].[OrganizationUser] OU ON OU.[Id] = GU.[OrganizationUserId] + WHERE + OU.[UserId] = @Id + + -- Delete AccessPolicy + DELETE + AP + FROM + [dbo].[AccessPolicy] AP + INNER JOIN + [dbo].[OrganizationUser] OU ON OU.[Id] = AP.[OrganizationUserId] + WHERE + [UserId] = @Id + + -- Delete organization users + DELETE + FROM + [dbo].[OrganizationUser] + WHERE + [UserId] = @Id + + -- Delete provider users + DELETE + FROM + [dbo].[ProviderUser] + WHERE + [UserId] = @Id + + -- Delete SSO Users + DELETE + FROM + [dbo].[SsoUser] + WHERE + [UserId] = @Id + + -- Delete Emergency Accesses + DELETE + FROM + [dbo].[EmergencyAccess] + WHERE + [GrantorId] = @Id + OR + [GranteeId] = @Id + + -- Delete Sends + DELETE + FROM + [dbo].[Send] + WHERE + [UserId] = @Id + + -- Finally, delete the user + DELETE + FROM + [dbo].[User] + WHERE + [Id] = @Id + + COMMIT TRANSACTION User_DeleteById +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[Organization_DeleteById] + @Id UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationId] @Id + + DECLARE @BatchSize INT = 100 + WHILE @BatchSize > 0 + BEGIN + BEGIN TRANSACTION Organization_DeleteById_Ciphers + + DELETE TOP(@BatchSize) + FROM + [dbo].[Cipher] + WHERE + [UserId] IS NULL + AND [OrganizationId] = @Id + + SET @BatchSize = @@ROWCOUNT + + COMMIT TRANSACTION Organization_DeleteById_Ciphers + END + + BEGIN TRANSACTION Organization_DeleteById + + DELETE + FROM + [dbo].[SsoUser] + WHERE + [OrganizationId] = @Id + + DELETE + FROM + [dbo].[SsoConfig] + WHERE + [OrganizationId] = @Id + + DELETE CU + FROM + [dbo].[CollectionUser] CU + INNER JOIN + [dbo].[OrganizationUser] OU ON [CU].[OrganizationUserId] = [OU].[Id] + WHERE + [OU].[OrganizationId] = @Id + + DELETE + FROM + [dbo].[OrganizationUser] + WHERE + [OrganizationId] = @Id + + DELETE + FROM + [dbo].[ProviderOrganization] + WHERE + [OrganizationId] = @Id + + EXEC [dbo].[OrganizationApiKey_OrganizationDeleted] @Id + EXEC [dbo].[OrganizationConnection_OrganizationDeleted] @Id + EXEC [dbo].[OrganizationSponsorship_OrganizationDeleted] @Id + + DELETE + FROM + [dbo].[Project] + WHERE + [OrganizationId] = @Id + + DELETE + FROM + [dbo].[Secret] + WHERE + [OrganizationId] = @Id + + DELETE AK + FROM + [dbo].[ApiKey] AK + INNER JOIN + [dbo].[ServiceAccount] SA ON [AK].[ServiceAccountId] = [SA].[Id] + WHERE + [SA].[OrganizationId] = @Id + + DELETE + FROM + [dbo].[ServiceAccount] + WHERE + [OrganizationId] = @Id + + DELETE + FROM + [dbo].[Organization] + WHERE + [Id] = @Id + + COMMIT TRANSACTION Organization_DeleteById +END +GO + +CREATE OR ALTER PROCEDURE [dbo].[OrganizationUser_DeleteById] + @Id UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + + EXEC [dbo].[User_BumpAccountRevisionDateByOrganizationUserId] @Id + + DECLARE @OrganizationId UNIQUEIDENTIFIER + DECLARE @UserId UNIQUEIDENTIFIER + + SELECT + @OrganizationId = [OrganizationId], + @UserId = [UserId] + FROM + [dbo].[OrganizationUser] + WHERE + [Id] = @Id + + IF @OrganizationId IS NOT NULL AND @UserId IS NOT NULL + BEGIN + EXEC [dbo].[SsoUser_Delete] @UserId, @OrganizationId + END + + DELETE + FROM + [dbo].[CollectionUser] + WHERE + [OrganizationUserId] = @Id + + DELETE + FROM + [dbo].[GroupUser] + WHERE + [OrganizationUserId] = @Id + + DELETE + FROM + [dbo].[AccessPolicy] + WHERE + [OrganizationUserId] = @Id + + EXEC [dbo].[OrganizationSponsorship_OrganizationUserDeleted] @Id + + DELETE + FROM + [dbo].[OrganizationUser] + WHERE + [Id] = @Id +END +GO diff --git a/util/MySqlMigrations/Migrations/20230106122006_SecretsManager.Designer.cs b/util/MySqlMigrations/Migrations/20230106122006_SecretsManager.Designer.cs new file mode 100644 index 000000000..f01ac93a9 --- /dev/null +++ b/util/MySqlMigrations/Migrations/20230106122006_SecretsManager.Designer.cs @@ -0,0 +1,2118 @@ +// +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("20230106122006_SecretsManager")] + partial class SecretsManager + { + 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.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.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClientSecret") + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + 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.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("RequestFingerprint") + .HasColumnType("longtext"); + + 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.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.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.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("PushToken") + .HasMaxLength(255) + .HasColumnType("varchar(255)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Device", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("varchar(256)"); + + b.Property("GranteeId") + .HasColumnType("char(36)"); + + b.Property("GrantorId") + .HasColumnType("char(36)"); + + b.Property("KeyEncrypted") + .HasColumnType("longtext"); + + b.Property("LastNotificationDate") + .HasColumnType("datetime(6)"); + + b.Property("RecoveryInitiatedDate") + .HasColumnType("datetime(6)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("tinyint unsigned"); + + b.Property("Type") + .HasColumnType("tinyint unsigned"); + + b.Property("WaitTimeDays") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("GranteeId"); + + b.HasIndex("GrantorId"); + + b.ToTable("EmergencyAccess", (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("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("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.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("Bit.Infrastructure.EntityFramework.Models.Grant", b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ConsumedDate") + .HasColumnType("datetime(6)"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("longtext"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("ExpirationDate") + .HasColumnType("datetime(6)"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("varchar(200)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.HasKey("Key"); + + b.ToTable("Grant", (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.Property("UserId") + .HasColumnType("char(36)"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + 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("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.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("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.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.Models.Provider", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("BillingEmail") + .HasColumnType("longtext"); + + b.Property("BusinessAddress1") + .HasColumnType("longtext"); + + b.Property("BusinessAddress2") + .HasColumnType("longtext"); + + b.Property("BusinessAddress3") + .HasColumnType("longtext"); + + b.Property("BusinessCountry") + .HasColumnType("longtext"); + + b.Property("BusinessName") + .HasColumnType("longtext"); + + b.Property("BusinessTaxNumber") + .HasColumnType("longtext"); + + b.Property("CreationDate") + .HasColumnType("datetime(6)"); + + b.Property("Enabled") + .HasColumnType("tinyint(1)"); + + b.Property("Name") + .HasColumnType("longtext"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("Status") + .HasColumnType("tinyint unsigned"); + + b.Property("UseEvents") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("Provider", (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.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.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.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.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.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.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("Key") + .HasColumnType("longtext"); + + b.Property("LastFailedLoginDate") + .HasColumnType("datetime(6)"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("varchar(100)"); + + b.Property("MasterPassword") + .HasMaxLength(300) + .HasColumnType("varchar(300)"); + + b.Property("MasterPasswordHint") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Premium") + .HasColumnType("tinyint(1)"); + + b.Property("PremiumExpirationDate") + .HasColumnType("datetime(6)"); + + b.Property("PrivateKey") + .HasColumnType("longtext"); + + b.Property("PublicKey") + .HasColumnType("longtext"); + + b.Property("ReferenceData") + .HasColumnType("longtext"); + + b.Property("RenewalReminderDate") + .HasColumnType("datetime(6)"); + + b.Property("RevisionDate") + .HasColumnType("datetime(6)"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("varchar(50)"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("longtext"); + + b.Property("TwoFactorRecoveryCode") + .HasMaxLength(32) + .HasColumnType("varchar(32)"); + + b.Property("UnknownDeviceVerificationEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("UsesKeyConnector") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.ToTable("User", (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.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Cipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Ciphers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Ciphers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Cipher", "Cipher") + .WithMany("CollectionCiphers") + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionCiphers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionGroups") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionUsers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("CollectionUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("CollectionUsers") + .HasForeignKey("UserId"); + + b.Navigation("Collection"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantee") + .WithMany() + .HasForeignKey("GranteeId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantor") + .WithMany() + .HasForeignKey("GrantorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grantee"); + + b.Navigation("Grantor"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Groups") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany("GroupUsers") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("GroupUsers") + .HasForeignKey("UserId"); + + b.Navigation("Group"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("ApiKeys") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Connections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoredOrganization") + .WithMany() + .HasForeignKey("SponsoredOrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoringOrganization") + .WithMany() + .HasForeignKey("SponsoringOrganizationId"); + + b.Navigation("SponsoredOrganization"); + + b.Navigation("SponsoringOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("OrganizationUsers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("OrganizationUsers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Policies") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.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.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.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.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.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.Models.SsoConfig", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoConfigs") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoUsers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("SsoUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Transactions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .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.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Navigation("CollectionCiphers"); + + b.Navigation("CollectionGroups"); + + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("Ciphers"); + + b.Navigation("Connections"); + + b.Navigation("Groups"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("Policies"); + + b.Navigation("SsoConfigs"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("CollectionUsers"); + + b.Navigation("Folders"); + + b.Navigation("GroupUsers"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/MySqlMigrations/Migrations/20230106122006_SecretsManager.cs b/util/MySqlMigrations/Migrations/20230106122006_SecretsManager.cs new file mode 100644 index 000000000..c14ccfe4e --- /dev/null +++ b/util/MySqlMigrations/Migrations/20230106122006_SecretsManager.cs @@ -0,0 +1,282 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Bit.MySqlMigrations.Migrations; + +public partial class SecretsManager : Migration +{ + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UseSecretsManager", + table: "Organization", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + + migrationBuilder.CreateTable( + name: "Project", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + OrganizationId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationDate = table.Column(type: "datetime(6)", nullable: false), + RevisionDate = table.Column(type: "datetime(6)", nullable: false), + DeletedDate = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Project", x => x.Id); + table.ForeignKey( + name: "FK_Project_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "Secret", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + OrganizationId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Key = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Value = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Note = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationDate = table.Column(type: "datetime(6)", nullable: false), + RevisionDate = table.Column(type: "datetime(6)", nullable: false), + DeletedDate = table.Column(type: "datetime(6)", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Secret", x => x.Id); + table.ForeignKey( + name: "FK_Secret_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ServiceAccount", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + OrganizationId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + Name = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + CreationDate = table.Column(type: "datetime(6)", nullable: false), + RevisionDate = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ServiceAccount", x => x.Id); + table.ForeignKey( + name: "FK_ServiceAccount_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ProjectSecret", + columns: table => new + { + ProjectsId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + SecretsId = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci") + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectSecret", x => new { x.ProjectsId, x.SecretsId }); + table.ForeignKey( + name: "FK_ProjectSecret_Project_ProjectsId", + column: x => x.ProjectsId, + principalTable: "Project", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ProjectSecret_Secret_SecretsId", + column: x => x.SecretsId, + principalTable: "Secret", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "AccessPolicy", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + GroupId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + GrantedProjectId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + GrantedServiceAccountId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + ServiceAccountId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + OrganizationUserId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Read = table.Column(type: "tinyint(1)", nullable: false), + Write = table.Column(type: "tinyint(1)", nullable: false), + CreationDate = table.Column(type: "datetime(6)", nullable: false), + RevisionDate = table.Column(type: "datetime(6)", nullable: false), + Discriminator = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_AccessPolicy", x => x.Id); + table.ForeignKey( + name: "FK_AccessPolicy_Group_GroupId", + column: x => x.GroupId, + principalTable: "Group", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_OrganizationUser_OrganizationUserId", + column: x => x.OrganizationUserId, + principalTable: "OrganizationUser", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_Project_GrantedProjectId", + column: x => x.GrantedProjectId, + principalTable: "Project", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_ServiceAccount_GrantedServiceAccountId", + column: x => x.GrantedServiceAccountId, + principalTable: "ServiceAccount", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_ServiceAccount_ServiceAccountId", + column: x => x.ServiceAccountId, + principalTable: "ServiceAccount", + principalColumn: "Id"); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ApiKey", + columns: table => new + { + Id = table.Column(type: "char(36)", nullable: false, collation: "ascii_general_ci"), + ServiceAccountId = table.Column(type: "char(36)", nullable: true, collation: "ascii_general_ci"), + Name = table.Column(type: "varchar(200)", maxLength: 200, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ClientSecret = table.Column(type: "varchar(30)", maxLength: 30, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Scope = table.Column(type: "varchar(4000)", maxLength: 4000, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + EncryptedPayload = table.Column(type: "varchar(4000)", maxLength: 4000, nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + Key = table.Column(type: "longtext", nullable: true) + .Annotation("MySql:CharSet", "utf8mb4"), + ExpireAt = table.Column(type: "datetime(6)", nullable: true), + CreationDate = table.Column(type: "datetime(6)", nullable: false), + RevisionDate = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiKey", x => x.Id); + table.ForeignKey( + name: "FK_ApiKey_ServiceAccount_ServiceAccountId", + column: x => x.ServiceAccountId, + principalTable: "ServiceAccount", + principalColumn: "Id"); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_GrantedProjectId", + table: "AccessPolicy", + column: "GrantedProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_GrantedServiceAccountId", + table: "AccessPolicy", + column: "GrantedServiceAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_GroupId", + table: "AccessPolicy", + column: "GroupId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_OrganizationUserId", + table: "AccessPolicy", + column: "OrganizationUserId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_ServiceAccountId", + table: "AccessPolicy", + column: "ServiceAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiKey_ServiceAccountId", + table: "ApiKey", + column: "ServiceAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_Project_DeletedDate", + table: "Project", + column: "DeletedDate"); + + migrationBuilder.CreateIndex( + name: "IX_Project_OrganizationId", + table: "Project", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectSecret_SecretsId", + table: "ProjectSecret", + column: "SecretsId"); + + migrationBuilder.CreateIndex( + name: "IX_Secret_DeletedDate", + table: "Secret", + column: "DeletedDate"); + + migrationBuilder.CreateIndex( + name: "IX_Secret_OrganizationId", + table: "Secret", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_ServiceAccount_OrganizationId", + table: "ServiceAccount", + column: "OrganizationId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AccessPolicy"); + + migrationBuilder.DropTable( + name: "ApiKey"); + + migrationBuilder.DropTable( + name: "ProjectSecret"); + + migrationBuilder.DropTable( + name: "ServiceAccount"); + + migrationBuilder.DropTable( + name: "Project"); + + migrationBuilder.DropTable( + name: "Secret"); + + migrationBuilder.DropColumn( + name: "UseSecretsManager", + table: "Organization"); + } +} diff --git a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs index 297c8c8b3..b3c6c1220 100644 --- a/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/MySqlMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -16,9 +16,83 @@ namespace Bit.MySqlMigrations.Migrations { #pragma warning disable 612, 618 modelBuilder - .HasAnnotation("ProductVersion", "6.0.4") + .HasAnnotation("ProductVersion", "6.0.12") .HasAnnotation("Relational:MaxIdentifierLength", 64); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("char(36)"); + + b.Property("ClientSecret") + .HasMaxLength(30) + .HasColumnType("varchar(30)"); + + 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.Models.AuthRequest", b => { b.Property("Id") @@ -646,6 +720,9 @@ namespace Bit.MySqlMigrations.Migrations b.Property("UseScim") .HasColumnType("tinyint(1)"); + b.Property("UseSecretsManager") + .HasColumnType("tinyint(1)"); + b.Property("UseSso") .HasColumnType("tinyint(1)"); @@ -834,6 +911,38 @@ namespace Bit.MySqlMigrations.Migrations b.ToTable("Policy", (string)null); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Provider", b => { b.Property("Id") @@ -956,6 +1065,44 @@ namespace Bit.MySqlMigrations.Migrations b.ToTable("ProviderUser", (string)null); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Send", b => { b.Property("Id") @@ -1013,6 +1160,32 @@ namespace Bit.MySqlMigrations.Migrations b.ToTable("Send", (string)null); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.SsoConfig", b => { b.Property("Id") @@ -1280,6 +1453,134 @@ namespace Bit.MySqlMigrations.Migrations b.ToTable("User", (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.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.AuthRequest", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Device", "ResponseDevice") @@ -1522,6 +1823,17 @@ namespace Bit.MySqlMigrations.Migrations b.Navigation("Organization"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.ProviderOrganization", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") @@ -1558,6 +1870,17 @@ namespace Bit.MySqlMigrations.Migrations b.Navigation("User"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Send", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") @@ -1573,6 +1896,17 @@ namespace Bit.MySqlMigrations.Migrations b.Navigation("User"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.SsoConfig", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") @@ -1616,6 +1950,96 @@ namespace Bit.MySqlMigrations.Migrations b.Navigation("User"); }); + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .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.Cipher", b => { b.Navigation("CollectionCiphers"); @@ -1661,6 +2085,15 @@ namespace Bit.MySqlMigrations.Migrations b.Navigation("CollectionUsers"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => { b.Navigation("Ciphers"); diff --git a/util/MySqlMigrations/packages.lock.json b/util/MySqlMigrations/packages.lock.json index 27cae9c36..840b75657 100644 --- a/util/MySqlMigrations/packages.lock.json +++ b/util/MySqlMigrations/packages.lock.json @@ -549,6 +549,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2757,6 +2766,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/util/PostgresMigrations/Migrations/20230106153838_SecretsManager.Designer.cs b/util/PostgresMigrations/Migrations/20230106153838_SecretsManager.Designer.cs new file mode 100644 index 000000000..114d17325 --- /dev/null +++ b/util/PostgresMigrations/Migrations/20230106153838_SecretsManager.Designer.cs @@ -0,0 +1,2129 @@ +// +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("20230106153838_SecretsManager")] + partial class SecretsManager + { + 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.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.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientSecret") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + 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.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("RequestFingerprint") + .HasColumnType("text"); + + 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.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.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.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreationDate") + .HasColumnType("timestamp 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.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.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("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("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.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("Bit.Infrastructure.EntityFramework.Models.Grant", b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ConsumedDate") + .HasColumnType("timestamp 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.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.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + 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("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.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("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.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.Models.Provider", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("BillingEmail") + .HasColumnType("text"); + + b.Property("BusinessAddress1") + .HasColumnType("text"); + + b.Property("BusinessAddress2") + .HasColumnType("text"); + + b.Property("BusinessAddress3") + .HasColumnType("text"); + + b.Property("BusinessCountry") + .HasColumnType("text"); + + b.Property("BusinessName") + .HasColumnType("text"); + + b.Property("BusinessTaxNumber") + .HasColumnType("text"); + + b.Property("CreationDate") + .HasColumnType("timestamp 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("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.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.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.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.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.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.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("Key") + .HasColumnType("text"); + + b.Property("LastFailedLoginDate") + .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("UnknownDeviceVerificationEnabled") + .HasColumnType("boolean"); + + b.Property("UsesKeyConnector") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("User", (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.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Cipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Ciphers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Ciphers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Cipher", "Cipher") + .WithMany("CollectionCiphers") + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionCiphers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionGroups") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionUsers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("CollectionUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("CollectionUsers") + .HasForeignKey("UserId"); + + b.Navigation("Collection"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantee") + .WithMany() + .HasForeignKey("GranteeId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantor") + .WithMany() + .HasForeignKey("GrantorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grantee"); + + b.Navigation("Grantor"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Groups") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany("GroupUsers") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("GroupUsers") + .HasForeignKey("UserId"); + + b.Navigation("Group"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("ApiKeys") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Connections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoredOrganization") + .WithMany() + .HasForeignKey("SponsoredOrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoringOrganization") + .WithMany() + .HasForeignKey("SponsoringOrganizationId"); + + b.Navigation("SponsoredOrganization"); + + b.Navigation("SponsoringOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("OrganizationUsers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("OrganizationUsers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Policies") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.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.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.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.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.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.Models.SsoConfig", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoConfigs") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoUsers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("SsoUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Transactions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .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.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Navigation("CollectionCiphers"); + + b.Navigation("CollectionGroups"); + + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("Ciphers"); + + b.Navigation("Connections"); + + b.Navigation("Groups"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("Policies"); + + b.Navigation("SsoConfigs"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("CollectionUsers"); + + b.Navigation("Folders"); + + b.Navigation("GroupUsers"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/PostgresMigrations/Migrations/20230106153838_SecretsManager.cs b/util/PostgresMigrations/Migrations/20230106153838_SecretsManager.cs new file mode 100644 index 000000000..49f3763b6 --- /dev/null +++ b/util/PostgresMigrations/Migrations/20230106153838_SecretsManager.cs @@ -0,0 +1,325 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Bit.PostgresMigrations.Migrations; + +public partial class SecretsManager : Migration +{ + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UseSecretsManager", + table: "Organization", + type: "boolean", + nullable: false, + defaultValue: false); + + migrationBuilder.AlterColumn( + name: "RequestIpAddress", + table: "AuthRequest", + type: "character varying(50)", + maxLength: 50, + nullable: true, + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestDeviceIdentifier", + table: "AuthRequest", + type: "character varying(50)", + maxLength: 50, + nullable: true, + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "AccessCode", + table: "AuthRequest", + type: "character varying(25)", + maxLength: 25, + nullable: true, + oldClrType: typeof(string), + oldType: "text", + oldNullable: true); + + migrationBuilder.CreateTable( + name: "Project", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + OrganizationId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: true), + CreationDate = table.Column(type: "timestamp with time zone", nullable: false), + RevisionDate = table.Column(type: "timestamp with time zone", nullable: false), + DeletedDate = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Project", x => x.Id); + table.ForeignKey( + name: "FK_Project_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Secret", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + OrganizationId = table.Column(type: "uuid", nullable: false), + Key = table.Column(type: "text", nullable: true), + Value = table.Column(type: "text", nullable: true), + Note = table.Column(type: "text", nullable: true), + CreationDate = table.Column(type: "timestamp with time zone", nullable: false), + RevisionDate = table.Column(type: "timestamp with time zone", nullable: false), + DeletedDate = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Secret", x => x.Id); + table.ForeignKey( + name: "FK_Secret_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ServiceAccount", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + OrganizationId = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: true), + CreationDate = table.Column(type: "timestamp with time zone", nullable: false), + RevisionDate = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ServiceAccount", x => x.Id); + table.ForeignKey( + name: "FK_ServiceAccount_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProjectSecret", + columns: table => new + { + ProjectsId = table.Column(type: "uuid", nullable: false), + SecretsId = table.Column(type: "uuid", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectSecret", x => new { x.ProjectsId, x.SecretsId }); + table.ForeignKey( + name: "FK_ProjectSecret_Project_ProjectsId", + column: x => x.ProjectsId, + principalTable: "Project", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ProjectSecret_Secret_SecretsId", + column: x => x.SecretsId, + principalTable: "Secret", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AccessPolicy", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + GroupId = table.Column(type: "uuid", nullable: true), + GrantedProjectId = table.Column(type: "uuid", nullable: true), + GrantedServiceAccountId = table.Column(type: "uuid", nullable: true), + ServiceAccountId = table.Column(type: "uuid", nullable: true), + OrganizationUserId = table.Column(type: "uuid", nullable: true), + Read = table.Column(type: "boolean", nullable: false), + Write = table.Column(type: "boolean", nullable: false), + CreationDate = table.Column(type: "timestamp with time zone", nullable: false), + RevisionDate = table.Column(type: "timestamp with time zone", nullable: false), + Discriminator = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AccessPolicy", x => x.Id); + table.ForeignKey( + name: "FK_AccessPolicy_Group_GroupId", + column: x => x.GroupId, + principalTable: "Group", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_OrganizationUser_OrganizationUserId", + column: x => x.OrganizationUserId, + principalTable: "OrganizationUser", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_Project_GrantedProjectId", + column: x => x.GrantedProjectId, + principalTable: "Project", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_ServiceAccount_GrantedServiceAccountId", + column: x => x.GrantedServiceAccountId, + principalTable: "ServiceAccount", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_ServiceAccount_ServiceAccountId", + column: x => x.ServiceAccountId, + principalTable: "ServiceAccount", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "ApiKey", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + ServiceAccountId = table.Column(type: "uuid", nullable: true), + Name = table.Column(type: "character varying(200)", maxLength: 200, nullable: true), + ClientSecret = table.Column(type: "character varying(30)", maxLength: 30, nullable: true), + Scope = table.Column(type: "character varying(4000)", maxLength: 4000, nullable: true), + EncryptedPayload = table.Column(type: "character varying(4000)", maxLength: 4000, nullable: true), + Key = table.Column(type: "text", nullable: true), + ExpireAt = table.Column(type: "timestamp with time zone", nullable: true), + CreationDate = table.Column(type: "timestamp with time zone", nullable: false), + RevisionDate = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiKey", x => x.Id); + table.ForeignKey( + name: "FK_ApiKey_ServiceAccount_ServiceAccountId", + column: x => x.ServiceAccountId, + principalTable: "ServiceAccount", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_GrantedProjectId", + table: "AccessPolicy", + column: "GrantedProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_GrantedServiceAccountId", + table: "AccessPolicy", + column: "GrantedServiceAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_GroupId", + table: "AccessPolicy", + column: "GroupId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_OrganizationUserId", + table: "AccessPolicy", + column: "OrganizationUserId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_ServiceAccountId", + table: "AccessPolicy", + column: "ServiceAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiKey_ServiceAccountId", + table: "ApiKey", + column: "ServiceAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_Project_DeletedDate", + table: "Project", + column: "DeletedDate"); + + migrationBuilder.CreateIndex( + name: "IX_Project_OrganizationId", + table: "Project", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectSecret_SecretsId", + table: "ProjectSecret", + column: "SecretsId"); + + migrationBuilder.CreateIndex( + name: "IX_Secret_DeletedDate", + table: "Secret", + column: "DeletedDate"); + + migrationBuilder.CreateIndex( + name: "IX_Secret_OrganizationId", + table: "Secret", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_ServiceAccount_OrganizationId", + table: "ServiceAccount", + column: "OrganizationId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AccessPolicy"); + + migrationBuilder.DropTable( + name: "ApiKey"); + + migrationBuilder.DropTable( + name: "ProjectSecret"); + + migrationBuilder.DropTable( + name: "ServiceAccount"); + + migrationBuilder.DropTable( + name: "Project"); + + migrationBuilder.DropTable( + name: "Secret"); + + migrationBuilder.DropColumn( + name: "UseSecretsManager", + table: "Organization"); + + migrationBuilder.AlterColumn( + name: "RequestIpAddress", + table: "AuthRequest", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(50)", + oldMaxLength: 50, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "RequestDeviceIdentifier", + table: "AuthRequest", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(50)", + oldMaxLength: 50, + oldNullable: true); + + migrationBuilder.AlterColumn( + name: "AccessCode", + table: "AuthRequest", + type: "text", + nullable: true, + oldClrType: typeof(string), + oldType: "character varying(25)", + oldMaxLength: 25, + oldNullable: true); + } +} diff --git a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs index 795dee9c3..dbfde000d 100644 --- a/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/PostgresMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -18,19 +18,94 @@ namespace Bit.PostgresMigrations.Migrations #pragma warning disable 612, 618 modelBuilder .HasAnnotation("Npgsql:CollationDefinition:postgresIndetermanisticCollation", "en-u-ks-primary,en-u-ks-primary,icu,False") - .HasAnnotation("ProductVersion", "6.0.4") + .HasAnnotation("ProductVersion", "6.0.12") .HasAnnotation("Relational:MaxIdentifierLength", 63); NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("uuid"); + + b.Property("ClientSecret") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + 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.Models.AuthRequest", b => { b.Property("Id") .HasColumnType("uuid"); b.Property("AccessCode") - .HasColumnType("text"); - + .HasMaxLength(25) + .HasColumnType("character varying(25)"); + b.Property("Approved") .HasColumnType("boolean"); @@ -50,7 +125,8 @@ namespace Bit.PostgresMigrations.Migrations .HasColumnType("text"); b.Property("RequestDeviceIdentifier") - .HasColumnType("text"); + .HasMaxLength(50) + .HasColumnType("character varying(50)"); b.Property("RequestDeviceType") .HasColumnType("smallint"); @@ -59,7 +135,8 @@ namespace Bit.PostgresMigrations.Migrations .HasColumnType("text"); b.Property("RequestIpAddress") - .HasColumnType("text"); + .HasMaxLength(50) + .HasColumnType("character varying(50)"); b.Property("ResponseDate") .HasColumnType("timestamp with time zone"); @@ -190,7 +267,7 @@ namespace Bit.PostgresMigrations.Migrations b.HasIndex("GroupId"); - b.ToTable("CollectionGroups", (string)null); + b.ToTable("CollectionGroups"); }); modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => @@ -216,7 +293,7 @@ namespace Bit.PostgresMigrations.Migrations b.HasIndex("UserId"); - b.ToTable("CollectionUsers", (string)null); + b.ToTable("CollectionUsers"); }); modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => @@ -648,6 +725,9 @@ namespace Bit.PostgresMigrations.Migrations b.Property("UseScim") .HasColumnType("boolean"); + b.Property("UseSecretsManager") + .HasColumnType("boolean"); + b.Property("UseSso") .HasColumnType("boolean"); @@ -836,6 +916,38 @@ namespace Bit.PostgresMigrations.Migrations b.ToTable("Policy", (string)null); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Provider", b => { b.Property("Id") @@ -958,6 +1070,44 @@ namespace Bit.PostgresMigrations.Migrations b.ToTable("ProviderUser", (string)null); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Send", b => { b.Property("Id") @@ -1015,6 +1165,32 @@ namespace Bit.PostgresMigrations.Migrations b.ToTable("Send", (string)null); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.SsoConfig", b => { b.Property("Id") @@ -1288,6 +1464,134 @@ namespace Bit.PostgresMigrations.Migrations b.ToTable("User", (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.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.AuthRequest", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Device", "ResponseDevice") @@ -1530,6 +1834,17 @@ namespace Bit.PostgresMigrations.Migrations b.Navigation("Organization"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.ProviderOrganization", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") @@ -1566,6 +1881,17 @@ namespace Bit.PostgresMigrations.Migrations b.Navigation("User"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Send", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") @@ -1581,6 +1907,17 @@ namespace Bit.PostgresMigrations.Migrations b.Navigation("User"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.SsoConfig", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") @@ -1624,6 +1961,96 @@ namespace Bit.PostgresMigrations.Migrations b.Navigation("User"); }); + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .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.Cipher", b => { b.Navigation("CollectionCiphers"); @@ -1669,6 +2096,15 @@ namespace Bit.PostgresMigrations.Migrations b.Navigation("CollectionUsers"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => { b.Navigation("Ciphers"); diff --git a/util/PostgresMigrations/packages.lock.json b/util/PostgresMigrations/packages.lock.json index 27cae9c36..840b75657 100644 --- a/util/PostgresMigrations/packages.lock.json +++ b/util/PostgresMigrations/packages.lock.json @@ -549,6 +549,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2757,6 +2766,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )", diff --git a/util/SqlServerEFScaffold/Factories.cs b/util/SqlServerEFScaffold/Factories.cs new file mode 100644 index 000000000..55c1b124e --- /dev/null +++ b/util/SqlServerEFScaffold/Factories.cs @@ -0,0 +1,36 @@ +using Bit.Core.Settings; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Design; +using Microsoft.Extensions.Configuration; + +namespace SqlServerEFScaffold; + +public static class GlobalSettingsFactory +{ + public static GlobalSettings GlobalSettings { get; } = new GlobalSettings(); + static GlobalSettingsFactory() + { + var configBuilder = new ConfigurationBuilder().AddUserSecrets(); + var Configuration = configBuilder.Build(); + ConfigurationBinder.Bind(Configuration.GetSection("GlobalSettings"), GlobalSettings); + } +} + +public class DatabaseContextFactory : IDesignTimeDbContextFactory +{ + public DatabaseContext CreateDbContext(string[] args) + { + var globalSettings = GlobalSettingsFactory.GlobalSettings; + var optionsBuilder = new DbContextOptionsBuilder(); + var connectionString = globalSettings.SqlServer?.ConnectionString; + if (string.IsNullOrWhiteSpace(connectionString)) + { + throw new Exception("No SqlServer connection string found."); + } + optionsBuilder.UseSqlServer( + connectionString, + b => b.MigrationsAssembly("SqlServerEFScaffold")); + return new DatabaseContext(optionsBuilder.Options); + } +} diff --git a/util/SqlServerEFScaffold/Migrations/DatabaseContextModelSnapshot.cs b/util/SqlServerEFScaffold/Migrations/DatabaseContextModelSnapshot.cs new file mode 100644 index 000000000..1ebfca382 --- /dev/null +++ b/util/SqlServerEFScaffold/Migrations/DatabaseContextModelSnapshot.cs @@ -0,0 +1,1729 @@ +// +using System; +using Bit.Infrastructure.EntityFramework.Repositories; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Bit.SqlServerEFScaffold.Migrations +{ + [DbContext(typeof(DatabaseContext))] + partial class DatabaseContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Attachments") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("DeletedDate") + .HasColumnType("datetime2"); + + b.Property("Favorites") + .HasColumnType("nvarchar(max)"); + + b.Property("Folders") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("Reprompt") + .HasColumnType("tinyint"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Cipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("nvarchar(300)"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Collection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.Property("CollectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("CipherId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("CollectionId", "CipherId"); + + b.HasIndex("CipherId"); + + b.ToTable("CollectionCipher", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.Property("CollectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("GroupId") + .HasColumnType("uniqueidentifier"); + + b.Property("HidePasswords") + .HasColumnType("bit"); + + b.Property("ReadOnly") + .HasColumnType("bit"); + + b.HasKey("CollectionId", "GroupId"); + + b.HasIndex("GroupId"); + + b.ToTable("CollectionGroups"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.Property("CollectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("HidePasswords") + .HasColumnType("bit"); + + b.Property("ReadOnly") + .HasColumnType("bit"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("PushToken") + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Device", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("GranteeId") + .HasColumnType("uniqueidentifier"); + + b.Property("GrantorId") + .HasColumnType("uniqueidentifier"); + + b.Property("KeyEncrypted") + .HasColumnType("nvarchar(max)"); + + b.Property("LastNotificationDate") + .HasColumnType("datetime2"); + + b.Property("RecoveryInitiatedDate") + .HasColumnType("datetime2"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("tinyint"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.Property("WaitTimeDays") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("GranteeId"); + + b.HasIndex("GrantorId"); + + b.ToTable("EmergencyAccess", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Event", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ActingUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("CipherId") + .HasColumnType("uniqueidentifier"); + + b.Property("CollectionId") + .HasColumnType("uniqueidentifier"); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.Property("DeviceType") + .HasColumnType("tinyint"); + + b.Property("GroupId") + .HasColumnType("uniqueidentifier"); + + b.Property("InstallationId") + .HasColumnType("uniqueidentifier"); + + b.Property("IpAddress") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("PolicyId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProviderId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProviderOrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProviderUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.ToTable("Event", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Folder", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Grant", b => + { + b.Property("Key") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ClientId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ConsumedDate") + .HasColumnType("datetime2"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("Description") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("SessionId") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("SubjectId") + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("Type") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.HasKey("Key"); + + b.ToTable("Grant", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AccessAll") + .HasColumnType("bit"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("nvarchar(300)"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Group", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.Property("GroupId") + .HasColumnType("uniqueidentifier"); + + b.Property("OrganizationUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + b.ToTable("GroupUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Installation", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("Key") + .HasMaxLength(150) + .HasColumnType("nvarchar(150)"); + + b.HasKey("Id"); + + b.ToTable("Installation", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("BillingEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("BusinessAddress1") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("BusinessAddress2") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("BusinessAddress3") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("BusinessCountry") + .HasMaxLength(2) + .HasColumnType("nvarchar(2)"); + + b.Property("BusinessName") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("BusinessTaxNumber") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("Gateway") + .HasColumnType("tinyint"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Identifier") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("MaxAutoscaleSeats") + .HasColumnType("int"); + + b.Property("MaxCollections") + .HasColumnType("smallint"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("OwnersNotifiedOfAutoscaling") + .HasColumnType("datetime2"); + + b.Property("Plan") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("PlanType") + .HasColumnType("tinyint"); + + b.Property("PrivateKey") + .HasColumnType("nvarchar(max)"); + + b.Property("PublicKey") + .HasColumnType("nvarchar(max)"); + + b.Property("ReferenceData") + .HasColumnType("nvarchar(max)"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Seats") + .HasColumnType("int"); + + b.Property("SelfHost") + .HasColumnType("bit"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("nvarchar(max)"); + + b.Property("Use2fa") + .HasColumnType("bit"); + + b.Property("UseApi") + .HasColumnType("bit"); + + b.Property("UseDirectory") + .HasColumnType("bit"); + + b.Property("UseEvents") + .HasColumnType("bit"); + + b.Property("UseGroups") + .HasColumnType("bit"); + + b.Property("UseKeyConnector") + .HasColumnType("bit"); + + b.Property("UsePolicies") + .HasColumnType("bit"); + + b.Property("UseResetPassword") + .HasColumnType("bit"); + + b.Property("UseScim") + .HasColumnType("bit"); + + b.Property("UseSso") + .HasColumnType("bit"); + + b.Property("UseTotp") + .HasColumnType("bit"); + + b.Property("UsersGetPremium") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("Organization", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("ApiKey") + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationApiKey", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Config") + .HasColumnType("nvarchar(max)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("OrganizationConnection", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("FriendlyName") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("LastSyncDate") + .HasColumnType("datetime2"); + + b.Property("OfferedToEmail") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("PlanSponsorshipType") + .HasColumnType("tinyint"); + + b.Property("SponsoredOrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("SponsoringOrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("SponsoringOrganizationUserId") + .HasColumnType("uniqueidentifier"); + + b.Property("ToDelete") + .HasColumnType("bit"); + + b.Property("ValidUntil") + .HasColumnType("datetime2"); + + 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("uniqueidentifier"); + + b.Property("AccessAll") + .HasColumnType("bit"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("ExternalId") + .HasMaxLength(300) + .HasColumnType("nvarchar(300)"); + + b.Property("Key") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("Permissions") + .HasColumnType("nvarchar(max)"); + + b.Property("ResetPasswordKey") + .HasColumnType("nvarchar(max)"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("smallint"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + 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("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Policy", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Project", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DeletedDate") + .HasColumnType("datetime2"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + SqlServerKeyBuilderExtensions.IsClustered(b.HasKey("Id")); + + b.HasIndex("DeletedDate"); + + SqlServerIndexBuilderExtensions.IsClustered(b.HasIndex("DeletedDate"), false); + + b.HasIndex("OrganizationId"); + + SqlServerIndexBuilderExtensions.IsClustered(b.HasIndex("OrganizationId"), false); + + b.ToTable("Project", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Provider", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("BillingEmail") + .HasColumnType("nvarchar(max)"); + + b.Property("BusinessAddress1") + .HasColumnType("nvarchar(max)"); + + b.Property("BusinessAddress2") + .HasColumnType("nvarchar(max)"); + + b.Property("BusinessAddress3") + .HasColumnType("nvarchar(max)"); + + b.Property("BusinessCountry") + .HasColumnType("nvarchar(max)"); + + b.Property("BusinessName") + .HasColumnType("nvarchar(max)"); + + b.Property("BusinessTaxNumber") + .HasColumnType("nvarchar(max)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("tinyint"); + + b.Property("UseEvents") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("Provider", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ProviderOrganization", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Key") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("ProviderId") + .HasColumnType("uniqueidentifier"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Settings") + .HasColumnType("nvarchar(max)"); + + 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("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Email") + .HasColumnType("nvarchar(max)"); + + b.Property("Key") + .HasColumnType("nvarchar(max)"); + + b.Property("Permissions") + .HasColumnType("nvarchar(max)"); + + b.Property("ProviderId") + .HasColumnType("uniqueidentifier"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Status") + .HasColumnType("tinyint"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("ProviderId"); + + b.HasIndex("UserId"); + + b.ToTable("ProviderUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Secret", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("DeletedDate") + .HasColumnType("datetime2"); + + b.Property("Key") + .HasColumnType("nvarchar(max)"); + + b.Property("Note") + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Value") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + SqlServerKeyBuilderExtensions.IsClustered(b.HasKey("Id")); + + b.HasIndex("DeletedDate"); + + SqlServerIndexBuilderExtensions.IsClustered(b.HasIndex("DeletedDate"), false); + + b.HasIndex("OrganizationId"); + + SqlServerIndexBuilderExtensions.IsClustered(b.HasIndex("OrganizationId"), false); + + b.ToTable("Secret", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Send", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("AccessCount") + .HasColumnType("int"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("DeletionDate") + .HasColumnType("datetime2"); + + b.Property("Disabled") + .HasColumnType("bit"); + + b.Property("ExpirationDate") + .HasColumnType("datetime2"); + + b.Property("HideEmail") + .HasColumnType("bit"); + + b.Property("Key") + .HasColumnType("nvarchar(max)"); + + b.Property("MaxAccessCount") + .HasColumnType("int"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("Password") + .HasMaxLength(300) + .HasColumnType("nvarchar(300)"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("Send", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Data") + .HasColumnType("nvarchar(max)"); + + b.Property("Enabled") + .HasColumnType("bit"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("SsoConfig", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("ExternalId") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.HasIndex("UserId"); + + b.ToTable("SsoUser", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.TaxRate", b => + { + b.Property("Id") + .HasMaxLength(40) + .HasColumnType("nvarchar(40)"); + + b.Property("Active") + .HasColumnType("bit"); + + b.Property("Country") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("PostalCode") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("Rate") + .HasColumnType("decimal(18,2)"); + + b.Property("State") + .HasMaxLength(2) + .HasColumnType("nvarchar(2)"); + + b.HasKey("Id"); + + b.ToTable("TaxRate", (string)null); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.Property("Id") + .HasColumnType("uniqueidentifier"); + + b.Property("Amount") + .HasColumnType("decimal(18,2)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Details") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Gateway") + .HasColumnType("tinyint"); + + b.Property("GatewayId") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("OrganizationId") + .HasColumnType("uniqueidentifier"); + + b.Property("PaymentMethodType") + .HasColumnType("tinyint"); + + b.Property("Refunded") + .HasColumnType("bit"); + + b.Property("RefundedAmount") + .HasColumnType("decimal(18,2)"); + + b.Property("Type") + .HasColumnType("tinyint"); + + b.Property("UserId") + .HasColumnType("uniqueidentifier"); + + 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("uniqueidentifier"); + + b.Property("AccountRevisionDate") + .HasColumnType("datetime2"); + + b.Property("ApiKey") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Culture") + .HasMaxLength(10) + .HasColumnType("nvarchar(10)"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("nvarchar(256)"); + + b.Property("EmailVerified") + .HasColumnType("bit"); + + b.Property("EquivalentDomains") + .HasColumnType("nvarchar(max)"); + + b.Property("ExcludedGlobalEquivalentDomains") + .HasColumnType("nvarchar(max)"); + + b.Property("FailedLoginCount") + .HasColumnType("int"); + + b.Property("ForcePasswordReset") + .HasColumnType("bit"); + + b.Property("Gateway") + .HasColumnType("tinyint"); + + b.Property("GatewayCustomerId") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("GatewaySubscriptionId") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Kdf") + .HasColumnType("tinyint"); + + b.Property("KdfIterations") + .HasColumnType("int"); + + b.Property("Key") + .HasColumnType("nvarchar(max)"); + + b.Property("LastFailedLoginDate") + .HasColumnType("datetime2"); + + b.Property("LicenseKey") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("MasterPassword") + .HasMaxLength(300) + .HasColumnType("nvarchar(300)"); + + b.Property("MasterPasswordHint") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("MaxStorageGb") + .HasColumnType("smallint"); + + b.Property("Name") + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Premium") + .HasColumnType("bit"); + + b.Property("PremiumExpirationDate") + .HasColumnType("datetime2"); + + b.Property("PrivateKey") + .HasColumnType("nvarchar(max)"); + + b.Property("PublicKey") + .HasColumnType("nvarchar(max)"); + + b.Property("ReferenceData") + .HasColumnType("nvarchar(max)"); + + b.Property("RenewalReminderDate") + .HasColumnType("datetime2"); + + b.Property("RevisionDate") + .HasColumnType("datetime2"); + + b.Property("SecurityStamp") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("nvarchar(50)"); + + b.Property("Storage") + .HasColumnType("bigint"); + + b.Property("TwoFactorProviders") + .HasColumnType("nvarchar(max)"); + + b.Property("TwoFactorRecoveryCode") + .HasMaxLength(32) + .HasColumnType("nvarchar(32)"); + + b.Property("UnknownDeviceVerificationEnabled") + .HasColumnType("bit"); + + b.Property("UsesKeyConnector") + .HasColumnType("bit"); + + b.HasKey("Id"); + + b.ToTable("User", (string)null); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.Property("ProjectsId") + .HasColumnType("uniqueidentifier"); + + b.Property("SecretsId") + .HasColumnType("uniqueidentifier"); + + b.HasKey("ProjectsId", "SecretsId"); + + b.HasIndex("SecretsId"); + + b.ToTable("ProjectSecret"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Ciphers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Ciphers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Cipher", "Cipher") + .WithMany("CollectionCiphers") + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionCiphers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionGroups") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionUsers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("CollectionUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("CollectionUsers") + .HasForeignKey("UserId"); + + b.Navigation("Collection"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantee") + .WithMany() + .HasForeignKey("GranteeId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantor") + .WithMany() + .HasForeignKey("GrantorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grantee"); + + b.Navigation("Grantor"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Groups") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany("GroupUsers") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("GroupUsers") + .HasForeignKey("UserId"); + + b.Navigation("Group"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("ApiKeys") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Connections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoredOrganization") + .WithMany() + .HasForeignKey("SponsoredOrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoringOrganization") + .WithMany() + .HasForeignKey("SponsoringOrganizationId"); + + b.Navigation("SponsoredOrganization"); + + b.Navigation("SponsoringOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("OrganizationUsers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("OrganizationUsers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Policies") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.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.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.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.Models.Send", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoConfig", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoConfigs") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoUsers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("SsoUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Transactions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Navigation("CollectionCiphers"); + + b.Navigation("CollectionGroups"); + + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("Ciphers"); + + b.Navigation("Connections"); + + b.Navigation("Groups"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("Policies"); + + b.Navigation("SsoConfigs"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("CollectionUsers"); + + b.Navigation("Folders"); + + b.Navigation("GroupUsers"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/SqlServerEFScaffold/README.MD b/util/SqlServerEFScaffold/README.MD new file mode 100644 index 000000000..fa866152f --- /dev/null +++ b/util/SqlServerEFScaffold/README.MD @@ -0,0 +1,27 @@ +## Usage + +The SqlServerEFScaffold project is intended to be used as a tool for developers to validate their Microsoft SQL Server database changes and Infrastructure.EntityFramework.Models stay in sync for entity framework MS SQL Server repositories. + +## Check Infrastructure.EntityFramework.Models (Database First) + +Run the following: + +```dotnet ef dbcontext scaffold "" Microsoft.EntityFrameworkCore.SqlServer -o Model``` + +The dotnet entity framework command will generate models from the local database provided. + +Engineers can reference these models and validate they match with Infrastructure.EntityFramework.Models. + + +## Check Microsoft SQL Server Database changes (Code/Model First) + +Run the following: + +``` +dotnet ef migrations add Init +dotnet ef migrations script +``` + +This will generate a SQL script to initialize a database based on the models in Infrastructure.EntityFramework.Models. + +This is helpful to check against the proposed database changes provided in /src/SQL \ No newline at end of file diff --git a/util/SqlServerEFScaffold/SqlServerEFScaffold.csproj b/util/SqlServerEFScaffold/SqlServerEFScaffold.csproj new file mode 100644 index 000000000..e9e56f909 --- /dev/null +++ b/util/SqlServerEFScaffold/SqlServerEFScaffold.csproj @@ -0,0 +1,18 @@ + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + + diff --git a/util/SqlServerEFScaffold/packages.lock.json b/util/SqlServerEFScaffold/packages.lock.json new file mode 100644 index 000000000..ac6b719f2 --- /dev/null +++ b/util/SqlServerEFScaffold/packages.lock.json @@ -0,0 +1,2894 @@ +{ + "version": 1, + "dependencies": { + "net6.0": { + "Microsoft.EntityFrameworkCore.Design": { + "type": "Direct", + "requested": "[6.0.4, )", + "resolved": "6.0.4", + "contentHash": "NOAtatJPq/xDa+vqfxL5+OwCKv83N/JX/IPgY6VQZ95KUtV9uuC+mVPsremG3a9UM3tPfK4CXMh1rwiaZHYCPQ==", + "dependencies": { + "Humanizer.Core": "2.8.26", + "Microsoft.EntityFrameworkCore.Relational": "6.0.4" + } + }, + "AspNetCoreRateLimit": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "FzXAJFgaRjKfnKAVwjEEC7OAGQM5v/I3sQw2tpzmR0yHTCGhUAxZzDuwZiXTk8XLrI6vovzkqKkfKmiDl3nYMg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.1", + "Microsoft.Extensions.Options": "6.0.0", + "Newtonsoft.Json": "13.0.1" + } + }, + "AspNetCoreRateLimit.Redis": { + "type": "Transitive", + "resolved": "1.0.1", + "contentHash": "CsSGy/7SXt6iBOKg0xCvsRjb/ZHshbtr2Of1MHc912L2sLnZqadUrTboyXZC+ZlgEBeJ14GyjPTu8ZyfEhGUnw==", + "dependencies": { + "AspNetCoreRateLimit": "4.0.2", + "StackExchange.Redis": "2.5.43" + } + }, + "AutoMapper": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "+596AnKykYCk9RxXCEF4GYuapSebQtFVvIA1oVG1rrRkCLAC7AkWehJ0brCfYUbdDW3v1H/p0W3hob7JoXGjMw==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "AutoMapper.Extensions.Microsoft.DependencyInjection": { + "type": "Transitive", + "resolved": "11.0.0", + "contentHash": "0asw5WxdCFh2OTi9Gv+oKyH9SzxwYQSnO8TV5Dd0GggovILzJW4UimP26JAcxc3yB5NnC5urooZ1BBs8ElpiBw==", + "dependencies": { + "AutoMapper": "11.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "AWSSDK.Core": { + "type": "Transitive", + "resolved": "3.7.10.11", + "contentHash": "B+M7ggPC0FogATRPQxDXL0eTusCQtXulW4zCuX39yiHV8+u9MEXRytcAw0ZA3zFBYYx6ovl9lklho6OQo1DRRQ==" + }, + "AWSSDK.SimpleEmail": { + "type": "Transitive", + "resolved": "3.7.0.150", + "contentHash": "rc/4ZnISfbgTfqz5/BWqMHBAzk4R09qfe1xkdJf2jXo44Zn2X72W8IiLLweBtmNhL7d8Tcf6UCtOHYkFwxHvug==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "AWSSDK.SQS": { + "type": "Transitive", + "resolved": "3.7.2.47", + "contentHash": "RPTVBsY333n+aIEqw148Envx9OQkE1/jhjlioNXDP6BrA3fAPN9A+2HoA02c0KSp/sazXYWg8w/kDL8FchH8Dw==", + "dependencies": { + "AWSSDK.Core": "[3.7.10.11, 4.0.0)" + } + }, + "Azure.Core": { + "type": "Transitive", + "resolved": "1.24.0", + "contentHash": "+/qI1j2oU1S4/nvxb2k/wDsol00iGf1AyJX5g3epV7eOpQEP/2xcgh/cxgKMeFgn3U2fmgSiBnQZdkV+l5y0Uw==", + "dependencies": { + "Microsoft.Bcl.AsyncInterfaces": "1.1.1", + "System.Diagnostics.DiagnosticSource": "4.6.0", + "System.Memory.Data": "1.0.2", + "System.Numerics.Vectors": "4.5.0", + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.7.2", + "System.Threading.Tasks.Extensions": "4.5.4" + } + }, + "Azure.Extensions.AspNetCore.DataProtection.Blobs": { + "type": "Transitive", + "resolved": "1.2.1", + "contentHash": "wxvkC6DeWThBtaPbsWdicp5Ltya4J8JuhxmZJDQkhnXG7oihfu8RqBV6w/X1nMieuIOq1qQaGTvjx7nEHHfxSQ==", + "dependencies": { + "Azure.Core": "1.14.0", + "Azure.Storage.Blobs": "12.8.0", + "Microsoft.AspNetCore.DataProtection": "2.1.0" + } + }, + "Azure.Identity": { + "type": "Transitive", + "resolved": "1.3.0", + "contentHash": "l1SYfZKOFBuUFG7C2SWHmJcrQQaiXgBdVCycx4vcZQkC6efDVt7mzZ5pfJAFEJDBUq7mjRQ0RPq9ZDGdSswqMg==", + "dependencies": { + "Azure.Core": "1.6.0", + "Microsoft.Identity.Client": "4.22.0", + "Microsoft.Identity.Client.Extensions.Msal": "2.16.5", + "System.Memory": "4.5.3", + "System.Security.Cryptography.ProtectedData": "4.5.0", + "System.Text.Json": "4.6.0", + "System.Threading.Tasks.Extensions": "4.5.2" + } + }, + "Azure.Messaging.EventGrid": { + "type": "Transitive", + "resolved": "4.10.0", + "contentHash": "X3dh3Cek/7wFPUrBJ2KbnkJteGjWvKBoSBmD/uQm8reMIavCFTKhnl95F937eLn/2cSsm5l3oPHtYPFtDerA7Q==", + "dependencies": { + "Azure.Core": "1.24.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Blobs": { + "type": "Transitive", + "resolved": "12.11.0", + "contentHash": "50eRjIhY7Q1JN7kT2MSawDKCcwSb7uRZUkz00P/BLjSg47gm2hxUYsnJPyvzCHntYMbOWzrvaVQTwYwXabaR5Q==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Text.Json": "4.7.2" + } + }, + "Azure.Storage.Common": { + "type": "Transitive", + "resolved": "12.10.0", + "contentHash": "vYkHGzUkdZTace/cDPZLG+Mh/EoPqQuGxDIBOau9D+XWoDPmuUFGk325aXplkFE4JFGpSwoytNYzk/qBCaiHqg==", + "dependencies": { + "Azure.Core": "1.22.0", + "System.IO.Hashing": "6.0.0" + } + }, + "Azure.Storage.Queues": { + "type": "Transitive", + "resolved": "12.9.0", + "contentHash": "jDiyHtsCUCrWNvZW7SjJnJb46UhpdgQrWCbL8aWpapDHlq9LvbvxYpfLh4dfKAz09QiTznLMIU3i+md9+7GzqQ==", + "dependencies": { + "Azure.Storage.Common": "12.10.0", + "System.Memory.Data": "1.0.2", + "System.Text.Json": "4.7.2" + } + }, + "BitPay.Light": { + "type": "Transitive", + "resolved": "1.0.1907", + "contentHash": "QTTIgXakHrRNQPxNyH7bZ7frm0bI8N6gRDtiqVyKG/QYQ+KfjN70xt0zQ0kO0zf8UBaKuwcV5B7vvpXtzR9ijg==", + "dependencies": { + "Newtonsoft.Json": "12.0.2" + } + }, + "Braintree": { + "type": "Transitive", + "resolved": "5.12.0", + "contentHash": "bV2tsVIvBQeKwULT4qPZUWhxSr8mFwyAAcvLDvDpCU0cMYPHzGSahha+ghUdgGMb317BqL34/Od59n2s3MkhOQ==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "System.Xml.XPath.XmlDocument": "4.3.0" + } + }, + "Dapper": { + "type": "Transitive", + "resolved": "2.0.123", + "contentHash": "RDFF4rBLLmbpi6pwkY7q/M6UXHRJEOerplDGE5jwEkP/JGJnBauAClYavNKJPW1yOTWRPIyfj4is3EaJxQXILQ==" + }, + "Fido2": { + "type": "Transitive", + "resolved": "3.0.0-beta2", + "contentHash": "FnNMbK88dyPp0Ww/iMim5g89rSPdqkjQiDiTJJtvxDcEk8JK/eBdTzAl4myNaKS9e8PKrxxddOTrnNja3PHGtQ==", + "dependencies": { + "Fido2.Models": "3.0.0-beta2", + "NSec.Cryptography": "20.2.0", + "System.Formats.Cbor": "5.0.0", + "System.IdentityModel.Tokens.Jwt": "6.6.0" + } + }, + "Fido2.AspNet": { + "type": "Transitive", + "resolved": "3.0.0-beta2", + "contentHash": "qkowZS0WPS26gDG97rwjZObOa/xtFVjSpvWHl3OwWRQ9ZU5xNePXKk2XJWmO2MCQc40idxyEOfA34MMexCHc3w==", + "dependencies": { + "Fido2": "3.0.0-beta2", + "Fido2.Models": "3.0.0-beta2" + } + }, + "Fido2.Models": { + "type": "Transitive", + "resolved": "3.0.0-beta2", + "contentHash": "6ePSMUtqz6lAfDUjDvOONMLugcKiAyz8hzoLSAISk3iDIjBMLMPlZSV3TVZqiY+5SAzC8x61OHNoCODqorucNw==" + }, + "Handlebars.Net": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "p60QyeBYpZmcZdIXRMqs9XySIBaxJ0lj3+QD0EJVr4ybTigOTCumXMMin5dPwjo9At1UwkDZ3gGwa1lmGjG6DA==", + "dependencies": { + "Microsoft.CSharp": "4.7.0" + } + }, + "Humanizer.Core": { + "type": "Transitive", + "resolved": "2.8.26", + "contentHash": "OiKusGL20vby4uDEswj2IgkdchC1yQ6rwbIkZDVBPIR6al2b7n3pC91elBul9q33KaBgRKhbZH3+2Ur4fnWx2A==" + }, + "IdentityModel": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "b18wrIx5wnZlMxAX7oVsE+nDtAJ4hajYlH0xPlaRvo4r/fz08K6pPeZvbiqS9nfNbzfIgLFmNX+FL9qR9ZR5PA==", + "dependencies": { + "Newtonsoft.Json": "11.0.2", + "System.Text.Encodings.Web": "4.7.0" + } + }, + "IdentityModel.AspNetCore.OAuth2Introspection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "ZNdMZMaj9fqR3j50vYsu+1U3QGd6n8+fqwf+a8mCTcmXGor+HgFDfdq0mM34bsmD6uEgAQup7sv2ZW5kR36dbA==", + "dependencies": { + "IdentityModel": "4.0.0" + } + }, + "IdentityServer4": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "blaxxGuOA7v/w1q+fxn97wZ+x2ecG1ZD4mc/N/ZOXMNeFZZhqv+4LF26Gecyik3nWrJPmbMEtQbLmRsKG8k61w==", + "dependencies": { + "IdentityModel": "4.4.0", + "IdentityServer4.Storage": "4.1.2", + "Microsoft.AspNetCore.Authentication.OpenIdConnect": "3.1.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.6.0", + "Newtonsoft.Json": "12.0.2" + } + }, + "IdentityServer4.AccessTokenValidation": { + "type": "Transitive", + "resolved": "3.0.1", + "contentHash": "qu/M6UyN4o9NVep7q545Ms7hYAnsQqSdLbN1Fjjrn4m35lyBfeQPSSNzDryAKHbodyWOQfHaOqKEyMEJQ5Rpgw==", + "dependencies": { + "IdentityModel.AspNetCore.OAuth2Introspection": "4.0.1", + "Microsoft.AspNetCore.Authentication.JwtBearer": "3.0.0" + } + }, + "IdentityServer4.Storage": { + "type": "Transitive", + "resolved": "4.1.2", + "contentHash": "KoSffyZyyeCNTIyJiZnCuPakJ1QbCHlpty6gbWUj/7yl+w0PXIchgmmJnJSvddzBb8iZ2xew/vGlxWUIP17P2g==", + "dependencies": { + "IdentityModel": "4.4.0" + } + }, + "libsodium": { + "type": "Transitive", + "resolved": "1.0.18", + "contentHash": "Ajv3AR9Qg/C4SQcE2ONx/UieeKnn5lSvVNc6egC3p6NP6qjZzWJ+Xg2vJURNYjkpHui/KctBwQjMPqpZK8/CHA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1" + } + }, + "linq2db": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "6/u1EzQlV25bhN0Ej/I5dLV5Hgxun+ww/TX2VnMBnSVytED2VzQGeFIO/14I624GkfPOtB79x1ooL3F18dAbdw==" + }, + "linq2db.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.11.0", + "contentHash": "mS+L6HyVHP3oJaTuFVZswNmPpTfYleGjDTo2IWBJmYXZpSQ5EPw1DpHzmyLAiQd+93ofy0Ala+9HWzv6/k73ZQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "6.0.5", + "linq2db": "4.4.0" + } + }, + "MailKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "5MTpTqmjqT7HPvYbP3HozRZMth5vSaT0ReN0iM3rAM4CgLI/R1qqtLDDNWGnFFIlcNzeJkZQRJJMkv8cgzWBbA==", + "dependencies": { + "MimeKit": "3.2.0" + } + }, + "Microsoft.AspNetCore.Authentication.JwtBearer": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "joDS3+lD1i9qcdFLWP4D316t3bHpezmTNOzbMIf9ZcRPX4QTuiUutZcQn/kZplf3BiLHqwUChZXxPjCAMKaKAQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.10.0" + } + }, + "Microsoft.AspNetCore.Authentication.OpenIdConnect": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "O1cAQYUTU8EfRqwc5/rfTns4E4hKlFlg59fuKRrST+PzsxI6H07KqRN/JjdYhAuVYxF8jPnIGbj+zuc5paOWUw==", + "dependencies": { + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "5.5.0" + } + }, + "Microsoft.AspNetCore.Cryptography.Internal": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "/0FX1OqckMmXAAlsHgBFNymTZuq4nuAOMhiwm6e8CEMi2aOjnMYwiMc7mtvpGTAO0O4C0zwx+iaChxDgvqit2A==" + }, + "Microsoft.AspNetCore.Cryptography.KeyDerivation": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "1Lbwrxg/HRY/nbrkcrB3EUXUYQN8Tkw7Ktgb6/2on2P7ybT5aM59H05gk+OBC8ZTBxwdle9e1tyT3wxEYKw5xw==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "6.0.4" + } + }, + "Microsoft.AspNetCore.DataProtection": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "G+UoMHL0xiyFh30wkL7Bv/XL6eugTAKYhLPS53k1/Me1bYRwOOw+8VL/q0ppq3/yMzpHX+MkExaCTDlYl48FgA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.Internal": "2.1.0", + "Microsoft.AspNetCore.DataProtection.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.1.0", + "Microsoft.Extensions.Logging.Abstractions": "2.1.0", + "Microsoft.Extensions.Options": "2.1.0", + "Microsoft.Win32.Registry": "4.5.0", + "System.Security.Cryptography.Xml": "4.5.0", + "System.Security.Principal.Windows": "4.5.0" + } + }, + "Microsoft.AspNetCore.DataProtection.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "2+HVDhUqrnV9+EJNEewSy+Gk4hOVPzLPMpFDZI7kuH7NWxtbNkI6A6gT5lO2/kEPMyM8/iLWtohbOwjpC9rHVw==" + }, + "Microsoft.AspNetCore.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "1TQgBfd/NPZLR2o/h6l5Cml2ZCF5hsyV4h9WEwWwAIavrbdTnaNozGGcTOd4AOgQvogMM9UM1ajflm9Cwd0jLQ==", + "dependencies": { + "Microsoft.AspNetCore.Hosting.Server.Abstractions": "2.1.0", + "Microsoft.AspNetCore.Http.Abstractions": "2.1.0", + "Microsoft.Extensions.Hosting.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Hosting.Server.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "YTKMi2vHX6P+WHEVpW/DS+eFHnwivCSMklkyamcK1ETtc/4j8H3VR0kgW8XIBqukNxhD8k5wYt22P7PhrWSXjQ==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "Microsoft.Extensions.Configuration.Abstractions": "2.1.0" + } + }, + "Microsoft.AspNetCore.Http.Abstractions": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "vbFDyKsSYBnxl3+RABtN79b0vsTcG66fDY8vD6Nqvu9uLtSej70Q5NcbGlnN6bJpZci5orSdgFTHMhBywivDPg==", + "dependencies": { + "Microsoft.AspNetCore.Http.Features": "2.1.0", + "System.Text.Encodings.Web": "4.5.0" + } + }, + "Microsoft.AspNetCore.Http.Features": { + "type": "Transitive", + "resolved": "2.1.0", + "contentHash": "UmkUePxRjsQW0j5euFFscBwjvTu25b8+qIK/2fI3GvcqQ+mkwgbWNAT8b/Gkoei1m2bTWC07lSdutuRDPPLcJA==", + "dependencies": { + "Microsoft.Extensions.Primitives": "2.1.0" + } + }, + "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" + } + }, + "Microsoft.Azure.Cosmos": { + "type": "Transitive", + "resolved": "3.24.0", + "contentHash": "QpUe5ho6OzlXwgcJVgAmOR7t3XLC9RI4t8T96RZY61pSOIllPOJdp30L0LwA16tKcqi5r2KayEgWO/MS9fh/6A==", + "dependencies": { + "Azure.Core": "1.3.0", + "Microsoft.Bcl.AsyncInterfaces": "1.0.0", + "Microsoft.Bcl.HashCode": "1.1.0", + "Newtonsoft.Json": "10.0.2", + "System.Buffers": "4.5.1", + "System.Collections.Immutable": "1.7.0", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Memory": "4.5.4", + "System.Numerics.Vectors": "4.5.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3", + "System.Threading.Tasks.Extensions": "4.5.4", + "System.ValueTuple": "4.5.0" + } + }, + "Microsoft.Azure.Cosmos.Table": { + "type": "Transitive", + "resolved": "1.0.8", + "contentHash": "ToeEd1yijM7nQfLYvdFLG//RjKPmfqm45eOm86UAKrxtyGI/CXqP8iL74mzBp6mZ9A/K/ZYA2fVdpH0xHR5Keg==", + "dependencies": { + "Microsoft.Azure.DocumentDB.Core": "2.11.2", + "Microsoft.OData.Core": "7.6.4", + "Newtonsoft.Json": "10.0.2" + } + }, + "Microsoft.Azure.DocumentDB.Core": { + "type": "Transitive", + "resolved": "2.11.2", + "contentHash": "cA8eWrTFbYrkHrz095x4CUGb7wqQgA1slzFZCYexhNwz6Zcn3v+S1yvWMGwGRmRjT0MKU9tYdFWgLfT0OjSycw==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "Newtonsoft.Json": "9.0.1", + "System.Collections.Immutable": "1.3.0", + "System.Collections.NonGeneric": "4.0.1", + "System.Collections.Specialized": "4.0.1", + "System.Diagnostics.TraceSource": "4.0.0", + "System.Dynamic.Runtime": "4.0.11", + "System.Linq.Queryable": "4.0.1", + "System.Net.Http": "4.3.4", + "System.Net.NameResolution": "4.0.0", + "System.Net.NetworkInformation": "4.1.0", + "System.Net.Requests": "4.0.11", + "System.Net.Security": "4.3.2", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Security.SecureString": "4.0.0" + } + }, + "Microsoft.Azure.NotificationHubs": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "C2SssjX3e6/HIo1OCImQDDVOn64d1+gkgEmgxJryzkwixyivJHWH2YIgxZs33pyzVQcZWx5PR2tqLkQ7riSq8Q==", + "dependencies": { + "Microsoft.Extensions.Caching.Memory": "3.1.8", + "Newtonsoft.Json": "12.0.3" + } + }, + "Microsoft.Azure.ServiceBus": { + "type": "Transitive", + "resolved": "5.2.0", + "contentHash": "wyZNJggyFNtKxd+HgvcTiuRYuTjDGi+pgE4RcBvFbfvNiarKr5AOlE4Ne7on1eUJZuMuEa19wN5dj694HlP60A==", + "dependencies": { + "Microsoft.Azure.Amqp": "2.4.11", + "Microsoft.Azure.Services.AppAuthentication": "[1.0.3, 2.0.0)", + "Newtonsoft.Json": "10.0.3", + "System.Diagnostics.DiagnosticSource": "4.5.1", + "System.IdentityModel.Tokens.Jwt": "5.4.0" + } + }, + "Microsoft.Azure.Services.AppAuthentication": { + "type": "Transitive", + "resolved": "1.0.3", + "contentHash": "ywpQaK1klu1IoX4VUf+TBmU4kR71aWNI6O5rEIJU8z28L2xhJhnIm7k2Nf1Zu/PygeuOtt5g0QPCk5+lLltbeQ==", + "dependencies": { + "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.14.2", + "NETStandard.Library": "1.6.1", + "System.Diagnostics.Process": "4.3.0" + } + }, + "Microsoft.Bcl.AsyncInterfaces": { + "type": "Transitive", + "resolved": "1.1.1", + "contentHash": "yuvf07qFWFqtK3P/MRkEKLhn5r2UbSpVueRziSqj0yJQIKFwG1pq9mOayK3zE5qZCTs0CbrwL9M6R8VwqyGy2w==" + }, + "Microsoft.Bcl.HashCode": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "J2G1k+u5unBV+aYcwxo94ip16Rkp65pgWFb0R6zwJipzWNMgvqlWeuI7/+R+e8bob66LnSG+llLJ+z8wI94cHg==" + }, + "Microsoft.CSharp": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" + }, + "Microsoft.Data.SqlClient": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "o/sIRlcKEcI9vg5z9USqJ/VCxtUUBYEOXYr4TrkMNu+gGBh0KfUi06Jqpe+xZgeoxcqYruV9dLOn046uFA4vHQ==", + "dependencies": { + "Azure.Identity": "1.3.0", + "Microsoft.Data.SqlClient.SNI.runtime": "4.0.0", + "Microsoft.Identity.Client": "4.22.0", + "Microsoft.IdentityModel.JsonWebTokens": "6.8.0", + "Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.8.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Buffers": "4.5.1", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Diagnostics.DiagnosticSource": "5.0.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime.Caching": "5.0.0", + "System.Security.Cryptography.Cng": "5.0.0", + "System.Security.Principal.Windows": "5.0.0", + "System.Text.Encoding.CodePages": "5.0.0", + "System.Text.Encodings.Web": "4.7.2" + } + }, + "Microsoft.Data.SqlClient.SNI.runtime": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "wtLlRwQX7YoBUYm25xBjJ3UsuLgycme1xXqDn8t3S5kPCWiZrx8uOkyZHLKzH4kkCiQ9m2/J5JeCKNRbZNn3Qg==" + }, + "Microsoft.Data.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bui5wPPqq9OwTL5A+YJPcVStTPrOFcLwg/kAVWyqdjrTief4kTK/3bNv0MqUDVNgAUG8pcFbtdc674CIh1F3gw==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "xb10XFoPf/gWu8ik5v7xnVyUY7W21LBOLtT7PidzwYVdnE3aKuQ/bIZLcQuY7rdDNT89/wse2q5FRjm207cIMQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Analyzers": "6.0.12", + "Microsoft.Extensions.Caching.Memory": "6.0.1", + "Microsoft.Extensions.DependencyInjection": "6.0.1", + "Microsoft.Extensions.Logging": "6.0.0", + "System.Collections.Immutable": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Abstractions": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "hvRytAcLhrb35HmtMjYWsNZZLt39ryuN7j04lDchRa9VToreyqgo5gMniTdQ6MfCflxtGnDes65V/Y2pjbEyWg==" + }, + "Microsoft.EntityFrameworkCore.Analyzers": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "ZDUY+KlsIyKdfvIJeNdqRiPExFQ5GRZVdx/Cp52vhpCJRImYv34O0Xfmw2eiLu4qe1jmM2pTzAAFKELaKwtj/w==" + }, + "Microsoft.EntityFrameworkCore.Relational": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "HBtRGHtF0Vf+BIQTkRGiopmE5rLYhj59xPpd17S1tLgYpiHDVbepCuHwh5H63fzjO99Z4tW5wmmEGF7KnD91WQ==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "2Hutlqt07bnWZFtYqT1lj0otX8ygMyBikysGnfQNF2TK3i5GqSTeJ8tqNi/URiI9II7Cyl15A0rflXmFoySuIw==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Sqlite.Core": "6.0.12", + "SQLitePCLRaw.bundle_e_sqlite3": "2.1.2" + } + }, + "Microsoft.EntityFrameworkCore.Sqlite.Core": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "07vKE7+t9Z2BfGmHuJwNZNv8m1GWt7ZpYYHFh1tQg1oC6FJ78bSaFzLawsf2NK6CLhbB8DBsjE0rRhxMJ4rXsA==", + "dependencies": { + "Microsoft.Data.Sqlite.Core": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Microsoft.Extensions.DependencyModel": "6.0.0" + } + }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, + "Microsoft.Extensions.ApiDescription.Server": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "LH4OE/76F6sOCslif7+Xh3fS/wUUrE5ryeXAMcoCnuwOQGT5Smw0p57IgDh/pHgHaGz/e+AmEQb7pRgb++wt0w==" + }, + "Microsoft.Extensions.Caching.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "bcz5sSFJbganH0+YrfvIjJDIcKNW7TL07C4d1eTmXy/wOt52iz4LVogJb6pazs7W0+74j0YpXFErvp++Aq5Bsw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.Memory": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "B4y+Cev05eMcjf1na0v9gza6GUtahXbtY1JCypIgx3B4Ea/KAgsWyXEmW4q6zMbmTMtKzmPVk09rvFJirvMwTg==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Caching.StackExchangeRedis": { + "type": "Transitive", + "resolved": "6.0.6", + "contentHash": "bdVQpYm1hcHf0pyAypMjtDw3HjWQJ89UzloyyF1OBs56QlgA1naM498tP2Vjlho5vVRALMGPYzdRKCen8koubw==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "StackExchange.Redis": "2.2.4" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "tq2wXyh3fL17EMF2bXgRhU7JrbO3on93MRKYxzz4JzzvuGSA1l0W3GI9/tl8EO89TH+KWEymP7bcFway6z9fXg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "qWzV9o+ZRWq+pGm+1dF+R7qTgTYoXvbyowRoBxQJGfqTpqDun2eteerjRQhq5PQ/14S+lqto3Ft4gYaRyl4rdQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "IznHHzGUtrdpuQqIUdmzF6TYPcsYHONhHh3o9dGp39sX/9Zfmt476UnhvU0UhXgJnXXAikt/MpN6AuSLCCMdEQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "2.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "pnyXV1LFOsYjGveuC07xp0YHIyGq7jRq5Ncb5zrrIieMLWVwgMyYxcOH0jTnBedDT4Gh1QinSqsjqzcieHk1og==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "V4Dth2cYMZpw3HhGw9XUDIijpI6gN+22LDt0AhufIgOppCUfpWX4483OmN+dFXRJkJLc8Tv0Q8QK+1ingT2+KQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "GJGery6QytCzS/BxJ96klgG9in3uH26KcUBbiVG/coNDXCRq6LGVVlUT4vXq34KPuM+R2av+LeYdX9h4IZOCUg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "6.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "Fy8yr4V6obi7ZxvKYI1i85jqtwMq8tqyxQVZpRSkgeA8enqy/KvBIMdcuNdznlxQMZa72mvbHqb7vbg4Pyx95w==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "6.0.0", + "Microsoft.Extensions.Configuration.Json": "6.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileProviders.Physical": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "vWXPg3HJQIpZkENn1KWq8SfbqVujVD7S7vIAyFXXqK5xkf1Vho+vG0bLBCHxU36lD1cLLtmGpfYf0B3MYFi9tQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "xlzi2IYREJH3/m6+lUrQlujzX8wDitm4QGnUu6kUXTQAWPuZY8i+ticFJbzfqaetLA6KR/rO6Ew/HuYD+bxifg==" + }, + "Microsoft.Extensions.DependencyModel": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "TD5QHg98m3+QhgEV1YVoNMl5KtBw/4rjfxLHO0e/YV9bPUBDKntApP4xdrVtGgCeQZHVfC2EXIGsdpRNrr87Pg==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0", + "System.Text.Json": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "0pd4/fho0gC12rQswaGQxbU34jOS1TPS8lZPpkFCH68ppQjHNHYle9iRuHeev1LhrJ94YPvzcRd8UmIuFk23Qw==", + "dependencies": { + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "QvkL7l0nM8udt3gfyu0Vw8bbCXblxaKOl7c2oBfgGy4LCURRaL9XWZX1FWJrQc43oMokVneVxH38iz+bY1sbhg==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "6.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "ip8jnL1aPiaPeKINCqaTEbvBFDmVx9dXQEBZ2HOBRXPD1eabGNqP/bKlsIcp7U2lGxiXd5xIhoFcmY8nM4Hdiw==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "3.1.8", + "contentHash": "7ZJUKwPipkDvuv2KJPZ3r01wp2AWNMiYH+61i0dL89F7QICknjKpWgLKLpTSUYFgl77S3b4264I6i4HzDdrb2A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "3.1.8", + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.FileProviders.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8" + } + }, + "Microsoft.Extensions.Identity.Core": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "8vBsyGkA8ZI3lZvm1nf+9ynRC/TzPD+UtbdgTlKk+cz+AW5I41LrK8f/adGej5uXgprOA2DMjZw33vZG6vyXxA==", + "dependencies": { + "Microsoft.AspNetCore.Cryptography.KeyDerivation": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0" + } + }, + "Microsoft.Extensions.Identity.Stores": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "linRCnWBfnqg8qjrd9u/KMISy8O4a6X/GRhpHXU0ar654YQw9LJ/Ht+psx8QLqSX5EsCBbBCZzuamatH2FWIyQ==", + "dependencies": { + "Microsoft.Extensions.Caching.Abstractions": "6.0.0", + "Microsoft.Extensions.Identity.Core": "6.0.4", + "Microsoft.Extensions.Logging": "6.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "eIbyj40QDg1NDz0HBW0S5f3wrLVnKWnDJ/JtZ+yJDFnDj90VoPuoPmFkeaXrtu+0cKm5GRAwoDf+dBWXK0TUdg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0", + "Microsoft.Extensions.Options": "6.0.0", + "System.Diagnostics.DiagnosticSource": "6.0.0" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "6.0.1", + "contentHash": "dzB2Cgg+JmrouhjkcQGzSFjjvpwlq353i8oBQO2GWNjCXSzhbtBRUf28HSauWe7eib3wYOdb3tItdjRwAdwCSg==" + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "dzXN0+V1AyjOe2xcJ86Qbo233KHuLEY0njf/P2Kw8SfJU+d45HNS2ctJdnEnrWbM9Ye2eFgaC5Mj9otRMU6IsQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "6.0.0", + "Microsoft.Extensions.Primitives": "6.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y/lGICwO27fCkQRK3tZseVzFjZaxfGmui990E67sB4MuiPzdJHnJDS/BeYWrHShSSBgCl4KyKRx4ux686fftPg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "2.0.0", + "Microsoft.Extensions.Options": "2.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "9+PnzmQFfEFNR9J2aDTfJGGupShHjOuGw4VUv+JB044biSHrnmCIMD+mJHmb2H7YryrfBEXDurxQ47gJZdCKNQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Microsoft.Identity.Client": { + "type": "Transitive", + "resolved": "4.22.0", + "contentHash": "GlamU9rs8cSVIx9WSGv5QKpt66KkE+ImxNa/wNZZUJ3knt3PM98T9sOY8B7NcEfhw7NoxU2/0TSOcmnRSJQgqw==" + }, + "Microsoft.Identity.Client.Extensions.Msal": { + "type": "Transitive", + "resolved": "2.16.5", + "contentHash": "VlGUZEpF8KP/GCfFI59sdE0WA0o9quqwM1YQY0dSp6jpGy5EOBkureaybLfpwCuYUUjQbLkN2p7neUIcQCfbzA==", + "dependencies": { + "Microsoft.Identity.Client": "4.22.0", + "System.Security.Cryptography.ProtectedData": "4.5.0" + } + }, + "Microsoft.IdentityModel.Clients.ActiveDirectory": { + "type": "Transitive", + "resolved": "3.14.2", + "contentHash": "TNsJJMiRnkeby1ovThVoV9yFsPWjAdluwOA+Nf0LtSsBVVrKQv8Qp4kYOgyNwMVj+pDwbhXISySk+4HyHVWNZQ==", + "dependencies": { + "NETStandard.Library": "1.6.0", + "System.Runtime.Serialization.Json": "4.0.2", + "System.Runtime.Serialization.Primitives": "4.1.1" + } + }, + "Microsoft.IdentityModel.JsonWebTokens": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "0qjS31rN1MQTc46tAYbzmMTSRfdV5ndZxSjYxIGqKSidd4wpNJfNII/pdhU5Fx8olarQoKL9lqqYw4yNOIwT0Q==", + "dependencies": { + "Microsoft.IdentityModel.Tokens": "6.10.0" + } + }, + "Microsoft.IdentityModel.Logging": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "zbcwV6esnNzhZZ/VP87dji6VrUBLB5rxnZBkDMqNYpyG+nrBnBsbm4PUYLCBMUflHCM9EMLDG0rLnqqT+l0ldA==" + }, + "Microsoft.IdentityModel.Protocols": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "DFyXD0xylP+DknCT3hzJ7q/Q5qRNu0hO/gCU90O0ATdR0twZmlcuY9RNYaaDofXKVbzcShYNCFCGle2G/o8mkg==", + "dependencies": { + "Microsoft.IdentityModel.Logging": "6.10.0", + "Microsoft.IdentityModel.Tokens": "6.10.0" + } + }, + "Microsoft.IdentityModel.Protocols.OpenIdConnect": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "LVvMXAWPbPeEWTylDrxunlHH2wFyE4Mv0L4gZrJHC4HTESbWHquKZb/y/S8jgiQEDycOP0PDQvbG4RR/tr2TVQ==", + "dependencies": { + "Microsoft.IdentityModel.Protocols": "6.10.0", + "System.IdentityModel.Tokens.Jwt": "6.10.0" + } + }, + "Microsoft.IdentityModel.Tokens": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "qbf1NslutDB4oLrriYTJpy7oB1pbh2ej2lEHd2IPDQH9C74ysOdhU5wAC7KoXblldbo7YsNR2QYFOqQM/b0Rsg==", + "dependencies": { + "Microsoft.CSharp": "4.5.0", + "Microsoft.IdentityModel.Logging": "6.10.0", + "System.Security.Cryptography.Cng": "4.5.0" + } + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "VyPlqzH2wavqquTcYpkIIAQ6WdenuKoFN0BdYBbCWsclXacSOHNQn66Gt4z5NBqEYW0FAPm5rlvki9ZiCij5xQ==" + }, + "Microsoft.NETCore.Targets": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==" + }, + "Microsoft.OData.Core": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "/EjnJezMBjXf8OjcShhGzPY7pOO0CopgoZGhS6xsP3t2uhC+O72IBHgtQ7F3v1rRXWVtJwLGhzE1GfJUlx3c4Q==", + "dependencies": { + "Microsoft.OData.Edm": "[7.6.4]", + "Microsoft.Spatial": "[7.6.4]" + } + }, + "Microsoft.OData.Edm": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "MSSmA6kIfpgFTtNpOnnayoSj/6KSzHC1U9KOjF7cTA1PG4tZ7rIMi1pvjFc8CmYEvP4cxGl/+vrCn+HpK26HTQ==" + }, + "Microsoft.OpenApi": { + "type": "Transitive", + "resolved": "1.2.3", + "contentHash": "Nug3rO+7Kl5/SBAadzSMAVgqDlfGjJZ0GenQrLywJ84XGKO0uRqkunz5Wyl0SDwcR71bAATXvSdbdzPrYRYKGw==" + }, + "Microsoft.Spatial": { + "type": "Transitive", + "resolved": "7.6.4", + "contentHash": "3mB+Frn4LU4yb5ie9R752QiRn0Hvp9PITkSRofV/Lzm9EyLM87Fy9ziqgz75O/c712dh6GxuypMSBUGmNFwMeA==" + }, + "Microsoft.Win32.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "9ZQKCWxH7Ijp9BfahvL2Zyf1cJIk8XYLF6Yjzr2yi0b2cOut/HQ31qf1ThHAgCc3WiZMdnWcfJCgN82/0UunxA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "Microsoft.Win32.Registry": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dDoKi0PnDz31yAyETfRntsLArTlVAVzUzCIvvEDsDsucrl33Dl8pIJG06ePTJTI3tGpeyHS9Cq7Foc/s4EeKcg==", + "dependencies": { + "System.Security.AccessControl": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "Microsoft.Win32.SystemEvents": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "hqTM5628jSsQiv+HGpiq3WKBl2c8v1KZfby2J6Pr7pEPlK9waPdgEO6b8A/+/xn/yZ9ulv8HuqK71ONy2tg67A==" + }, + "MimeKit": { + "type": "Transitive", + "resolved": "3.2.0", + "contentHash": "l9YHMBhBUwY7qQHUp8fw0EvjcbmhN4Iggz6MdjqIShBf42+0nJTa5gu0kuupCOPuiARc9ZaS9c9f0gKz4OnxKw==", + "dependencies": { + "Portable.BouncyCastle": "1.9.0", + "System.Security.Cryptography.Pkcs": "6.0.0" + } + }, + "MySqlConnector": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "JVokQTUNN3WHAu9Vw8ieeq1dXTFokJiig5P0VJ4f439UxRrsPo6SaVWC8Zdm6mkPeQFhZ0/9afdWa02EY/1j/w==" + }, + "NETStandard.Library": { + "type": "Transitive", + "resolved": "1.6.1", + "contentHash": "WcSp3+vP+yHNgS8EV5J7pZ9IRpeDuARBPN28by8zqff1wJQXm26PVU8L3/fYLBJVU7BtDyqNVWq2KlCVvSSR4A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.AppContext": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Console": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.Compression.ZipFile": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Linq": "4.3.0", + "System.Linq.Expressions": "4.3.0", + "System.Net.Http": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Net.Sockets": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.InteropServices.RuntimeInformation": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Timer": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XDocument": "4.3.0" + } + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.1", + "contentHash": "ppPFpBcvxdsfUonNcvITKqLl3bqxWbDCZIzDWHzjpdAHRFfZe0Dw9HmA0+za13IdyrgJwpkDTDA9fHaxOrt20A==" + }, + "Npgsql": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "wKa8MJEJaj0xQXUQZGv7q/KfPID23jSSvFFtljMworrv7dNajr0GN8PCU1SpywqHjMWdYEfK29DY1aYbiISbQg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "Npgsql.EntityFrameworkCore.PostgreSQL": { + "type": "Transitive", + "resolved": "6.0.8", + "contentHash": "YJRpO+3wXQyWuwRUCVJj/Rsn46sY0bZ6uCGOEFApiRe0ZYJ6N6TxZUWKbTNJYjesickcLGzynOerpSbDJX1AYg==", + "dependencies": { + "Microsoft.EntityFrameworkCore": "6.0.12", + "Microsoft.EntityFrameworkCore.Abstractions": "6.0.12", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12", + "Npgsql": "6.0.8" + } + }, + "NSec.Cryptography": { + "type": "Transitive", + "resolved": "20.2.0", + "contentHash": "NxzHaDQm3JfH+9VQdLI1bC4h/ZTKPo5o/4BEscBu4KK0Yv35sB87hSRuzpr09VahxY5ZpJfE2tHyK4u27jfiyQ==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "4.7.0", + "libsodium": "[1.0.18, 1.0.19)" + } + }, + "Otp.NET": { + "type": "Transitive", + "resolved": "1.2.2", + "contentHash": "2hrZfkbzeWJ3tNXXt/1beg4IY+nS4F3gIfh4NVFvW0f6Pj51hGpiJ4prBz7Dmrr4ZYrA96rTERVGieZ4xYm7jA==" + }, + "Pipelines.Sockets.Unofficial": { + "type": "Transitive", + "resolved": "2.2.2", + "contentHash": "Bhk0FWxH1paI+18zr1g5cTL+ebeuDcBCR+rRFO+fKEhretgjs7MF2Mc1P64FGLecWp4zKCUOPzngBNrqVyY7Zg==", + "dependencies": { + "System.IO.Pipelines": "5.0.1" + } + }, + "Pomelo.EntityFrameworkCore.MySql": { + "type": "Transitive", + "resolved": "6.0.2", + "contentHash": "KvlZ800CnEuEGnxj5OT1fCKGjQXxW5kpPlCP91JqBYG+2Z3927eqXmlX6LLKUt4swqE8ZsEQ+Zkpab8bqstf4g==", + "dependencies": { + "Microsoft.EntityFrameworkCore.Relational": "[6.0.7, 7.0.0)", + "Microsoft.Extensions.DependencyInjection": "6.0.0", + "MySqlConnector": "2.1.2" + } + }, + "Portable.BouncyCastle": { + "type": "Transitive", + "resolved": "1.9.0", + "contentHash": "eZZBCABzVOek+id9Xy04HhmgykF0wZg9wpByzrWN7q8qEI0Qen9b7tfd7w8VA3dOeesumMG7C5ZPy0jk7PSRHw==" + }, + "Quartz": { + "type": "Transitive", + "resolved": "3.4.0", + "contentHash": "N8350OAlQhd8zKg0ARFikGjh3bfAW/CF/KVxu2fTIlAALB/oC1eg54n/QAPYR5ryHuYyDr5G8/Qa4k+D/7OFRQ==", + "dependencies": { + "Microsoft.Extensions.Logging.Abstractions": "2.1.1", + "System.Configuration.ConfigurationManager": "4.7.0", + "System.Diagnostics.DiagnosticSource": "4.7.1" + } + }, + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7VSGO0URRKoMEAq0Sc9cRz8mb6zbyx/BZDEWhgPdzzpmFhkam3fJ1DAGWFXBI4nGlma+uPKpfuMQP5LXRnOH5g==" + }, + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "0oAaTAm6e2oVH+/Zttt0cuhGaePQYKII1dY8iaqP7CvOpVKgLybKRFvQjXR2LtxXOXTVPNv14j0ot8uV+HrUmw==" + }, + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "G24ibsCNi5Kbz0oXWynBoRgtGvsw5ZSVEWjv13/KiCAM8C6wz9zzcCniMeQFIkJ2tasjo2kXlvlBZhplL51kGg==" + }, + "runtime.native.System": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "c/qWt2LieNZIj1jGnVNsE2Kl23Ya2aSTBuXMD6V7k9KWr6l16Tqdwq+hJScEpWER9753NWC8h96PaVNY5Ld7Jw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Data.SqlClient.sni": { + "type": "Transitive", + "resolved": "4.7.0", + "contentHash": "9kyFSIdN3T0qjDQ2R0HRXYIhS3l5psBzQi6qqhdLz+SzFyEy4sVxNOke+yyYv8Cu8rPER12c3RDjLT8wF3WBYQ==", + "dependencies": { + "runtime.win-arm64.runtime.native.System.Data.SqlClient.sni": "4.4.0", + "runtime.win-x64.runtime.native.System.Data.SqlClient.sni": "4.4.0", + "runtime.win-x86.runtime.native.System.Data.SqlClient.sni": "4.4.0" + } + }, + "runtime.native.System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "INBPonS5QPEgn7naufQFXJEp3zX6L4bwHgJ/ZH78aBTpeNfQMtf7C6VrAFhlq2xxWBveIOWyFzQjJ8XzHMhdOQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZVuZJqnnegJhd2k/PtAbbIcZ3aZeITq3sj06oKfMBSfphW3HDmk/t4ObvbOk/JA/swGR0LNqMksAh/f7gpTROg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "M2nN92ePS8BgQ2oi6Jj3PlTUzadYSIWLdZrHY1n1ZcW9o4wAQQ6W+aQ2lfq1ysZQfVCgDwY58alUdowrzezztg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DloMk88juo0OuOWr56QG7MNchmafTLYWvABy36izkrLI5VledI0rq28KGs1i9wbpeT9NPQrx/wTf8U2vazqQ3Q==", + "dependencies": { + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": "4.3.0" + } + }, + "runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "QR1OwtwehHxSeQvZKXe+iSd+d3XZNkEcuWMFYa2i0aG1l+lR739HPicKMlTbJst3spmeekDVBUS7SeS26s4U/g==", + "dependencies": { + "runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2", + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "I+GNKGg2xCHueRd1m9PzeEW7WLbNNLznmTuEi8/vZX71HudUbx1UTwlGkiwMri7JLl8hGaIAWnA/GONhu+LOyQ==" + }, + "runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "1Z3TAq1ytS1IBRtPXJvEUZdVsfWfeNEhBkbiOCGEl9wwAfsjP2lz3ZFDx5tq8p60/EqbS0HItG5piHuB71RjoA==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kVXCuMTrTlxq4XOOMAysuNwsXWpYeboGddNGpIgNSZmv1b6r/s/DPk0fYMB7Q5Qo4bY68o48jt4T4y5BVecbCQ==" + }, + "runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "6mU/cVmmHtQiDXhnzUImxIcDL48GbTk+TsptXyJA+MIOG9LRjPoAQC/qBFB7X+UNyK86bmvGwC8t+M66wsYC8w==" + }, + "runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "vjwG0GGcTW/PPg6KVud8F9GLWYuAV1rrw1BKAqY0oh4jcUqg15oYF1+qkGR2x2ZHM4DQnWKQ7cJgYbfncz/lYg==" + }, + "runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "7KMFpTkHC/zoExs+PwP8jDCWcrK9H6L7soowT80CUx3e+nxP/AFnq0AQAW5W76z2WYbLAYCRyPfwYFG6zkvQRw==" + }, + "runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xrlmRCnKZJLHxyyLIqkZjNXqgxnKdZxfItrPkjI+6pkRo5lHX8YvSZlWrSI5AVwLMi4HbNWP7064hcAWeZKp5w==" + }, + "runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "leXiwfiIkW7Gmn7cgnNcdtNAU70SjmKW3jxGj1iKHOvdn0zRWsgv/l2OJUO5zdGdiv2VRFnAsxxhDgMzofPdWg==" + }, + "runtime.win-arm64.runtime.native.System.Data.SqlClient.sni": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "LbrynESTp3bm5O/+jGL8v0Qg5SJlTV08lpIpFesXjF6uGNMWqFnUQbYBJwZTeua6E/Y7FIM1C54Ey1btLWupdg==" + }, + "runtime.win-x64.runtime.native.System.Data.SqlClient.sni": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "38ugOfkYJqJoX9g6EYRlZB5U2ZJH51UP8ptxZgdpS07FgOEToV+lS11ouNK2PM12Pr6X/PpT5jK82G3DwH/SxQ==" + }, + "runtime.win-x86.runtime.native.System.Data.SqlClient.sni": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "YhEdSQUsTx+C8m8Bw7ar5/VesXvCFMItyZF7G1AUY+OM0VPZUOeAVpJ4Wl6fydBGUYZxojTDR3I6Bj/+BPkJNA==" + }, + "SendGrid": { + "type": "Transitive", + "resolved": "9.27.0", + "contentHash": "kMyXRQ8hmN2bG3tYZ7T31Ufl1kXkpuP5+WBh1BJ32WY31DTnBTCVGURoIqfbTo/tRuQfAYLxra6C8cQGN6kk+A==", + "dependencies": { + "Newtonsoft.Json": "9.0.1", + "starkbank-ecdsa": "[1.3.3, 2.0.0)" + } + }, + "Sentry": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "Pkw4+51EDUQ0X02jdCZIpaM2Q4UO06VKGDE+dYYNxgvOirRXGKTKxRk4NPKJTLSTNl+2JyT9HoE7C6BTlYhLOw==" + }, + "Sentry.Serilog": { + "type": "Transitive", + "resolved": "3.16.0", + "contentHash": "GFTVfQdOFqZ9Vmo8EEZTx1EQMDRJjka/4v2CwxnAUh+sqHDICga4eOm4AyGzDBbE4s9iAHMgMUCceIqo+7z84w==", + "dependencies": { + "Sentry": "3.16.0", + "Serilog": "2.10.0" + } + }, + "Serilog": { + "type": "Transitive", + "resolved": "2.10.0", + "contentHash": "+QX0hmf37a0/OZLxM3wL7V6/ADvC1XihXN4Kq/p6d8lCPfgkRdiuhbWlMaFjR9Av0dy5F0+MBeDmDdRZN/YwQA==" + }, + "Serilog.AspNetCore": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "/JO/txIxRR61x1UXQAgUzG2Sx05o1QHCkokVBWrKzmAoDu+p5EtCAj7L/TVVg7Ezhh3GPiZ0JI9OJCmRO9tSRw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "5.0.0", + "Microsoft.Extensions.Logging": "5.0.0", + "Serilog": "2.10.0", + "Serilog.Extensions.Hosting": "4.2.0", + "Serilog.Formatting.Compact": "1.1.0", + "Serilog.Settings.Configuration": "3.3.0", + "Serilog.Sinks.Console": "4.0.1", + "Serilog.Sinks.Debug": "2.0.0", + "Serilog.Sinks.File": "5.0.0" + } + }, + "Serilog.Extensions.Hosting": { + "type": "Transitive", + "resolved": "4.2.0", + "contentHash": "gT2keceCmPQR9EX0VpXQZvUgELdfE7yqJ7MOxBhm3WLCblcvRgswEOOTgok/DHObbM15A3V/DtF3VdVDQPIZzQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "3.1.8", + "Microsoft.Extensions.Hosting.Abstractions": "3.1.8", + "Microsoft.Extensions.Logging.Abstractions": "3.1.8", + "Serilog": "2.10.0", + "Serilog.Extensions.Logging": "3.1.0" + } + }, + "Serilog.Extensions.Logging": { + "type": "Transitive", + "resolved": "3.1.0", + "contentHash": "IWfem7wfrFbB3iw1OikqPFNPEzfayvDuN4WP7Ue1AVFskalMByeWk3QbtUXQR34SBkv1EbZ3AySHda/ErDgpcg==", + "dependencies": { + "Microsoft.Extensions.Logging": "2.0.0", + "Serilog": "2.9.0" + } + }, + "Serilog.Extensions.Logging.File": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "usO0qr4v9VCMBWiTJ1nQmAbPNCt40FrkDol6CpfCXbsxGZS/hH+YCueF7vvPQ32ATI0GWcMWiKRdjXEE7/HxTQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "2.0.0", + "Microsoft.Extensions.Configuration.Binder": "2.0.0", + "Serilog": "2.5.0", + "Serilog.Extensions.Logging": "2.0.2", + "Serilog.Formatting.Compact": "1.0.0", + "Serilog.Sinks.Async": "1.1.0", + "Serilog.Sinks.RollingFile": "3.3.0" + } + }, + "Serilog.Formatting.Compact": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "pNroKVjo+rDqlxNG5PXkRLpfSCuDOBY0ri6jp9PLe505ljqwhwZz8ospy2vWhQlFu5GkIesh3FcDs4n7sWZODA==", + "dependencies": { + "Serilog": "2.8.0" + } + }, + "Serilog.Settings.Configuration": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "7GNudISZwqaT902hqEL2OFGTZeUFWfnrNLupJkOqeF41AR3GjcxX+Hwb30xb8gG2/CDXsCMVfF8o0+8KY0fJNg==", + "dependencies": { + "Microsoft.Extensions.DependencyModel": "3.0.0", + "Microsoft.Extensions.Options.ConfigurationExtensions": "2.0.0", + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Async": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "xll0Kanz2BkCxuv+F3p1WXr47jdsVM0GU1n1LZvK+18QiRZ/WGFNxSNw9EMKFV5ED5gr7MUpAe6PCMNL1HGUMA==", + "dependencies": { + "Serilog": "2.1.0", + "System.Collections.Concurrent": "4.0.12" + } + }, + "Serilog.Sinks.AzureCosmosDB": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Im2/ZqjXQIpsd727qEo5Pq+br0MiNVuTvI40Yk7736tgjCpEx+omPHv4+c4fEAxnOP2kL9Ge6UoDFoDw3cjF2A==", + "dependencies": { + "Microsoft.Azure.Cosmos": "3.24.0", + "Microsoft.CSharp": "4.7.0", + "Newtonsoft.Json": "13.0.1", + "Serilog": "2.10.0", + "Serilog.Sinks.PeriodicBatching": "2.3.1" + } + }, + "Serilog.Sinks.Console": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "apLOvSJQLlIbKlbx+Y2UDHSP05kJsV7mou+fvJoRGs/iR+jC22r8cuFVMjjfVxz/AD4B2UCltFhE1naRLXwKNw==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.Debug": { + "type": "Transitive", + "resolved": "2.0.0", + "contentHash": "Y6g3OBJ4JzTyyw16fDqtFcQ41qQAydnEvEqmXjhwhgjsnG/FaJ8GUqF5ldsC/bVkK8KYmqrPhDO+tm4dF6xx4A==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.File": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "uwV5hdhWPwUH1szhO8PJpFiahqXmzPzJT/sOijH/kFgUx+cyoDTMM8MHD0adw9+Iem6itoibbUXHYslzXsLEAg==", + "dependencies": { + "Serilog": "2.10.0" + } + }, + "Serilog.Sinks.PeriodicBatching": { + "type": "Transitive", + "resolved": "2.3.1", + "contentHash": "LVYvqpqjSTD8dhfxRnzpxTs8/ys3V2q01MvaY3r0eKsDgpKK1U1y/5N6gFHgiesbxG0V+O5IWdz4+c1DzoNyOQ==", + "dependencies": { + "Serilog": "2.0.0" + } + }, + "Serilog.Sinks.RollingFile": { + "type": "Transitive", + "resolved": "3.3.0", + "contentHash": "2lT5X1r3GH4P0bRWJfhA7etGl8Q2Ipw9AACvtAHWRUSpYZ42NGVyHoVs2ALBZ/cAkkS+tA4jl80Zie144eLQPg==", + "dependencies": { + "Serilog.Sinks.File": "3.2.0", + "System.IO": "4.1.0", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Text.Encoding.Extensions": "4.0.11" + } + }, + "Serilog.Sinks.SyslogMessages": { + "type": "Transitive", + "resolved": "2.0.6", + "contentHash": "V2Yq2GEbk7taEPbpBLFzLXhrHrUzKf4sQu/zLrANU8XIoUn/Mr08M2E8PrcrWVXCj0R4xLMWYe0Z1sxOrMF3IA==", + "dependencies": { + "Serilog": "2.5.0", + "Serilog.Sinks.PeriodicBatching": "2.3.0" + } + }, + "SQLitePCLRaw.bundle_e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "ilkvNhrTersLmIVAcDwwPqfhUFCg19Z1GVMvCSi3xk6Akq94f4qadLORQCq/T8+9JgMiPs+F/NECw5uauviaNw==", + "dependencies": { + "SQLitePCLRaw.lib.e_sqlite3": "2.1.2", + "SQLitePCLRaw.provider.e_sqlite3": "2.1.2" + } + }, + "SQLitePCLRaw.core": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "A8EBepVqY2lnAp3a8jnhbgzF2tlj2S3HcJQGANTYg/TbYbKa8Z5cM1h74An/vy0svhfzT7tVY0sFmUglLgv+2g==", + "dependencies": { + "System.Memory": "4.5.3" + } + }, + "SQLitePCLRaw.lib.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "zibGtku8M4Eea1R3ZCAxc86QbNvyEN17mAcQkvWKBuHvRpMiK2g5anG4R5Be7cWKSd1i6baYz8y4dMMAKcXKPg==" + }, + "SQLitePCLRaw.provider.e_sqlite3": { + "type": "Transitive", + "resolved": "2.1.2", + "contentHash": "lxCZarZdvAsMl2zw9bXHrXK6RxVhB4b23iTFhCOdHFhxfbsxLxWf+ocvswJwR/9Wh/E//ddMi+wJGqUKV7VwoA==", + "dependencies": { + "SQLitePCLRaw.core": "2.1.2" + } + }, + "StackExchange.Redis": { + "type": "Transitive", + "resolved": "2.5.43", + "contentHash": "YQ38jVbX1b5mBi6lizESou+NpV6QZpeo6ofRR6qeuqJ8ePOmhcwhje3nDTNIGEkfPSK0sLuF6pR5rtFyq2F46g==", + "dependencies": { + "Pipelines.Sockets.Unofficial": "2.2.2", + "System.Diagnostics.PerformanceCounter": "5.0.0" + } + }, + "starkbank-ecdsa": { + "type": "Transitive", + "resolved": "1.3.3", + "contentHash": "OblOaKb1enXn+dSp7tsx9yjwV+/BEKM9jFhshIkZTwCk7LuTFTp+wSon6rFzuPiIiTGtvVWQNUw2slHjGktJog==" + }, + "Stripe.net": { + "type": "Transitive", + "resolved": "40.0.0", + "contentHash": "SD1bGiF+sVQG3p2LXNTZ5rEG2aCnXIHokcxYS9yyW3dR01J0ryf+iNFOwid148yePZ0gCBcRxj3wiW1mTmP7UQ==", + "dependencies": { + "Newtonsoft.Json": "12.0.3", + "System.Configuration.ConfigurationManager": "6.0.0" + } + }, + "Swashbuckle.AspNetCore": { + "type": "Transitive", + "resolved": "6.3.1", + "contentHash": "JFk0+HHUPdjYuPhkpGBMLi2JtnEuWkE2pp0yXQp64DmeMe+Fb0hZyVNq/ENJ2vQNso7Zg+C758WmR/xyAl36bA==", + "dependencies": { + "Microsoft.Extensions.ApiDescription.Server": "3.0.0", + "Swashbuckle.AspNetCore.Swagger": "6.3.1", + "Swashbuckle.AspNetCore.SwaggerGen": "6.3.1", + "Swashbuckle.AspNetCore.SwaggerUI": "6.3.1" + } + }, + "Swashbuckle.AspNetCore.Swagger": { + "type": "Transitive", + "resolved": "6.3.1", + "contentHash": "idAFh4xhyJHYHfdLVOOn+BmscBul1OQbWsnL6YPJE8tO/0y6S79hDCvs6OY5VI093/9+1pYY3j31Zet9yaDZjA==", + "dependencies": { + "Microsoft.OpenApi": "1.2.3" + } + }, + "Swashbuckle.AspNetCore.SwaggerGen": { + "type": "Transitive", + "resolved": "6.3.1", + "contentHash": "+uoBV4h/6NhCPLoTofSmuOnZ+usu4PW1jP6l4OHwPyu2frbYXGNpJsHs5uUXXn929OiVQkT8wo3Lj/o+P99Ejg==", + "dependencies": { + "Swashbuckle.AspNetCore.Swagger": "6.3.1" + } + }, + "Swashbuckle.AspNetCore.SwaggerUI": { + "type": "Transitive", + "resolved": "6.3.1", + "contentHash": "JLm9hN67jh7RHsX3H30+tb432Li8xm/qV5lRyMMkyHYMfWitIuKAAdrpo2ILcHOIeH7CLMuOO2hp/iLBmE+Bkw==" + }, + "System.AppContext": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "fKC+rmaLfeIzUhagxY17Q9siv/sPrjjKcfNg1Ic8IlQkZLipo8ljcaZQu4VtI4Jqbzjc2VTjzGLF6WmsRXAEgA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Collections": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3Dcj85/TBdVpL5Zr+gEEBUuFe2icOnLalmEh9hfck1PTYbbyWuZgh4fmm2ysCLTrqLQw6t3TgTyJ+VLp+Qb+Lw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Collections.Concurrent": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ztl69Xp0Y/UXCL+3v3tEU+lIy+bvjKNUmopn1wep/a291pVPK7dxBd6T7WnlQqRog+d1a/hSsgRsmFnIBKTPLQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Collections.Immutable": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Collections.NonGeneric": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "hMxFT2RhhlffyCdKLDXjx8WEC5JfCvNozAZxCablAuFRH74SCV4AgzE8yJCh/73bFnEoZgJ9MJmkjQ0dJmnKqA==", + "dependencies": { + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Collections.Specialized": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "/HKQyVP0yH1I0YtK7KJL/28snxHNH/bi+0lgk/+MbURF6ULhAE31MDI+NZDerNWu264YbxklXCCygISgm+HMug==", + "dependencies": { + "System.Collections.NonGeneric": "4.0.1", + "System.Globalization": "4.0.11", + "System.Globalization.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Configuration.ConfigurationManager": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "7T+m0kDSlIPTHIkPMIu6m6tV6qsMqJpvQWW2jIc2qi7sn40qxFo0q+7mEQAhMPXZHMKnWrnv47ntGlM/ejvw3g==", + "dependencies": { + "System.Security.Cryptography.ProtectedData": "6.0.0", + "System.Security.Permissions": "6.0.0" + } + }, + "System.Console": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "DHDrIxiqk1h03m6khKWV2X8p/uvN79rgSqpilL6uzpmSfxfU5ng8VcPtW4qsDsQDHiTv6IPV9TmD5M/vElPNLg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Data.SqlClient": { + "type": "Transitive", + "resolved": "4.8.5", + "contentHash": "fRqxut4lrndPHrXD+ht1XRmCL3obuKldm4XjCRYS9p5f7FSR7shBxAwTkDrpFMsHC9BhNgjjmUtiIjvehn5zkg==", + "dependencies": { + "Microsoft.Win32.Registry": "4.7.0", + "System.Security.Principal.Windows": "4.7.0", + "runtime.native.System.Data.SqlClient.sni": "4.7.0" + } + }, + "System.Diagnostics.Debug": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "ZUhUOdqmaG5Jk3Xdb8xi5kIyQYAA4PnTNlHx1mu9ZY3qv4ELIdKbnL/akbGaKi2RnNUWaZsAs31rvzFdewTj2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.DiagnosticSource": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "frQDfv0rl209cKm1lnwTgFPzNigy2EKk1BS3uAvHvlBVKe5cymGyHO+Sj+NLv5VF/AhHsqPIUUwya5oV4CHMUw==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Diagnostics.PerformanceCounter": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "kcQWWtGVC3MWMNXdMDWfrmIlFZZ2OdoeT6pSNVRtk9+Sa7jwdPiMlNwb0ZQcS7NRlT92pCfmjRtkSWUW3RAKwg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0", + "Microsoft.Win32.Registry": "5.0.0", + "System.Configuration.ConfigurationManager": "5.0.0", + "System.Security.Principal.Windows": "5.0.0" + } + }, + "System.Diagnostics.Process": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "J0wOX07+QASQblsfxmIMFc9Iq7KTXYL3zs2G/Xc704Ylv3NpuVdo6gij6V3PGiptTxqsK0K7CdXenRvKUnkA2g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "Microsoft.Win32.Registry": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Thread": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Diagnostics.Tools": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "UUvkJfSYJMM6x527dJg2VyWPSRqIVB0Z7dbjHst1zmwTXz5CcXSYJFWRpuigfbO1Lf7yfZiIaEUesfnl/g5EyA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Diagnostics.TraceSource": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "6WVCczFZKXwpWpzd/iJkYnsmWTSFFiU24Xx/YdHXBcu+nFI/ehTgeqdJQFbtRPzbrO3KtRNjvkhtj4t5/WwWsA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Diagnostics.Tracing": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rswfv0f/Cqkh78rA5S8eN8Neocz234+emGCtTF3lxPY96F+mmmUen6tbn0glN6PMvlKQb9bPAY5e9u7fgPTkKw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Drawing.Common": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "NfuoKUiP2nUWwKZN6twGqXioIe1zVD0RIj2t976A+czLHr2nY454RwwXs6JU9Htc6mwqL6Dn/nEL3dpVf2jOhg==", + "dependencies": { + "Microsoft.Win32.SystemEvents": "6.0.0" + } + }, + "System.Dynamic.Runtime": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "db34f6LHYM0U0JpE+sOmjar27BnqTVkbLJhgfwMpTdgTigG/Hna3m2MYVwnFzGGKnEJk2UXFuoVTr8WUbU91/A==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.ObjectModel": "4.0.12", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Threading": "4.0.11" + } + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" + }, + "System.Formats.Cbor": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "OJ8UXNyYIvu22ZrMHDBcnBvs3l6w2wEWUSwgPf2gimUrdoKJC4pcg963kiYAA9kvs8HYLQKQ+2Arr7pm19aZ4A==" + }, + "System.Globalization": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "kYdVd2f2PAdFGblzFswE4hkNANJBKRmsfa2X5LG2AcWE1c7/4t0pYae1L8vfZ5xvE2nK/R9JprtToA61OSHWIg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Calendars": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GUlBtdOWT4LTV3I+9/PJW+56AnnChTaOqqTLFtdmype/L500M2LIyXgmtd9X2P2VOkmJd5c67H5SaC2QcL1bFA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Globalization.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "FhKmdR6MPG+pxow6wGtNAWdZh7noIOpdD5TwQ3CprzgIE1bBBoim0vbR1+AWsWjQmU7zXHgQo4TWSP6lCeiWcQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0" + } + }, + "System.IdentityModel.Tokens.Jwt": { + "type": "Transitive", + "resolved": "6.10.0", + "contentHash": "C+Q5ORsFycRkRuvy/Xd0Pv5xVpmWSAvQYZAGs7VQogmkqlLhvfZXTgBIlHqC3cxkstSoLJAYx6xZB7foQ2y5eg==", + "dependencies": { + "Microsoft.IdentityModel.JsonWebTokens": "6.10.0", + "Microsoft.IdentityModel.Tokens": "6.10.0" + } + }, + "System.IO": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3qjaHvxQPDpSOYICjUoTsmoq5u6QJAFRUITgeT/4gqkF1bajbSmb1kwSxEA8AHlofqgcKJcM8udgieRNhaJ5Cg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.Compression": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YHndyoiV90iu4iKG115ibkhrG+S3jBm8Ap9OwoUAzO5oPDAWcr0SFwQFm0HjM8WkEZWo0zvLTyLmbvTkW1bXgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Buffers": "4.3.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.IO.Compression": "4.3.0" + } + }, + "System.IO.Compression.ZipFile": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "G4HwjEsgIwy3JFBduZ9quBkAu+eUwjIdJleuNSgmUojbH6O3mlvEIme+GHx/cLlTAPcrnnL7GqvB9pTlWRfhOg==", + "dependencies": { + "System.Buffers": "4.3.0", + "System.IO": "4.3.0", + "System.IO.Compression": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.IO.FileSystem": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "3wEMARTnuio+ulnvi+hkRNROYwa1kylvYahhcLk4HSoVdl+xxTFVeVlYOfLwrDPImGls0mDqbMhrza8qnWPTdA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.IO.FileSystem.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "6QOb2XFLch7bEc4lIcJH49nJN2HV+OC3fHDgsLVsBVBk3Y4hFAnOBGzJ2lUu7CyDDFo9IBWkSsnbkT6IBwwiMw==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.IO.Hashing": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Rfm2jYCaUeGysFEZjDe7j1R4x6Z6BzumS/vUT5a1AA/AWJuGX71PoGB0RmpyX3VmrGqVnAwtfMn39OHR8Y/5+g==" + }, + "System.IO.Pipelines": { + "type": "Transitive", + "resolved": "5.0.1", + "contentHash": "qEePWsaq9LoEEIqhbGe6D5J8c9IqQOUuTzzV6wn1POlfdLkJliZY3OlB0j0f17uMWlqZYjH7txj+2YbyrIA8Yg==" + }, + "System.Linq": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5DbqIUpsDp0dFftytzuMmc0oeMdQwjcP/EWxsksIz/w1TcFRkZ3yKKz0PqiYFMmEwPSWw+qNVqD7PJ889JzHbw==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Linq.Expressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "PGKkrd2khG4CnlyJwxwwaWWiSiWFNBGlgXvJpeO0xCXrZ89ODrQ6tjEWS/kOqZ8GwEOUATtKtzp1eRgmYNfclg==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Linq": "4.3.0", + "System.ObjectModel": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Emit.Lightweight": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Reflection.TypeExtensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Linq.Queryable": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "Yn/WfYe9RoRfmSLvUt2JerP0BTGGykCZkQPgojaxgzF2N0oPo+/AhB8TXOpdCcNlrG3VRtsamtK2uzsp3cqRVw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Diagnostics.Debug": "4.0.11", + "System.Linq": "4.1.0", + "System.Linq.Expressions": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Extensions": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==" + }, + "System.Memory.Data": { + "type": "Transitive", + "resolved": "1.0.2", + "contentHash": "JGkzeqgBsiZwKJZ1IxPNsDFZDhUvuEdX8L8BDC8N3KOj+6zMcNU28CNN59TpZE/VJYy9cP+5M+sbxtWJx3/xtw==", + "dependencies": { + "System.Text.Encodings.Web": "4.7.2", + "System.Text.Json": "4.6.0" + } + }, + "System.Net.Http": { + "type": "Transitive", + "resolved": "4.3.4", + "contentHash": "aOa2d51SEbmM+H+Csw7yJOuNZoHkrP2XnAurye5HWYgGVVU54YZDvsLUYRv6h18X3sPnjNCANmN7ZhIPiqMcjA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.1", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.DiagnosticSource": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.NameResolution": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "JdqRdM1Qym3YehqdKIi5LHrpypP4JMfxKQSNCJ2z4WawkG0il+N3XfNeJOxll2XrTnG7WgYYPoeiu/KOwg0DQw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.Net.Primitives": "4.0.11", + "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.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.NetworkInformation": { + "type": "Transitive", + "resolved": "4.1.0", + "contentHash": "Q0rfeiW6QsiZuicGjrFA7cRr2+kXex0JIljTTxzI09GIftB8k+aNL31VsQD1sI2g31cw7UGDTgozA/FgeNSzsQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "Microsoft.Win32.Primitives": "4.0.1", + "System.Collections": "4.0.11", + "System.Diagnostics.Tracing": "4.1.0", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.IO.FileSystem": "4.0.1", + "System.IO.FileSystem.Primitives": "4.0.1", + "System.Linq": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.Sockets": "4.1.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.Principal.Windows": "4.0.0", + "System.Threading": "4.0.11", + "System.Threading.Overlapped": "4.0.1", + "System.Threading.Tasks": "4.0.11", + "System.Threading.Thread": "4.0.0", + "System.Threading.ThreadPool": "4.0.10", + "runtime.native.System": "4.0.0" + } + }, + "System.Net.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "qOu+hDwFwoZPbzPvwut2qATe3ygjeQBDQj91xlsaqGFQUI5i4ZnZb8yyQuLGpDGivEPIt8EJkd1BVzVoP31FXA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Net.Requests": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "vxGt7C0cZixN+VqoSW4Yakc1Y9WknmxauDqzxgpw/FnBdz4kQNN51l4wxdXX5VY1xjqy//+G+4CvJWp1+f+y6Q==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.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.IO": "4.1.0", + "System.Net.Http": "4.1.0", + "System.Net.Primitives": "4.0.11", + "System.Net.WebHeaderCollection": "4.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11" + } + }, + "System.Net.Security": { + "type": "Transitive", + "resolved": "4.3.2", + "contentHash": "xT2jbYpbBo3ha87rViHoTA6WdvqOAW37drmqyx/6LD8p7HEPT2qgdxoimRzWtPg8Jh4X5G9BV2seeTv4x6FYlA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.Win32.Primitives": "4.3.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Diagnostics.Tracing": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Extensions": "4.3.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Claims": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Security.Cryptography.X509Certificates": "4.3.0", + "System.Security.Principal": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.ThreadPool": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Security": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.2" + } + }, + "System.Net.Sockets": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "m6icV6TqQOAdgt5N/9I5KNpjom/5NFtkmGseEH+AK/hny8XrytLH3+b5M8zL/Ycg3fhIocFpUMyl/wpFnVRvdw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Net.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Net.WebHeaderCollection": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "XX2TIAN+wBSAIV51BU2FvvXMdstUa8b0FBSZmDWjZdwUMmggQSifpTOZ5fNH20z9ZCg2fkV1L5SsZnpO2RQDRQ==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "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", + "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" + }, + "System.ObjectModel": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "bdX+80eKv9bN6K4N+d77OankKHGn6CH711a6fcOpMQu2Fckp/Ft4L/kW9WznHpyR0NRAvJutzOMHNNlBGvxQzQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Private.DataContractSerialization": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "lcqFBUaCZxPiUkA4dlSOoPZGtZsAuuElH2XHgLwGLxd7ZozWetV5yiz0qGAV2AUYOqw97MtZBjbLMN16Xz4vXA==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Collections.Concurrent": "4.0.12", + "System.Diagnostics.Debug": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Emit.Lightweight": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Runtime.Serialization.Primitives": "4.1.1", + "System.Text.Encoding": "4.0.11", + "System.Text.Encoding.Extensions": "4.0.11", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Threading.Tasks": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1", + "System.Xml.XmlSerializer": "4.0.11" + } + }, + "System.Reflection": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "KMiAFoW7MfJGa9nDFNcfu+FpEdiHpWgTcS2HdMpDvt9saK3y/G4GwprPyzqjFH9NTaGPQeWNHU+iDlDILj96aQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "228FG0jLcIwTVJyz8CLFKueVqQK36ANazUManGaJHkO0icjiIypKW7YLWLIWahyIkdh5M7mV2dJepllLyA1SKg==", + "dependencies": { + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.ILGeneration": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "59tBslAk9733NXLrUJrwNZEzbMAcu8k344OYo+wfSVygcgZ9lgBdGIzH/nrg3LYhXceynyvTc8t5/GD4Ri0/ng==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Emit.Lightweight": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "oadVHGSMsTmZsAF864QYN1t1QzZjIcuKU3l2S9cZOwDdDueNTrqq1yRj7koFfIGEnKpt6NjpL3rOzRhs4ryOgA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Emit.ILGeneration": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "rJkrJD3kBI5B712aRu4DpSIiHRtr6QlfZSQsb0hYHrDCZORXCFjQfoipo2LaMUHoT9i1B7j7MnfaEKWDFmFQNQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5RXItQz5As4xN2/YUDxdpsEkMhvw3e6aNveFXUn4Hl/udNTCNhnKp8lT9fnc3MhvGKh1baak5CovpuQUXHAlIA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Reflection.TypeExtensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7u6ulLcZbyxB5Gq0nMkQttcdBTx57ibzw+4IOXEfR+sXYQoHvjW5LTLyNr8O22UIMrqYbchJQJnos4eooYzYJA==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Resources.ResourceManager": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "/zrcPkkWdZmI4F92gL/TPumP98AVDu/Wxr3CSJGQQ+XN6wbRZcyfSKVoPo17ilb3iOr0cCRqJInGwNMolqhS8A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Globalization": "4.3.0", + "System.Reflection": "4.3.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0" + } + }, + "System.Runtime.Caching": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "30D6MkO8WF9jVGWZIP0hmCN8l9BTY4LCsAzLIe4xFSXzs+AjDotR7DpSmj27pFskDURzUvqYYY0ikModgBTxWw==", + "dependencies": { + "System.Configuration.ConfigurationManager": "5.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + }, + "System.Runtime.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "guW0uK0fn5fcJJ1tJVXYd7/1h5F+pea1r7FLSOz/f8vPEqbR2ZAknuRDvTQ8PzAilDveOxNjSfr0CHfIQfFk8g==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.Handles": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OKiSUN7DmTWeYb3l51A7EYaeNMnvxwE249YtZz7yooT4gOZhmTjIn48KgSsw2k2lYdLgTKNJw/ZIfSElwDRVgg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Runtime.InteropServices": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "uv1ynXqiMK8mp1GM3jDqPCFN66eJ5w5XNomaK2XD+TuCroNTLFGeZ+WCmBMcBDyTFKou3P6cR6J/QsaqDp7fGQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Reflection": "4.3.0", + "System.Reflection.Primitives": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Runtime.InteropServices.RuntimeInformation": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "cbz4YJMqRDR7oLeMRbdYv7mYzc++17lNhScCX0goO2XpGWdvAt60CGN+FHdePUEHCe/Jy9jUlvNAiNdM+7jsOw==", + "dependencies": { + "System.Reflection": "4.3.0", + "System.Reflection.Extensions": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0" + } + }, + "System.Runtime.Numerics": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "yMH+MfdzHjy17l2KESnPiF2dwq7T+xLnSJar7slyimAkUh/gTrS9/UQOtv7xarskJ2/XDSNvfLGOBQPjL7PaHQ==", + "dependencies": { + "System.Globalization": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0" + } + }, + "System.Runtime.Serialization.Json": { + "type": "Transitive", + "resolved": "4.0.2", + "contentHash": "+7DIJhnKYgCzUgcLbVTtRQb2l1M0FP549XFlFkQM5lmNiUBl44AfNbx4bz61xA8PzLtlYwfmif4JJJW7MPPnjg==", + "dependencies": { + "System.IO": "4.1.0", + "System.Private.DataContractSerialization": "4.1.1", + "System.Runtime": "4.1.0" + } + }, + "System.Runtime.Serialization.Primitives": { + "type": "Transitive", + "resolved": "4.1.1", + "contentHash": "HZ6Du5QrTG8MNJbf4e4qMO3JRAkIboGT5Fk804uZtg3Gq516S7hAqTm2UZKUHa7/6HUGdVy3AqMQKbns06G/cg==", + "dependencies": { + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0" + } + }, + "System.Security.AccessControl": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" + }, + "System.Security.Claims": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "P/+BR/2lnc4PNDHt/TPBAWHVMLMRHsyYZbU1NphW4HIWzCggz8mJbTQQ3MKljFE7LS3WagmVFuBgoLcFzYXlkA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Security.Principal": "4.3.0" + } + }, + "System.Security.Cryptography.Algorithms": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "W1kd2Y8mYSCgc3ULTAZ0hOP2dSdG5YauTb1089T0/kRcN2MpSAW1izOFROrJgxSlMn3ArsgHXagigyi+ibhevg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.Apple": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Cng": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "jIMXsKn94T9JY7PvPq/tMfqa6GAaHpElRDpmG+SuL+D3+sTw2M8VhnibKnN8Tq+4JqbPJ/f+BwtLeDMEnzAvRg==", + "dependencies": { + "System.Formats.Asn1": "5.0.0" + } + }, + "System.Security.Cryptography.Csp": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "X4s/FCkEUnRGnwR3aSfVIkldBmtURMhmexALNTwpjklzxWU7yjMk7GHLKOZTNkgnWnE0q7+BCf9N2LVRWxewaA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0" + } + }, + "System.Security.Cryptography.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "1DEWjZZly9ae9C79vFwqaO5kaOlI5q+3/55ohmq/7dpDyDfc8lYe7YVxJUZ5MF/NtbkRjwFRo14yM4OEo9EmDw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Collections.Concurrent": "4.3.0", + "System.Linq": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.OpenSsl": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "h4CEgOgv5PKVF/HwaHzJRiVboL2THYCou97zpmhjghx5frc7fIvlkY1jL+lnIQyChrJDMNEXS6r7byGif8Cy4w==", + "dependencies": { + "System.Collections": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "elM3x+xSRhzQysiqo85SbidJJ2YbZlnvmh+53TuSZHsD7dNuuEWser+9EFtY+rYupBwkq2avc6ZCO3/6qACgmg==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.Primitives": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "7bDIyVFNL/xKeFHjhobUAQqSpJq9YTOpbEs6mR233Et01STBMXNAc/V+BM6dwYGc95gVh/Zf+iVXWzj3mE8DWg==", + "dependencies": { + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Threading": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "rp1gMNEZpvx9vP0JW0oHLxlf8oSiQgtno77Y4PLUBjSiDYoD77Y8uXHr1Ea5XG4/pIKhqAdxZ8v8OTUtqo9PeQ==" + }, + "System.Security.Cryptography.X509Certificates": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "t2Tmu6Y2NtJ2um0RtcuhP7ZdNNxXEgUm2JeoA/0NvlMjAhKCnM1NX07TDl3244mVp3QU6LPEhT3HTtH1uF7IYw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.Globalization.Calendars": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.Handles": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Runtime.Numerics": "4.3.0", + "System.Security.Cryptography.Algorithms": "4.3.0", + "System.Security.Cryptography.Cng": "4.3.0", + "System.Security.Cryptography.Csp": "4.3.0", + "System.Security.Cryptography.Encoding": "4.3.0", + "System.Security.Cryptography.OpenSsl": "4.3.0", + "System.Security.Cryptography.Primitives": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "runtime.native.System": "4.3.0", + "runtime.native.System.Net.Http": "4.3.0", + "runtime.native.System.Security.Cryptography.OpenSsl": "4.3.0" + } + }, + "System.Security.Cryptography.Xml": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "i2Jn6rGXR63J0zIklImGRkDIJL4b1NfPSEbIVHBlqoIb12lfXIigCbDRpDmIEzwSo/v1U5y/rYJdzZYSyCWxvg==", + "dependencies": { + "System.Security.Cryptography.Pkcs": "4.5.0", + "System.Security.Permissions": "4.5.0" + } + }, + "System.Security.Permissions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "T/uuc7AklkDoxmcJ7LGkyX1CcSviZuLCa4jg3PekfJ7SU0niF0IVTXwUiNVP9DSpzou2PpxJ+eNY2IfDM90ZCg==", + "dependencies": { + "System.Security.AccessControl": "6.0.0", + "System.Windows.Extensions": "6.0.0" + } + }, + "System.Security.Principal": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "I1tkfQlAoMM2URscUtpcRo/hX0jinXx6a/KUtEQoz3owaYwl3qwsO8cbzYVVnjxrzxjHo3nJC+62uolgeGIS9A==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Security.Principal.Windows": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" + }, + "System.Security.SecureString": { + "type": "Transitive", + "resolved": "4.0.0", + "contentHash": "sqzq9GD6/b0yqPuMpgIKBuoLf4VKAj8oAfh4kXSzPaN6eoKY3hRi9C5L27uip25qlU+BGPfb0xh2Rmbwc4jFVA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1", + "System.Runtime.InteropServices": "4.1.0", + "System.Security.Cryptography.Primitives": "4.0.0", + "System.Text.Encoding": "4.0.11", + "System.Threading": "4.0.11" + } + }, + "System.Text.Encoding": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Text.Encoding.CodePages": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "NyscU59xX6Uo91qvhOs2Ccho3AR2TnZPomo1Z0K6YpyztBPM/A5VbkzOO19sy3A3i1TtEnTxA7bCe3Us+r5MWg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "5.0.0" + } + }, + "System.Text.Encoding.Extensions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "YVMK0Bt/A43RmwizJoZ22ei2nmrhobgeiYwFzC4YAN+nue8RF6djXDMog0UCn+brerQoYVyaS+ghy9P/MUVcmw==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0", + "System.Text.Encoding": "4.3.0" + } + }, + "System.Text.Encodings.Web": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "Vg8eB5Tawm1IFqj4TVK1czJX89rhFxJo9ELqc/Eiq0eXy13RK00eubyU6TJE6y+GQXjyV5gSfiewDUZjQgSE0w==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Text.Json": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "zaJsHfESQvJ11vbXnNlkrR46IaMULk/gHxYsJphzSF+07kTjPHv+Oc14w6QEOfo3Q4hqLJgStUaYB9DBl0TmWg==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encodings.Web": "6.0.0" + } + }, + "System.Text.RegularExpressions": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "RpT2DA+L660cBt1FssIE9CAGpLFdFPuheB7pLpKpn6ZXNby7jDERe8Ua/Ne2xGiwLVG2JOqziiaVCGDon5sKFA==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "VkUS0kOBcUf3Wwm0TSbrevDDZ6BlM+b/HRiapRFWjM5O0NS0LviG0glKmFK+hhPDd1XFeSdU1GmlLhb2CoVpIw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Threading.Tasks": "4.3.0" + } + }, + "System.Threading.Overlapped": { + "type": "Transitive", + "resolved": "4.0.1", + "contentHash": "f7aLuLkBoCQM2kng7zqLFBXz9Gk48gDK8lk1ih9rH/1arJJzZK9gJwNvPDhL6Ps/l6rwOr8jw+4FCHL0KKWiEg==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.0.1", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Handles": "4.0.1" + } + }, + "System.Threading.Tasks": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "LbSxKEdOUhVe8BezB/9uOGGppt+nZf6e1VFyw6v3DN6lqitm0OSn2uXMOdtP0M3W4iMcqcivm2J6UgqiwwnXiA==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.Threading.Tasks.Extensions": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "zteT+G8xuGu6mS+mzDzYXbzS7rd3K6Fjb9RiZlYlJPam2/hU7JCBZBVEcywNuR+oZ1ncTvc/cq0faRr3P01OVg==" + }, + "System.Threading.Thread": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "OHmbT+Zz065NKII/ZHcH9XO1dEuLGI1L2k7uYss+9C1jLxTC9kTZZuzUOyXHayRk+dft9CiDf3I/QZ0t8JKyBQ==", + "dependencies": { + "System.Runtime": "4.3.0" + } + }, + "System.Threading.ThreadPool": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "k/+g4b7vjdd4aix83sTgC9VG6oXYKAktSfNIJUNGxPEj7ryEOfzHHhfnmsZvjxawwcD9HyWXKCXmPjX8U4zeSw==", + "dependencies": { + "System.Runtime": "4.3.0", + "System.Runtime.Handles": "4.3.0" + } + }, + "System.Threading.Timer": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "Z6YfyYTCg7lOZjJzBjONJTFKGN9/NIYKSxhU5GRd+DTwHSZyvWp1xuI5aR+dLg+ayyC5Xv57KiY4oJ0tMO89fQ==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0", + "Microsoft.NETCore.Targets": "1.1.0", + "System.Runtime": "4.3.0" + } + }, + "System.ValueTuple": { + "type": "Transitive", + "resolved": "4.5.0", + "contentHash": "okurQJO6NRE/apDIP23ajJ0hpiNmJ+f0BwOlB/cSqTLQlw5upkf+5+96+iG2Jw40G1fCVCyPz/FhIABUjMR+RQ==" + }, + "System.Windows.Extensions": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==", + "dependencies": { + "System.Drawing.Common": "6.0.0" + } + }, + "System.Xml.ReaderWriter": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "GrprA+Z0RUXaR4N7/eW71j1rgMnEnEVlgii49GZyAjTH7uliMnrOU3HNFBr6fEDBCJCIdlVNq9hHbaDR621XBA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.IO.FileSystem": "4.3.0", + "System.IO.FileSystem.Primitives": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Runtime.InteropServices": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Text.Encoding.Extensions": "4.3.0", + "System.Text.RegularExpressions": "4.3.0", + "System.Threading.Tasks": "4.3.0", + "System.Threading.Tasks.Extensions": "4.3.0" + } + }, + "System.Xml.XDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "5zJ0XDxAIg8iy+t4aMnQAu0MqVbqyvfoUVl1yDV61xdo3Vth45oA2FoY4pPkxYAH5f8ixpmTqXeEIya95x0aCQ==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Diagnostics.Tools": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Reflection": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "lJ8AxvkX7GQxpC6GFCeBj8ThYVyQczx2+f/cWHJU8tjS7YfI6Cv6bon70jVEgs2CiFbmmM8b9j1oZVx0dSI2Ww==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Text.Encoding": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XmlSerializer": { + "type": "Transitive", + "resolved": "4.0.11", + "contentHash": "FrazwwqfIXTfq23mfv4zH+BjqkSFNaNFBtjzu3I9NRmG8EELYyrv/fJnttCIwRMFRR/YKXF1hmsMmMEnl55HGw==", + "dependencies": { + "System.Collections": "4.0.11", + "System.Globalization": "4.0.11", + "System.IO": "4.1.0", + "System.Linq": "4.1.0", + "System.Reflection": "4.1.0", + "System.Reflection.Emit": "4.0.1", + "System.Reflection.Emit.ILGeneration": "4.0.1", + "System.Reflection.Extensions": "4.0.1", + "System.Reflection.Primitives": "4.0.1", + "System.Reflection.TypeExtensions": "4.1.0", + "System.Resources.ResourceManager": "4.0.1", + "System.Runtime": "4.1.0", + "System.Runtime.Extensions": "4.1.0", + "System.Text.RegularExpressions": "4.1.0", + "System.Threading": "4.0.11", + "System.Xml.ReaderWriter": "4.0.11", + "System.Xml.XmlDocument": "4.0.1" + } + }, + "System.Xml.XPath": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "v1JQ5SETnQusqmS3RwStF7vwQ3L02imIzl++sewmt23VGygix04pEH+FCj1yWb+z4GDzKiljr1W7Wfvrx0YwgA==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Diagnostics.Debug": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0" + } + }, + "System.Xml.XPath.XmlDocument": { + "type": "Transitive", + "resolved": "4.3.0", + "contentHash": "A/uxsWi/Ifzkmd4ArTLISMbfFs6XpRPsXZonrIqyTY70xi8t+mDtvSM5Os0RqyRDobjMBwIDHDL4NOIbkDwf7A==", + "dependencies": { + "System.Collections": "4.3.0", + "System.Globalization": "4.3.0", + "System.IO": "4.3.0", + "System.Resources.ResourceManager": "4.3.0", + "System.Runtime": "4.3.0", + "System.Runtime.Extensions": "4.3.0", + "System.Threading": "4.3.0", + "System.Xml.ReaderWriter": "4.3.0", + "System.Xml.XPath": "4.3.0", + "System.Xml.XmlDocument": "4.3.0" + } + }, + "YubicoDotNetClient": { + "type": "Transitive", + "resolved": "1.2.0", + "contentHash": "uP5F3Ko1gqZi3lwS2R/jAAwhBxXs/6PKDpS6FdQjsBA5qmF0hQmbtfxM6QHTXOMoWbUtfetG7+LtgmG8T5zDIg==", + "dependencies": { + "NETStandard.Library": "1.6.1" + } + }, + "api": { + "type": "Project", + "dependencies": { + "Azure.Messaging.EventGrid": "[4.10.0, )", + "Commercial.Core": "[2022.12.0, )", + "Commercial.Infrastructure.EntityFramework": "[2022.12.0, )", + "Core": "[2022.12.0, )", + "SharedWeb": "[2022.12.0, )", + "Swashbuckle.AspNetCore": "[6.3.1, )" + } + }, + "commercial.core": { + "type": "Project", + "dependencies": { + "Core": "[2022.12.0, )" + } + }, + "commercial.infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2022.12.0, )", + "Infrastructure.EntityFramework": "[2022.12.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.2.1, )", + "Azure.Storage.Blobs": "[12.11.0, )", + "Azure.Storage.Queues": "[12.9.0, )", + "BitPay.Light": "[1.0.1907, )", + "Braintree": "[5.12.0, )", + "Fido2.AspNet": "[3.0.0-beta2, )", + "Handlebars.Net": "[2.1.2, )", + "IdentityServer4": "[4.1.2, )", + "IdentityServer4.AccessTokenValidation": "[3.0.1, )", + "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": "[4.1.0, )", + "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": "[2022.12.0, )", + "Dapper": "[2.0.123, )", + "System.Data.SqlClient": "[4.8.5, )" + } + }, + "infrastructure.entityframework": { + "type": "Project", + "dependencies": { + "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", + "Core": "[2022.12.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": "[2022.12.0, )", + "Infrastructure.Dapper": "[2022.12.0, )", + "Infrastructure.EntityFramework": "[2022.12.0, )" + } + } + } + } +} \ No newline at end of file diff --git a/util/SqliteMigrations/Migrations/20230106153919_SecretsManager.Designer.cs b/util/SqliteMigrations/Migrations/20230106153919_SecretsManager.Designer.cs new file mode 100644 index 000000000..f7b4637ad --- /dev/null +++ b/util/SqliteMigrations/Migrations/20230106153919_SecretsManager.Designer.cs @@ -0,0 +1,2116 @@ +// +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("20230106153919_SecretsManager")] + partial class SecretsManager + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.12"); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ClientSecret") + .HasMaxLength(30) + .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.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("RequestFingerprint") + .HasColumnType("TEXT"); + + 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.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.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.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("CollectionId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + b.ToTable("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("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.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.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("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("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.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("Bit.Infrastructure.EntityFramework.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.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.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("GroupId", "OrganizationUserId"); + + b.HasIndex("OrganizationUserId"); + + b.HasIndex("UserId"); + + 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("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.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("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.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.Models.Provider", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("BillingEmail") + .HasColumnType("TEXT"); + + b.Property("BusinessAddress1") + .HasColumnType("TEXT"); + + b.Property("BusinessAddress2") + .HasColumnType("TEXT"); + + b.Property("BusinessAddress3") + .HasColumnType("TEXT"); + + b.Property("BusinessCountry") + .HasColumnType("TEXT"); + + b.Property("BusinessName") + .HasColumnType("TEXT"); + + b.Property("BusinessTaxNumber") + .HasColumnType("TEXT"); + + b.Property("CreationDate") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("RevisionDate") + .HasColumnType("TEXT"); + + b.Property("Status") + .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.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.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.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.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.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.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("Key") + .HasColumnType("TEXT"); + + b.Property("LastFailedLoginDate") + .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("UnknownDeviceVerificationEnabled") + .HasColumnType("INTEGER"); + + b.Property("UsesKeyConnector") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("User", (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.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Cipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Ciphers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Ciphers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionCipher", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Cipher", "Cipher") + .WithMany("CollectionCiphers") + .HasForeignKey("CipherId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionCiphers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Cipher"); + + b.Navigation("Collection"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionGroup", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionGroups") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.CollectionUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Collection", "Collection") + .WithMany("CollectionUsers") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany("CollectionUsers") + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("CollectionUsers") + .HasForeignKey("UserId"); + + b.Navigation("Collection"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Device", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.EmergencyAccess", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantee") + .WithMany() + .HasForeignKey("GranteeId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "Grantor") + .WithMany() + .HasForeignKey("GrantorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Grantee"); + + b.Navigation("Grantor"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Folder", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Folders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Groups") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany("GroupUsers") + .HasForeignKey("GroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", "OrganizationUser") + .WithMany() + .HasForeignKey("OrganizationUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", null) + .WithMany("GroupUsers") + .HasForeignKey("UserId"); + + b.Navigation("Group"); + + b.Navigation("OrganizationUser"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("ApiKeys") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationConnection", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Connections") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationSponsorship", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoredOrganization") + .WithMany() + .HasForeignKey("SponsoredOrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "SponsoringOrganization") + .WithMany() + .HasForeignKey("SponsoringOrganizationId"); + + b.Navigation("SponsoredOrganization"); + + b.Navigation("SponsoringOrganization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("OrganizationUsers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("OrganizationUsers") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Policy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Policies") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.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.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.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.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.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.Models.SsoConfig", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoConfigs") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.SsoUser", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("SsoUsers") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("SsoUsers") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Transaction", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") + .WithMany("Transactions") + .HasForeignKey("OrganizationId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.User", "User") + .WithMany("Transactions") + .HasForeignKey("UserId"); + + b.Navigation("Organization"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .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.Cipher", b => + { + b.Navigation("CollectionCiphers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Collection", b => + { + b.Navigation("CollectionCiphers"); + + b.Navigation("CollectionGroups"); + + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Group", b => + { + b.Navigation("GroupUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Organization", b => + { + b.Navigation("ApiKeys"); + + b.Navigation("Ciphers"); + + b.Navigation("Connections"); + + b.Navigation("Groups"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("Policies"); + + b.Navigation("SsoConfigs"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.OrganizationUser", b => + { + b.Navigation("CollectionUsers"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => + { + b.Navigation("Ciphers"); + + b.Navigation("CollectionUsers"); + + b.Navigation("Folders"); + + b.Navigation("GroupUsers"); + + b.Navigation("OrganizationUsers"); + + b.Navigation("SsoUsers"); + + b.Navigation("Transactions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/util/SqliteMigrations/Migrations/20230106153919_SecretsManager.cs b/util/SqliteMigrations/Migrations/20230106153919_SecretsManager.cs new file mode 100644 index 000000000..7b4660d61 --- /dev/null +++ b/util/SqliteMigrations/Migrations/20230106153919_SecretsManager.cs @@ -0,0 +1,265 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Bit.SqliteMigrations.Migrations; + +public partial class SecretsManager : Migration +{ + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UseSecretsManager", + table: "Organization", + type: "INTEGER", + nullable: false, + defaultValue: false); + + migrationBuilder.CreateTable( + name: "Project", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + OrganizationId = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true), + CreationDate = table.Column(type: "TEXT", nullable: false), + RevisionDate = table.Column(type: "TEXT", nullable: false), + DeletedDate = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Project", x => x.Id); + table.ForeignKey( + name: "FK_Project_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Secret", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + OrganizationId = table.Column(type: "TEXT", nullable: false), + Key = table.Column(type: "TEXT", nullable: true), + Value = table.Column(type: "TEXT", nullable: true), + Note = table.Column(type: "TEXT", nullable: true), + CreationDate = table.Column(type: "TEXT", nullable: false), + RevisionDate = table.Column(type: "TEXT", nullable: false), + DeletedDate = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Secret", x => x.Id); + table.ForeignKey( + name: "FK_Secret_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ServiceAccount", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + OrganizationId = table.Column(type: "TEXT", nullable: false), + Name = table.Column(type: "TEXT", nullable: true), + CreationDate = table.Column(type: "TEXT", nullable: false), + RevisionDate = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ServiceAccount", x => x.Id); + table.ForeignKey( + name: "FK_ServiceAccount_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "ProjectSecret", + columns: table => new + { + ProjectsId = table.Column(type: "TEXT", nullable: false), + SecretsId = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ProjectSecret", x => new { x.ProjectsId, x.SecretsId }); + table.ForeignKey( + name: "FK_ProjectSecret_Project_ProjectsId", + column: x => x.ProjectsId, + principalTable: "Project", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_ProjectSecret_Secret_SecretsId", + column: x => x.SecretsId, + principalTable: "Secret", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "AccessPolicy", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + GroupId = table.Column(type: "TEXT", nullable: true), + GrantedProjectId = table.Column(type: "TEXT", nullable: true), + GrantedServiceAccountId = table.Column(type: "TEXT", nullable: true), + ServiceAccountId = table.Column(type: "TEXT", nullable: true), + OrganizationUserId = table.Column(type: "TEXT", nullable: true), + Read = table.Column(type: "INTEGER", nullable: false), + Write = table.Column(type: "INTEGER", nullable: false), + CreationDate = table.Column(type: "TEXT", nullable: false), + RevisionDate = table.Column(type: "TEXT", nullable: false), + Discriminator = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AccessPolicy", x => x.Id); + table.ForeignKey( + name: "FK_AccessPolicy_Group_GroupId", + column: x => x.GroupId, + principalTable: "Group", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_OrganizationUser_OrganizationUserId", + column: x => x.OrganizationUserId, + principalTable: "OrganizationUser", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_Project_GrantedProjectId", + column: x => x.GrantedProjectId, + principalTable: "Project", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_ServiceAccount_GrantedServiceAccountId", + column: x => x.GrantedServiceAccountId, + principalTable: "ServiceAccount", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_AccessPolicy_ServiceAccount_ServiceAccountId", + column: x => x.ServiceAccountId, + principalTable: "ServiceAccount", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "ApiKey", + columns: table => new + { + Id = table.Column(type: "TEXT", nullable: false), + ServiceAccountId = table.Column(type: "TEXT", nullable: true), + Name = table.Column(type: "TEXT", maxLength: 200, nullable: true), + ClientSecret = table.Column(type: "TEXT", maxLength: 30, nullable: true), + Scope = table.Column(type: "TEXT", maxLength: 4000, nullable: true), + EncryptedPayload = table.Column(type: "TEXT", maxLength: 4000, nullable: true), + Key = table.Column(type: "TEXT", nullable: true), + ExpireAt = table.Column(type: "TEXT", nullable: true), + CreationDate = table.Column(type: "TEXT", nullable: false), + RevisionDate = table.Column(type: "TEXT", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ApiKey", x => x.Id); + table.ForeignKey( + name: "FK_ApiKey_ServiceAccount_ServiceAccountId", + column: x => x.ServiceAccountId, + principalTable: "ServiceAccount", + principalColumn: "Id"); + }); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_GrantedProjectId", + table: "AccessPolicy", + column: "GrantedProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_GrantedServiceAccountId", + table: "AccessPolicy", + column: "GrantedServiceAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_GroupId", + table: "AccessPolicy", + column: "GroupId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_OrganizationUserId", + table: "AccessPolicy", + column: "OrganizationUserId"); + + migrationBuilder.CreateIndex( + name: "IX_AccessPolicy_ServiceAccountId", + table: "AccessPolicy", + column: "ServiceAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_ApiKey_ServiceAccountId", + table: "ApiKey", + column: "ServiceAccountId"); + + migrationBuilder.CreateIndex( + name: "IX_Project_DeletedDate", + table: "Project", + column: "DeletedDate"); + + migrationBuilder.CreateIndex( + name: "IX_Project_OrganizationId", + table: "Project", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_ProjectSecret_SecretsId", + table: "ProjectSecret", + column: "SecretsId"); + + migrationBuilder.CreateIndex( + name: "IX_Secret_DeletedDate", + table: "Secret", + column: "DeletedDate"); + + migrationBuilder.CreateIndex( + name: "IX_Secret_OrganizationId", + table: "Secret", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_ServiceAccount_OrganizationId", + table: "ServiceAccount", + column: "OrganizationId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AccessPolicy"); + + migrationBuilder.DropTable( + name: "ApiKey"); + + migrationBuilder.DropTable( + name: "ProjectSecret"); + + migrationBuilder.DropTable( + name: "ServiceAccount"); + + migrationBuilder.DropTable( + name: "Project"); + + migrationBuilder.DropTable( + name: "Secret"); + + migrationBuilder.DropColumn( + name: "UseSecretsManager", + table: "Organization"); + } +} diff --git a/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs b/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs index 4a9e5b909..3d75efc6e 100644 --- a/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs +++ b/util/SqliteMigrations/Migrations/DatabaseContextModelSnapshot.cs @@ -17,6 +17,80 @@ namespace Bit.SqliteMigrations.Migrations #pragma warning disable 612, 618 modelBuilder.HasAnnotation("ProductVersion", "6.0.12"); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.Property("Id") + .HasColumnType("TEXT"); + + b.Property("ClientSecret") + .HasMaxLength(30) + .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.Models.AuthRequest", b => { b.Property("Id") @@ -644,6 +718,9 @@ namespace Bit.SqliteMigrations.Migrations b.Property("UseScim") .HasColumnType("INTEGER"); + b.Property("UseSecretsManager") + .HasColumnType("INTEGER"); + b.Property("UseSso") .HasColumnType("INTEGER"); @@ -832,6 +909,38 @@ namespace Bit.SqliteMigrations.Migrations b.ToTable("Policy", (string)null); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Provider", b => { b.Property("Id") @@ -954,6 +1063,44 @@ namespace Bit.SqliteMigrations.Migrations b.ToTable("ProviderUser", (string)null); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Send", b => { b.Property("Id") @@ -1011,6 +1158,32 @@ namespace Bit.SqliteMigrations.Migrations b.ToTable("Send", (string)null); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.SsoConfig", b => { b.Property("Id") @@ -1278,6 +1451,134 @@ namespace Bit.SqliteMigrations.Migrations b.ToTable("User", (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.Models.GroupProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserProjectAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasBaseType("Bit.Infrastructure.EntityFramework.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.Models.ApiKey", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("ServiceAccount"); + }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.AuthRequest", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Device", "ResponseDevice") @@ -1520,6 +1821,17 @@ namespace Bit.SqliteMigrations.Migrations b.Navigation("Organization"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.ProviderOrganization", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") @@ -1556,6 +1868,17 @@ namespace Bit.SqliteMigrations.Migrations b.Navigation("User"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.Send", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") @@ -1571,6 +1894,17 @@ namespace Bit.SqliteMigrations.Migrations b.Navigation("User"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.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.Models.SsoConfig", b => { b.HasOne("Bit.Infrastructure.EntityFramework.Models.Organization", "Organization") @@ -1614,6 +1948,96 @@ namespace Bit.SqliteMigrations.Migrations b.Navigation("User"); }); + modelBuilder.Entity("ProjectSecret", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", null) + .WithMany() + .HasForeignKey("ProjectsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Secret", null) + .WithMany() + .HasForeignKey("SecretsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.GroupProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.GroupServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .HasForeignKey("GrantedServiceAccountId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Group", "Group") + .WithMany() + .HasForeignKey("GroupId"); + + b.Navigation("GrantedServiceAccount"); + + b.Navigation("Group"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.ServiceAccountProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.Project", "GrantedProject") + .WithMany("ServiceAccountAccessPolicies") + .HasForeignKey("GrantedProjectId"); + + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "ServiceAccount") + .WithMany() + .HasForeignKey("ServiceAccountId"); + + b.Navigation("GrantedProject"); + + b.Navigation("ServiceAccount"); + }); + + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.UserProjectAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.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.Models.UserServiceAccountAccessPolicy", b => + { + b.HasOne("Bit.Infrastructure.EntityFramework.Models.ServiceAccount", "GrantedServiceAccount") + .WithMany() + .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.Cipher", b => { b.Navigation("CollectionCiphers"); @@ -1659,6 +2083,15 @@ namespace Bit.SqliteMigrations.Migrations b.Navigation("CollectionUsers"); }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.Project", b => + { + b.Navigation("GroupAccessPolicies"); + + b.Navigation("ServiceAccountAccessPolicies"); + + b.Navigation("UserAccessPolicies"); + }); + modelBuilder.Entity("Bit.Infrastructure.EntityFramework.Models.User", b => { b.Navigation("Ciphers"); diff --git a/util/SqliteMigrations/packages.lock.json b/util/SqliteMigrations/packages.lock.json index 27cae9c36..840b75657 100644 --- a/util/SqliteMigrations/packages.lock.json +++ b/util/SqliteMigrations/packages.lock.json @@ -549,6 +549,15 @@ "Microsoft.Extensions.DependencyModel": "6.0.0" } }, + "Microsoft.EntityFrameworkCore.SqlServer": { + "type": "Transitive", + "resolved": "6.0.12", + "contentHash": "bdKnSz1w+WZz9QYWhs3wwGuMn4YssjdR+HOBpzChQ6C3+dblq4Pammm5fzugcPOhTgCiWftOT2jPOT5hEy4bYg==", + "dependencies": { + "Microsoft.Data.SqlClient": "2.1.4", + "Microsoft.EntityFrameworkCore.Relational": "6.0.12" + } + }, "Microsoft.Extensions.Caching.Abstractions": { "type": "Transitive", "resolved": "6.0.0", @@ -2757,6 +2766,7 @@ "AutoMapper.Extensions.Microsoft.DependencyInjection": "[11.0.0, )", "Core": "[2022.12.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, )",