1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-08 13:12:16 -05:00

Extract recipe to separate file

This commit is contained in:
Hinton 2025-04-24 10:58:30 +02:00
parent db04c2c0e6
commit 92553822f0
No known key found for this signature in database
GPG Key ID: 5F7295599C5D965C
3 changed files with 42 additions and 109 deletions

View File

@ -1,8 +1,6 @@
using Bit.Infrastructure.EntityFramework.Models;
using Bit.Seeder.Factories;
using Bit.Seeder.Recipes;
using Bit.Seeder.Settings;
using Bit.SharedWeb.Utilities;
using LinqToDB.EntityFrameworkCore;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -19,40 +17,15 @@ public class GenerateCommand
ConfigureServices(services);
var serviceProvider = services.BuildServiceProvider();
var logger = serviceProvider.GetRequiredService<ILogger<GenerateCommand>>();
// TODO: Can we remove GenerateCommand and provide a RecipeFactory or something. Or wire up DI.
using var scope = serviceProvider.CreateScope();
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<DatabaseContext>();
var organization = OrganizationSeeder.CreateEnterprise(name, domain, users);
var user = UserSeeder.CreateUser($"admin@{domain}");
var orgUser = organization.CreateOrganizationUser(user);
var additionalUsers = new List<User>();
var additionalOrgUsers = new List<OrganizationUser>();
for (var i = 0; i < users; i++)
{
var additionalUser = UserSeeder.CreateUser($"user{i}@{domain}");
additionalUsers.Add(additionalUser);
additionalOrgUsers.Add(organization.CreateOrganizationUser(additionalUser));
}
using (var scope = serviceProvider.CreateScope())
{
var scopedServices = scope.ServiceProvider;
var db = scopedServices.GetRequiredService<DatabaseContext>();
db.Add(organization);
db.Add(user);
db.Add(orgUser);
db.SaveChanges();
// Use LinqToDB's BulkCopy for significant better performance
db.BulkCopy(additionalUsers);
db.BulkCopy(additionalOrgUsers);
}
var recipe = new OrganizationWithUsersRecipe(db);
recipe.Seed(name, users, domain);
return true;
}
private void ConfigureServices(ServiceCollection services)

View File

@ -0,0 +1,35 @@
using Bit.Infrastructure.EntityFramework.Models;
using Bit.Infrastructure.EntityFramework.Repositories;
using Bit.Seeder.Factories;
using LinqToDB.EntityFrameworkCore;
namespace Bit.Seeder.Recipes;
public class OrganizationWithUsersRecipe(DatabaseContext db)
{
public void Seed(string name, int users, string domain)
{
var organization = OrganizationSeeder.CreateEnterprise(name, domain, users);
var user = UserSeeder.CreateUser($"admin@{domain}");
var orgUser = organization.CreateOrganizationUser(user);
var additionalUsers = new List<User>();
var additionalOrgUsers = new List<OrganizationUser>();
for (var i = 0; i < users; i++)
{
var additionalUser = UserSeeder.CreateUser($"user{i}@{domain}");
additionalUsers.Add(additionalUser);
additionalOrgUsers.Add(organization.CreateOrganizationUser(additionalUser));
}
db.Add(organization);
db.Add(user);
db.Add(orgUser);
db.SaveChanges();
// Use LinqToDB's BulkCopy for significant better performance
db.BulkCopy(additionalUsers);
db.BulkCopy(additionalOrgUsers);
}
}

View File

@ -1,75 +0,0 @@
using Bit.Core.Entities;
using Bit.Core.Settings;
using Bit.Core.Vault.Entities;
using Microsoft.EntityFrameworkCore;
namespace Bit.Seeder.Services;
public class DatabaseContext : DbContext
{
private readonly GlobalSettings _globalSettings;
public DatabaseContext(GlobalSettings globalSettings)
{
_globalSettings = globalSettings;
}
public DbSet<User> Users { get; set; }
public DbSet<Cipher> Ciphers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var provider = _globalSettings.DatabaseProvider ?? string.Empty;
Console.WriteLine($"Database Provider: '{provider}'");
// Output all available connection strings for debugging
Console.WriteLine($"SqlServer ConnectionString available: {!string.IsNullOrEmpty(_globalSettings.SqlServer?.ConnectionString)}");
Console.WriteLine($"PostgreSql ConnectionString available: {!string.IsNullOrEmpty(_globalSettings.PostgreSql?.ConnectionString)}");
Console.WriteLine($"MySql ConnectionString available: {!string.IsNullOrEmpty(_globalSettings.MySql?.ConnectionString)}");
Console.WriteLine($"Sqlite ConnectionString available: {!string.IsNullOrEmpty(_globalSettings.Sqlite?.ConnectionString)}");
var connectionString = _globalSettings.DatabaseProvider switch
{
"postgres" => _globalSettings.PostgreSql?.ConnectionString,
"mysql" => _globalSettings.MySql?.ConnectionString,
"sqlite" => _globalSettings.Sqlite?.ConnectionString,
_ => _globalSettings.SqlServer?.ConnectionString
};
Console.WriteLine($"Using connection string: {connectionString}");
switch (_globalSettings.DatabaseProvider)
{
case "postgres":
optionsBuilder.UseNpgsql(connectionString);
break;
case "mysql":
optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
break;
case "sqlite":
optionsBuilder.UseSqlite(connectionString);
break;
default:
optionsBuilder.UseSqlServer(connectionString);
break;
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Cipher>(entity =>
{
entity.ToTable("Cipher");
entity.Property(e => e.Type).HasConversion<int>();
entity.Property(e => e.Reprompt).HasConversion<int>();
});
modelBuilder.Entity<User>(entity =>
{
entity.ToTable("User");
entity.Property(e => e.Kdf).HasConversion<int>();
});
}
}