You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
148 lines
4.8 KiB
148 lines
4.8 KiB
using Bit.Seeder.Recipes; |
|
using Bit.Seeder.Services; |
|
using Bit.SeederUtility.Configuration; |
|
using Bit.SeederUtility.Helpers; |
|
using CommandDotNet; |
|
|
|
namespace Bit.SeederUtility.Commands; |
|
|
|
[Command("seed", Description = "Seed database using fixture-based presets")] |
|
public class SeedCommand |
|
{ |
|
[DefaultCommand] |
|
public void Execute(SeedArgs args) |
|
{ |
|
try |
|
{ |
|
args.Validate(); |
|
|
|
if (args.List) |
|
{ |
|
PrintAvailableSeeds(); |
|
return; |
|
} |
|
|
|
if (IsIndividualPreset(args.Preset!)) |
|
{ |
|
SeedIndividual(args); |
|
} |
|
else |
|
{ |
|
SeedOrganization(args); |
|
} |
|
} |
|
catch (Exception ex) when (ex is ArgumentException or InvalidOperationException) |
|
{ |
|
Console.Error.WriteLine($"Error: {ex.Message}"); |
|
Environment.Exit(1); |
|
} |
|
} |
|
|
|
private static void SeedOrganization(SeedArgs args) |
|
{ |
|
using var deps = SeederServiceFactory.Create(new SeederServiceOptions { EnableMangling = args.Mangle }); |
|
var recipe = new OrganizationRecipe(deps.ToDependencies()); |
|
|
|
Console.WriteLine($"Seeding organization from preset '{args.Preset}'..."); |
|
var result = recipe.Seed(args.Preset!, args.Password, args.KdfIterations); |
|
|
|
ConsoleOutput.PrintRow("Organization", result.OrganizationId); |
|
if (result.OwnerEmail is not null) |
|
{ |
|
ConsoleOutput.PrintRow("Owner", result.OwnerEmail); |
|
} |
|
ConsoleOutput.PrintRow("Password", result.Password); |
|
if (result.ApiKey is not null) |
|
{ |
|
ConsoleOutput.PrintRow("ApiKey", result.ApiKey); |
|
} |
|
ConsoleOutput.PrintCountRow("Users", result.UsersCount); |
|
ConsoleOutput.PrintCountRow("Groups", result.GroupsCount); |
|
ConsoleOutput.PrintCountRow("Collections", result.CollectionsCount); |
|
ConsoleOutput.PrintCountRow("Ciphers", result.CiphersCount); |
|
|
|
ConsoleOutput.PrintMangleMap(deps); |
|
} |
|
|
|
private static void SeedIndividual(SeedArgs args) |
|
{ |
|
using var deps = SeederServiceFactory.Create(new SeederServiceOptions { EnableMangling = args.Mangle }); |
|
var recipe = new IndividualUserRecipe(deps.ToDependencies()); |
|
|
|
Console.WriteLine($"Seeding individual user from preset '{args.Preset}'..."); |
|
var result = recipe.Seed(args.Preset!, args.Password, args.KdfIterations); |
|
|
|
ConsoleOutput.PrintRow("User", result.UserId); |
|
if (result.Email is not null) |
|
{ |
|
ConsoleOutput.PrintRow("Email", result.Email); |
|
} |
|
ConsoleOutput.PrintRow("Password", result.Password); |
|
ConsoleOutput.PrintRow("Premium", result.Premium); |
|
if (result.ApiKey is not null) |
|
{ |
|
ConsoleOutput.PrintRow("ApiKey", result.ApiKey); |
|
} |
|
ConsoleOutput.PrintCountRow("Folders", result.FoldersCount); |
|
ConsoleOutput.PrintCountRow("Ciphers", result.CiphersCount); |
|
|
|
ConsoleOutput.PrintMangleMap(deps); |
|
} |
|
|
|
private static void PrintAvailableSeeds() |
|
{ |
|
var available = PresetCatalogService.ListAvailable(); |
|
|
|
var orgPresets = new List<string>(); |
|
var individualPresets = new List<string>(); |
|
|
|
foreach (var presetName in available.Presets) |
|
{ |
|
if (IsIndividualPreset(presetName)) |
|
{ |
|
individualPresets.Add(presetName); |
|
} |
|
else |
|
{ |
|
orgPresets.Add(presetName); |
|
} |
|
} |
|
|
|
Console.WriteLine("Organization Presets:"); |
|
foreach (var preset in orgPresets) |
|
{ |
|
Console.WriteLine($" - {preset}"); |
|
} |
|
Console.WriteLine(); |
|
|
|
Console.WriteLine("Individual User Presets:"); |
|
foreach (var preset in individualPresets) |
|
{ |
|
Console.WriteLine($" - {preset}"); |
|
} |
|
Console.WriteLine(); |
|
|
|
Console.WriteLine("Available Fixtures:"); |
|
foreach (var (category, fixtures) in available.Fixtures.OrderBy(kvp => kvp.Key)) |
|
{ |
|
// Guard: Skip empty or single-character categories to prevent IndexOutOfRangeException |
|
if (string.IsNullOrEmpty(category) || category.Length < 2) |
|
{ |
|
continue; |
|
} |
|
|
|
var categoryName = char.ToUpperInvariant(category[0]) + category[1..]; |
|
Console.WriteLine($" {categoryName}:"); |
|
foreach (var fixture in fixtures) |
|
{ |
|
Console.WriteLine($" - {fixture}"); |
|
} |
|
} |
|
|
|
Console.WriteLine(); |
|
Console.WriteLine("Use: SeederUtility seed --preset <name>"); |
|
} |
|
|
|
private static bool IsIndividualPreset(string presetName) => |
|
PresetCatalogService.IsIndividualPreset(presetName); |
|
}
|
|
|