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.
87 lines
2.7 KiB
87 lines
2.7 KiB
using System.Security.Cryptography; |
|
using System.Text; |
|
using Bit.Seeder.Data.Enums; |
|
using Bit.Seeder.Data.Generators; |
|
using Bit.Seeder.Options; |
|
|
|
namespace Bit.Seeder.Data; |
|
|
|
/// <summary> |
|
/// Centralized context for all data generators in a seeding operation. |
|
/// Lazy-initializes generators on first access to avoid creating unused instances. |
|
/// </summary> |
|
/// <remarks> |
|
/// Adding a new generator: |
|
/// 1. Add private nullable field |
|
/// 2. Add public property with lazy initialization |
|
/// 3. Use in Recipe via _ctx.NewGenerator.Method() |
|
/// </remarks> |
|
internal sealed class GeneratorContext |
|
{ |
|
private readonly int _seed; |
|
|
|
private readonly GeographicRegion _region; |
|
|
|
private readonly OrganizationVaultOptions _options; |
|
|
|
private GeneratorContext(int seed, GeographicRegion region, OrganizationVaultOptions options) |
|
{ |
|
_seed = seed; |
|
_region = region; |
|
_options = options; |
|
} |
|
|
|
/// <summary> |
|
/// Creates a GeneratorContext from vault options, deriving seed from domain if not specified. |
|
/// </summary> |
|
public static GeneratorContext FromOptions(OrganizationVaultOptions options) |
|
{ |
|
var seed = options.Seed ?? DeriveStableSeed(options.Domain); |
|
var region = options.Region ?? GeographicRegion.Global; |
|
return new GeneratorContext(seed, region, options); |
|
} |
|
|
|
/// <summary> |
|
/// Derives a stable 32-bit seed from a domain string using SHA256. |
|
/// Same input always produces same output for deterministic generation. |
|
/// </summary> |
|
private static int DeriveStableSeed(string domain) |
|
{ |
|
var bytes = SHA256.HashData(Encoding.UTF8.GetBytes(domain)); |
|
return BitConverter.ToInt32(bytes, 0); |
|
} |
|
|
|
/// <summary> |
|
/// The seed used for deterministic generation. Exposed for distribution calculations. |
|
/// </summary> |
|
public int Seed => _seed; |
|
|
|
/// <summary> |
|
/// Total cipher count from options. Used for distribution calculations. |
|
/// </summary> |
|
public int CipherCount => _options.Ciphers; |
|
|
|
private CipherUsernameGenerator? _username; |
|
|
|
public CipherUsernameGenerator Username => _username ??= new( |
|
_seed, |
|
_options.UsernameDistribution, |
|
_region, |
|
_options.UsernamePattern); |
|
|
|
private FolderNameGenerator? _folder; |
|
|
|
public FolderNameGenerator Folder => _folder ??= new(_seed); |
|
|
|
private CardDataGenerator? _card; |
|
|
|
public CardDataGenerator Card => _card ??= new(_seed, _region); |
|
|
|
private IdentityDataGenerator? _identity; |
|
|
|
public IdentityDataGenerator Identity => _identity ??= new(_seed, _region); |
|
|
|
private SecureNoteDataGenerator? _secureNote; |
|
|
|
public SecureNoteDataGenerator SecureNote => _secureNote ??= new(_seed); |
|
}
|
|
|