// Command seed_users 预置内部账号(运营/编辑用,不开放公开注册)。 // // 项目已移除 AutoMigrate,表结构由 scripts/sql/005_create_users.sql 托管; // 本脚本用 CREATE TABLE IF NOT EXISTS 兜底建表,再 upsert 一个内部账号。 // // 用法: // go run ./scripts/seed_users // SEED_ADMIN_PASSWORD='你的强密码' go run ./scripts/seed_users // // 默认账号 admin / admin@studio.local,密码取环境变量 SEED_ADMIN_PASSWORD, // 缺省回落强密码常量。生产部署请务必通过环境变量指定并尽快修改。 package main import ( "errors" "flag" "log" "os" "golang.org/x/crypto/bcrypt" "gorm.io/gorm" "fashionapi/internal/config" "fashionapi/internal/database" "fashionapi/internal/model" ) func main() { configPath := flag.String("config", "", "配置文件路径,默认查找 configs/config.yml") flag.Parse() cfg, err := config.Load(*configPath) if err != nil { log.Fatalf("✗ 加载配置失败: %v", err) } db, err := database.New(cfg.Database) if err != nil { log.Fatalf("✗ 连接数据库失败: %v", err) } defer func() { if e := database.Close(db); e != nil { log.Printf("! 关闭数据库连接失败: %v", e) } }() // 1. 兜底建表(与 scripts/sql/005_create_users.sql 完全一致) createSQL := `CREATE TABLE IF NOT EXISTS users ( id int unsigned NOT NULL AUTO_INCREMENT, created_at int unsigned NOT NULL DEFAULT 0, updated_at int unsigned NOT NULL DEFAULT 0, username varchar(64) NOT NULL, email varchar(191) NOT NULL, password_hash varchar(255) NOT NULL DEFAULT '', is_deleted tinyint unsigned NOT NULL DEFAULT 0, PRIMARY KEY (id), UNIQUE KEY uk_username (username), UNIQUE KEY uk_email (email) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;` if e := db.Exec(createSQL).Error; e != nil { log.Fatalf("✗ 建表失败: %v", e) } log.Println("✓ users 表就绪") // 2. 预置内部账号 // admin: 正式内部账号,密码取环境变量 SEED_ADMIN_PASSWORD(缺省回落强密码常量)。 // root: 测试账号,固定弱密码 root,仅供本地联调使用,勿用于生产。 adminPassword := os.Getenv("SEED_ADMIN_PASSWORD") if adminPassword == "" { adminPassword = "Studio#2026!Admin" } accounts := []struct { username string email string password string }{ {username: "admin", email: "admin@studio.local", password: adminPassword}, {username: "root", email: "root@studio.local", password: "root"}, } for _, acc := range accounts { hash, e := bcrypt.GenerateFromPassword([]byte(acc.password), bcrypt.DefaultCost) if e != nil { log.Fatalf("✗ 生成密码哈希失败(%s): %v", acc.username, e) } var existing model.User qerr := db.Where("username = ?", acc.username).First(&existing).Error switch { case errors.Is(qerr, gorm.ErrRecordNotFound): user := model.User{Username: acc.username, Email: acc.email, PasswordHash: string(hash)} if cerr := db.Create(&user).Error; cerr != nil { log.Fatalf("✗ 创建内部账号失败(%s): %v", acc.username, cerr) } log.Printf("✓ 已创建内部账号: %s / %s", acc.username, acc.email) case qerr != nil: log.Fatalf("✗ 查询账号失败(%s): %v", acc.username, qerr) default: existing.PasswordHash = string(hash) if uerr := db.Save(&existing).Error; uerr != nil { log.Fatalf("✗ 更新账号密码失败(%s): %v", acc.username, uerr) } log.Printf("✓ 内部账号已存在,已刷新密码哈希: %s", acc.username) } log.Printf("ℹ 账号 %s 登录方式: %s / 密码: %s", acc.username, acc.username, acc.password) } log.Println("⚠ admin 为强密码账号请尽快改默认密码;root 为弱密码测试账号,仅本地使用") }