feat: reduce hashing cost by removing redundant password hashing

This commit is contained in:
2025-11-21 16:11:33 +01:00
parent 4cdda3f944
commit c020517ccf

View File

@@ -104,12 +104,25 @@ func seedDatabase(userRepo repositories.UserRepository, postRepo repositories.Po
fmt.Println("Starting database seeding...") fmt.Println("Starting database seeding...")
} }
seedPassword := "seed-password"
userPassword := "password123"
seedPasswordHash, err := bcrypt.GenerateFromPassword([]byte(seedPassword), bcrypt.DefaultCost)
if err != nil {
return fmt.Errorf("precompute seed password hash: %w", err)
}
userPasswordHash, err := bcrypt.GenerateFromPassword([]byte(userPassword), bcrypt.DefaultCost)
if err != nil {
return fmt.Errorf("precompute user password hash: %w", err)
}
spinner := NewSpinner("Creating seed user") spinner := NewSpinner("Creating seed user")
if !IsJSONOutput() { if !IsJSONOutput() {
spinner.Spin() spinner.Spin()
} }
seedUser, err := ensureSeedUser(userRepo) seedUser, err := ensureSeedUser(userRepo, string(seedPasswordHash))
if err != nil { if err != nil {
if !IsJSONOutput() { if !IsJSONOutput() {
spinner.Complete() spinner.Complete()
@@ -122,6 +135,7 @@ func seedDatabase(userRepo repositories.UserRepository, postRepo repositories.Po
} }
processor := NewParallelProcessor() processor := NewParallelProcessor()
processor.SetPasswordHash(string(userPasswordHash))
var progress *ProgressIndicator var progress *ProgressIndicator
if !IsJSONOutput() && *numUsers > 0 { if !IsJSONOutput() && *numUsers > 0 {
@@ -213,22 +227,16 @@ func findExistingSeedUser(userRepo repositories.UserRepository) (*database.User,
return nil, fmt.Errorf("no existing seed user found") return nil, fmt.Errorf("no existing seed user found")
} }
func ensureSeedUser(userRepo repositories.UserRepository) (*database.User, error) { func ensureSeedUser(userRepo repositories.UserRepository, passwordHash string) (*database.User, error) {
existingUser, err := findExistingSeedUser(userRepo) existingUser, err := findExistingSeedUser(userRepo)
if err == nil && existingUser != nil { if err == nil && existingUser != nil {
return existingUser, nil return existingUser, nil
} }
seedPassword := "seed-password"
randomID := generateRandomIdentifier() randomID := generateRandomIdentifier()
seedUsername := fmt.Sprintf("seed_admin_%s", randomID) seedUsername := fmt.Sprintf("seed_admin_%s", randomID)
seedEmail := fmt.Sprintf("seed_admin_%s@goyco.local", randomID) seedEmail := fmt.Sprintf("seed_admin_%s@goyco.local", randomID)
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(seedPassword), bcrypt.DefaultCost)
if err != nil {
return nil, fmt.Errorf("hash password: %w", err)
}
const maxRetries = 10 const maxRetries = 10
for range maxRetries { for range maxRetries {
user, err := userRepo.GetByEmail(seedEmail) user, err := userRepo.GetByEmail(seedEmail)
@@ -239,7 +247,7 @@ func ensureSeedUser(userRepo repositories.UserRepository) (*database.User, error
user = &database.User{ user = &database.User{
Username: seedUsername, Username: seedUsername,
Email: seedEmail, Email: seedEmail,
Password: string(hashedPassword), Password: passwordHash,
EmailVerified: true, EmailVerified: true,
} }
@@ -256,23 +264,17 @@ func ensureSeedUser(userRepo repositories.UserRepository) (*database.User, error
return nil, fmt.Errorf("failed to create seed user after %d attempts", maxRetries) return nil, fmt.Errorf("failed to create seed user after %d attempts", maxRetries)
} }
func createRandomUsers(userRepo repositories.UserRepository, count int) ([]database.User, error) { func createRandomUsers(userRepo repositories.UserRepository, count int, passwordHash string) ([]database.User, error) {
var users []database.User var users []database.User
for i := range count { for i := range count {
username := fmt.Sprintf("user_%d", i+1) username := fmt.Sprintf("user_%d", i+1)
email := fmt.Sprintf("user_%d@goyco.local", i+1) email := fmt.Sprintf("user_%d@goyco.local", i+1)
password := "password123"
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return nil, fmt.Errorf("hash password for user %d: %w", i+1, err)
}
user := &database.User{ user := &database.User{
Username: username, Username: username,
Email: email, Email: email,
Password: string(hashedPassword), Password: passwordHash,
EmailVerified: true, EmailVerified: true,
} }