From 82201c00eba9750d646b4da6c31832342a1e9ea2 Mon Sep 17 00:00:00 2001 From: Robert Y Date: Wed, 3 Jul 2024 08:49:54 -0600 Subject: [PATCH] Add rudimentary auto generation for 5000 users and ciphers --- util/DBSeeder/EFDBSeeder.cs | 120 +++++++++++++++++++++++------------- 1 file changed, 78 insertions(+), 42 deletions(-) diff --git a/util/DBSeeder/EFDBSeeder.cs b/util/DBSeeder/EFDBSeeder.cs index 119f43afd4b3..ecad691edc95 100644 --- a/util/DBSeeder/EFDBSeeder.cs +++ b/util/DBSeeder/EFDBSeeder.cs @@ -2,6 +2,7 @@ using Bit.Core.Vault.Enums; // Change this line using Bit.Infrastructure.EntityFramework.Repositories; using Bit.Infrastructure.EntityFramework.Vault.Models; +using Bogus; using Microsoft.Extensions.Logging; @@ -38,7 +39,7 @@ public bool SeedDatabase() // Seed the database SeedUsers(context); - SeedCipher(context); + SeedCiphers(context); Console.WriteLine("Database seeded successfully!"); } @@ -51,8 +52,12 @@ public bool SeedDatabase() } catch (Exception ex) { - Console.WriteLine($"An error occurred: {ex.Message}"); - return false; + Console.WriteLine($"Error adding users: {ex.Message}"); + if (ex.InnerException != null) + { + Console.WriteLine($"Inner exception: {ex.InnerException.Message}"); + } + throw; // Re-throw the exception to stop the seeding process } @@ -64,19 +69,29 @@ private void SeedUsers(DatabaseContext context) { if (!context.Users.Any()) { - context.Users.AddRange( - new Bit.Infrastructure.EntityFramework.Models.User // Specify the full namespace + Console.WriteLine("Generating 5000 users..."); + + var faker = new Faker() + .RuleFor(u => u.Id, f => Guid.NewGuid()) + .RuleFor(u => u.Name, f => f.Name.FullName()) + .RuleFor(u => u.Email, (f, u) => f.Internet.Email(u.Name)) + .RuleFor(u => u.EmailVerified, f => f.Random.Bool(0.9f)) + .RuleFor(u => u.SecurityStamp, f => Guid.NewGuid().ToString()) + .RuleFor(u => u.ApiKey, f => Guid.NewGuid().ToString("N").Substring(0, 30)) + .RuleFor(u => u.CreationDate, f => f.Date.Past(2)) + .RuleFor(u => u.RevisionDate, (f, u) => f.Date.Between(u.CreationDate, DateTime.UtcNow)); + + var users = faker.Generate(5000); + + const int batchSize = 100; + for (int i = 0; i < users.Count; i += batchSize) { - Id = Guid.NewGuid(), - Name = "Test User", - Email = "testuser@example.com", - EmailVerified = true, - SecurityStamp = Guid.NewGuid().ToString(), - ApiKey = "TestApiKey" + context.Users.AddRange(users.Skip(i).Take(batchSize)); + context.SaveChanges(); + Console.WriteLine($"Added {Math.Min(i + batchSize, users.Count)} users"); } - ); - context.SaveChanges(); - Console.WriteLine("Test user added to the database."); + + Console.WriteLine("5000 test users added to the database."); } else { @@ -84,46 +99,67 @@ private void SeedUsers(DatabaseContext context) } } - private void SeedCipher(DatabaseContext context) + private void SeedCiphers(DatabaseContext context) { if (!context.Ciphers.Any()) { - var testUser = context.Users.FirstOrDefault(); - if (testUser == null) + var users = context.Users.ToList(); + if (!users.Any()) { Console.WriteLine("No users found. Please seed users first."); return; } - var cipher = new Cipher - { - Id = Guid.NewGuid(), - UserId = testUser.Id, - OrganizationId = null, // Set this if needed - Type = CipherType.Login, - Data = JsonSerializer.Serialize(new + Console.WriteLine($"Generating ciphers for {users.Count} users..."); + + var faker = new Faker() + .RuleFor(c => c.Id, f => Guid.NewGuid()) + .RuleFor(c => c.Type, f => CipherType.Login) + .RuleFor(c => c.Data, f => JsonSerializer.Serialize(new { - Name = "Test Login", - Notes = "This is a test login cipher", + Name = f.Internet.DomainName(), + Notes = f.Lorem.Sentence(), Login = new { - Username = "testuser", - Password = "testpassword", - Uri = "https://example.com" + Username = f.Internet.UserName(), + Password = f.Internet.Password(), + Uri = f.Internet.Url() + } + })) + .RuleFor(c => c.CreationDate, f => f.Date.Past(1)) + .RuleFor(c => c.RevisionDate, (f, c) => f.Date.Between(c.CreationDate, DateTime.UtcNow)) + .RuleFor(c => c.DeletedDate, f => null) + .RuleFor(c => c.Reprompt, f => CipherRepromptType.None); + + const int batchSize = 100; + for (int i = 0; i < users.Count; i += batchSize) + { + var userBatch = users.Skip(i).Take(batchSize); + var ciphers = userBatch.Select(user => + { + var cipher = faker.Generate(); + cipher.UserId = user.Id; + return cipher; + }).ToList(); + + try + { + context.Ciphers.AddRange(ciphers); + context.SaveChanges(); + Console.WriteLine($"Added ciphers for users {i + 1} to {Math.Min(i + batchSize, users.Count)}"); + } + catch (Exception ex) + { + Console.WriteLine($"Error adding ciphers: {ex.Message}"); + if (ex.InnerException != null) + { + Console.WriteLine($"Inner exception: {ex.InnerException.Message}"); } - }), - Favorites = null, - Folders = null, - Attachments = null, - CreationDate = DateTime.UtcNow, - RevisionDate = DateTime.UtcNow, - DeletedDate = null, - Reprompt = CipherRepromptType.None - }; - - context.Ciphers.Add(cipher); - context.SaveChanges(); - Console.WriteLine("Test cipher added to the database."); + throw; // Re-throw the exception to stop the seeding process + } + } + + Console.WriteLine($"Ciphers added for all {users.Count} users."); } else {