mirror of
https://github.com/bitwarden/server
synced 2026-02-21 11:53:42 +00:00
Implement Bogus for name generation & Region specific usernames for vault items
This commit is contained in:
78
util/Seeder/Data/BogusNameProvider.cs
Normal file
78
util/Seeder/Data/BogusNameProvider.cs
Normal file
@@ -0,0 +1,78 @@
|
||||
using Bit.Seeder.Data.Enums;
|
||||
using Bogus;
|
||||
using Bogus.DataSets;
|
||||
|
||||
namespace Bit.Seeder.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Provides locale-aware name generation using the Bogus library.
|
||||
/// Maps GeographicRegion to appropriate Bogus locales for culturally-appropriate names.
|
||||
/// </summary>
|
||||
internal sealed class BogusNameProvider
|
||||
{
|
||||
private readonly Faker _faker;
|
||||
|
||||
public BogusNameProvider(GeographicRegion region, int? seed = null)
|
||||
{
|
||||
var locale = MapRegionToLocale(region, seed);
|
||||
_faker = seed.HasValue
|
||||
? new Faker(locale) { Random = new Randomizer(seed.Value) }
|
||||
: new Faker(locale);
|
||||
}
|
||||
|
||||
public string FirstName() => _faker.Name.FirstName();
|
||||
|
||||
public string FirstName(Name.Gender gender) => _faker.Name.FirstName(gender);
|
||||
|
||||
public string LastName() => _faker.Name.LastName();
|
||||
|
||||
private static string MapRegionToLocale(GeographicRegion region, int? seed) => region switch
|
||||
{
|
||||
GeographicRegion.NorthAmerica => "en_US",
|
||||
GeographicRegion.Europe => GetRandomEuropeanLocale(seed),
|
||||
GeographicRegion.AsiaPacific => GetRandomAsianLocale(seed),
|
||||
GeographicRegion.LatinAmerica => GetRandomLatinAmericanLocale(seed),
|
||||
GeographicRegion.MiddleEast => GetRandomMiddleEastLocale(seed),
|
||||
GeographicRegion.Africa => GetRandomAfricanLocale(seed),
|
||||
GeographicRegion.Global => "en",
|
||||
_ => "en"
|
||||
};
|
||||
|
||||
private static string GetRandomEuropeanLocale(int? seed)
|
||||
{
|
||||
var locales = new[] { "en_GB", "de", "fr", "es", "it", "nl", "pl", "pt_PT", "sv" };
|
||||
return PickLocale(locales, seed);
|
||||
}
|
||||
|
||||
private static string GetRandomAsianLocale(int? seed)
|
||||
{
|
||||
var locales = new[] { "ja", "ko", "zh_CN", "zh_TW", "vi" };
|
||||
return PickLocale(locales, seed);
|
||||
}
|
||||
|
||||
private static string GetRandomLatinAmericanLocale(int? seed)
|
||||
{
|
||||
var locales = new[] { "es_MX", "pt_BR", "es" };
|
||||
return PickLocale(locales, seed);
|
||||
}
|
||||
|
||||
private static string GetRandomMiddleEastLocale(int? seed)
|
||||
{
|
||||
// Bogus has limited Middle East support; use available Arabic/Turkish locales
|
||||
var locales = new[] { "ar", "tr", "fa" };
|
||||
return PickLocale(locales, seed);
|
||||
}
|
||||
|
||||
private static string GetRandomAfricanLocale(int? seed)
|
||||
{
|
||||
// Bogus has limited African support; use South African English and French (West Africa)
|
||||
var locales = new[] { "en_ZA", "fr" };
|
||||
return PickLocale(locales, seed);
|
||||
}
|
||||
|
||||
private static string PickLocale(string[] locales, int? seed)
|
||||
{
|
||||
var random = seed.HasValue ? new Random(seed.Value) : Random.Shared;
|
||||
return locales[random.Next(locales.Length)];
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,13 @@ namespace Bit.Seeder.Data;
|
||||
|
||||
/// <summary>
|
||||
/// Generates deterministic usernames for companies using configurable patterns.
|
||||
/// Uses Bogus library for locale-aware name generation while maintaining determinism
|
||||
/// through pre-generated arrays indexed by a seed.
|
||||
/// </summary>
|
||||
internal sealed class UsernameGenerator
|
||||
internal sealed class CipherUsernameGenerator
|
||||
{
|
||||
private const int _namePoolSize = 1500;
|
||||
|
||||
private readonly Random _random;
|
||||
|
||||
private readonly UsernamePattern _pattern;
|
||||
@@ -15,7 +19,7 @@ internal sealed class UsernameGenerator
|
||||
|
||||
private readonly string[] _lastNames;
|
||||
|
||||
public UsernameGenerator(
|
||||
public CipherUsernameGenerator(
|
||||
int seed,
|
||||
UsernamePatternType patternType = UsernamePatternType.FirstDotLast,
|
||||
GeographicRegion? region = null)
|
||||
@@ -23,12 +27,10 @@ internal sealed class UsernameGenerator
|
||||
_random = new Random(seed);
|
||||
_pattern = UsernamePatterns.GetPattern(patternType);
|
||||
|
||||
(_firstNames, _lastNames) = region switch
|
||||
{
|
||||
GeographicRegion.NorthAmerica => (Names.UsFirstNames, Names.UsLastNames),
|
||||
GeographicRegion.Europe => (Names.EuropeanFirstNames, Names.EuropeanLastNames),
|
||||
_ => (Names.AllFirstNames, Names.AllLastNames)
|
||||
};
|
||||
// Pre-generate arrays from Bogus for deterministic index-based access
|
||||
var provider = new BogusNameProvider(region ?? GeographicRegion.Global, seed);
|
||||
_firstNames = Enumerable.Range(0, _namePoolSize).Select(_ => provider.FirstName()).ToArray();
|
||||
_lastNames = Enumerable.Range(0, _namePoolSize).Select(_ => provider.LastName()).ToArray();
|
||||
}
|
||||
|
||||
public string Generate(Company company)
|
||||
@@ -1,80 +0,0 @@
|
||||
namespace Bit.Seeder.Data;
|
||||
|
||||
/// <summary>
|
||||
/// First and last names organized by region for username generation.
|
||||
/// Add new regions by creating arrays and including them in the All* properties.
|
||||
/// </summary>
|
||||
internal static class Names
|
||||
{
|
||||
public static readonly string[] UsFirstNames =
|
||||
[
|
||||
// Male
|
||||
"James", "Robert", "John", "Michael", "David", "William", "Richard", "Joseph", "Thomas", "Christopher",
|
||||
"Charles", "Daniel", "Matthew", "Anthony", "Mark", "Donald", "Steven", "Paul", "Andrew", "Joshua",
|
||||
"Kenneth", "Kevin", "Brian", "George", "Timothy", "Ronald", "Edward", "Jason", "Jeffrey", "Ryan",
|
||||
"Jacob", "Gary", "Nicholas", "Eric", "Jonathan", "Stephen", "Larry", "Justin", "Scott", "Brandon",
|
||||
"Benjamin", "Samuel", "Raymond", "Gregory", "Frank", "Alexander", "Patrick", "Jack", "Dennis", "Jerry",
|
||||
// Female
|
||||
"Mary", "Patricia", "Jennifer", "Linda", "Barbara", "Elizabeth", "Susan", "Jessica", "Sarah", "Karen",
|
||||
"Lisa", "Nancy", "Betty", "Margaret", "Sandra", "Ashley", "Kimberly", "Emily", "Donna", "Michelle",
|
||||
"Dorothy", "Carol", "Amanda", "Melissa", "Deborah", "Stephanie", "Rebecca", "Sharon", "Laura", "Cynthia",
|
||||
"Kathleen", "Amy", "Angela", "Shirley", "Anna", "Brenda", "Pamela", "Emma", "Nicole", "Helen",
|
||||
"Samantha", "Katherine", "Christine", "Debra", "Rachel", "Carolyn", "Janet", "Catherine", "Maria", "Heather"
|
||||
];
|
||||
|
||||
public static readonly string[] UsLastNames =
|
||||
[
|
||||
"Smith", "Johnson", "Williams", "Brown", "Jones", "Garcia", "Miller", "Davis", "Rodriguez", "Martinez",
|
||||
"Hernandez", "Lopez", "Gonzalez", "Wilson", "Anderson", "Thomas", "Taylor", "Moore", "Jackson", "Martin",
|
||||
"Lee", "Perez", "Thompson", "White", "Harris", "Sanchez", "Clark", "Ramirez", "Lewis", "Robinson",
|
||||
"Walker", "Young", "Allen", "King", "Wright", "Scott", "Torres", "Nguyen", "Hill", "Flores",
|
||||
"Green", "Adams", "Nelson", "Baker", "Hall", "Rivera", "Campbell", "Mitchell", "Carter", "Roberts",
|
||||
"Gomez", "Phillips", "Evans", "Turner", "Diaz", "Parker", "Cruz", "Edwards", "Collins", "Reyes",
|
||||
"Stewart", "Morris", "Morales", "Murphy", "Cook", "Rogers", "Gutierrez", "Ortiz", "Morgan", "Cooper",
|
||||
"Peterson", "Bailey", "Reed", "Kelly", "Howard", "Ramos", "Kim", "Cox", "Ward", "Richardson",
|
||||
"Watson", "Brooks", "Chavez", "Wood", "James", "Bennett", "Gray", "Mendoza", "Ruiz", "Hughes",
|
||||
"Price", "Alvarez", "Castillo", "Sanders", "Patel", "Myers", "Long", "Ross", "Foster", "Jimenez"
|
||||
];
|
||||
|
||||
public static readonly string[] EuropeanFirstNames =
|
||||
[
|
||||
// British
|
||||
"Oliver", "George", "Harry", "Jack", "Charlie", "Thomas", "Oscar", "William", "James", "Henry",
|
||||
"Olivia", "Amelia", "Isla", "Ava", "Emily", "Sophie", "Grace", "Mia", "Poppy", "Ella",
|
||||
// German
|
||||
"Maximilian", "Alexander", "Paul", "Leon", "Lukas", "Felix", "Noah", "Elias", "Ben", "Finn",
|
||||
"Emma", "Hannah", "Mia", "Sofia", "Anna", "Emilia", "Lena", "Marie", "Lea", "Clara",
|
||||
// French
|
||||
"Gabriel", "Raphael", "Leo", "Louis", "Lucas", "Adam", "Hugo", "Jules", "Arthur", "Nathan",
|
||||
"Louise", "Alice", "Chloe", "Ines", "Lea", "Manon", "Rose", "Anna", "Lina", "Mila",
|
||||
// Spanish
|
||||
"Hugo", "Martin", "Lucas", "Daniel", "Pablo", "Alejandro", "Adrian", "Alvaro", "David", "Mario",
|
||||
"Lucia", "Sofia", "Maria", "Martina", "Paula", "Julia", "Daniela", "Valeria", "Alba", "Emma",
|
||||
// Italian
|
||||
"Leonardo", "Francesco", "Alessandro", "Lorenzo", "Mattia", "Andrea", "Gabriele", "Riccardo", "Tommaso", "Edoardo",
|
||||
"Sofia", "Giulia", "Aurora", "Alice", "Ginevra", "Emma", "Giorgia", "Greta", "Beatrice", "Anna"
|
||||
];
|
||||
|
||||
public static readonly string[] EuropeanLastNames =
|
||||
[
|
||||
// British
|
||||
"Smith", "Jones", "Williams", "Brown", "Taylor", "Davies", "Wilson", "Evans", "Thomas", "Johnson",
|
||||
"Roberts", "Walker", "Wright", "Robinson", "Thompson", "White", "Hughes", "Edwards", "Green", "Hall",
|
||||
// German
|
||||
"Mueller", "Schmidt", "Schneider", "Fischer", "Weber", "Meyer", "Wagner", "Becker", "Schulz", "Hoffmann",
|
||||
"Schaefer", "Koch", "Bauer", "Richter", "Klein", "Wolf", "Schroeder", "Neumann", "Schwarz", "Zimmermann",
|
||||
// French
|
||||
"Martin", "Bernard", "Dubois", "Thomas", "Robert", "Richard", "Petit", "Durand", "Leroy", "Moreau",
|
||||
"Simon", "Laurent", "Lefebvre", "Michel", "Garcia", "David", "Bertrand", "Roux", "Vincent", "Fournier",
|
||||
// Spanish
|
||||
"Garcia", "Rodriguez", "Martinez", "Lopez", "Sanchez", "Gonzalez", "Perez", "Martin", "Gomez", "Ruiz",
|
||||
"Hernandez", "Jimenez", "Diaz", "Moreno", "Alvarez", "Munoz", "Romero", "Alonso", "Gutierrez", "Navarro",
|
||||
// Italian
|
||||
"Rossi", "Russo", "Ferrari", "Esposito", "Bianchi", "Romano", "Colombo", "Ricci", "Marino", "Greco",
|
||||
"Bruno", "Gallo", "Conti", "DeLuca", "Costa", "Giordano", "Mancini", "Rizzo", "Lombardi", "Moretti"
|
||||
];
|
||||
|
||||
public static readonly string[] AllFirstNames = [.. UsFirstNames, .. EuropeanFirstNames];
|
||||
|
||||
public static readonly string[] AllLastNames = [.. UsLastNames, .. EuropeanLastNames];
|
||||
}
|
||||
Reference in New Issue
Block a user