package seed import ( "crypto/rand" "encoding/hex" "fmt" "time" "github.com/brianvoe/gofakeit/v6" "gorm.io/gorm" "server/internal/auth" "server/internal/models" ) // Credential exposes the plaintext password generated for a seeded user. type Credential struct { Email string Password string } // SeedUsers generates n fake users and persists them. Returns the created slice. func SeedUsers(db *gorm.DB, n int) ([]models.User, []Credential, error) { if n <= 0 { return nil, nil, fmt.Errorf("seed size must be greater than zero") } gofakeit.Seed(time.Now().UnixNano()) items := make([]models.User, 0, n) creds := make([]Credential, 0, n) for i := 0; i < n; i++ { now := time.Now().UTC() uuid := gofakeit.UUID() email := gofakeit.Email() pw, err := randomPassword() if err != nil { return nil, nil, fmt.Errorf("generate password: %w", err) } passwordHash, err := auth.HashPassword(pw) if err != nil { return nil, nil, fmt.Errorf("hash seed password: %w", err) } item := models.User{ Email: email, Name: gofakeit.Name(), Password: passwordHash, Roles: models.UserRoles{"user"}, Status: models.UserStatusActive, Types: models.UserTypes{"internal"}, UUID: uuid, Details: &models.UserDetails{ Title: gofakeit.JobTitle(), FirstName: gofakeit.FirstName(), LastName: gofakeit.LastName(), Phone: gofakeit.Phone(), Address: gofakeit.Street(), City: gofakeit.City(), ZipCode: gofakeit.Zip(), Country: gofakeit.Country(), }, Preferences: &models.UserPreferences{ UseIdle: gofakeit.Bool(), IdleTimeout: gofakeit.Number(1, 30), UseIdlePassword: gofakeit.Bool(), IdlePin: gofakeit.DigitN(6), UseDirectLogin: gofakeit.Bool(), UseQuadcodeLogin: gofakeit.Bool(), SendNoticesMail: gofakeit.Bool(), Language: gofakeit.Language(), }, Avatar: nil, CreatedAt: now, UpdatedAt: now, ActivatedAt: func() *time.Time { ts := now return &ts }(), } items = append(items, item) creds = append(creds, Credential{ Email: email, Password: pw, }) } if err := db.Create(&items).Error; err != nil { return nil, nil, fmt.Errorf("insert users: %w", err) } return items, creds, nil } func randomPassword() (string, error) { buf := make([]byte, 12) if _, err := rand.Read(buf); err != nil { return "", err } // hex-encoded -> 24 characters. return hex.EncodeToString(buf), nil }