package store import ( "database/sql" "fmt" "time" _ "github.com/lib/pq" ) // User 用户模型 type User struct { ID int `json:"id"` Username string `json:"username"` PasswordHash string `json:"-"` IsAdmin bool `json:"is_admin"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // CreateUsersTable 创建 users 表(如果不存在) func CreateUsersTable(db *sql.DB) error { query := `CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, is_admin BOOLEAN DEFAULT FALSE, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() )` if _, err := db.Exec(query); err != nil { return fmt.Errorf("创建 users 表失败: %w", err) } // 创建索引 indexQueries := []string{ `CREATE INDEX IF NOT EXISTS idx_users_username ON users(username)`, } for _, q := range indexQueries { if _, err := db.Exec(q); err != nil { return fmt.Errorf("创建 users 索引失败: %w", err) } } return nil } // GetUserByUsername 按用户名查询用户 // 如果用户不存在,返回 (nil, nil) func GetUserByUsername(db *sql.DB, username string) (*User, error) { var u User err := db.QueryRow( `SELECT id, username, password_hash, is_admin, created_at, updated_at FROM users WHERE username = $1`, username, ).Scan(&u.ID, &u.Username, &u.PasswordHash, &u.IsAdmin, &u.CreatedAt, &u.UpdatedAt) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, fmt.Errorf("查询用户失败: %w", err) } return &u, nil } // CreateUser 创建新用户 func CreateUser(db *sql.DB, username, passwordHash string, isAdmin bool) (*User, error) { now := time.Now() var u User err := db.QueryRow( `INSERT INTO users (username, password_hash, is_admin, created_at, updated_at) VALUES ($1, $2, $3, $4, $4) ON CONFLICT (username) DO UPDATE SET updated_at = $4 RETURNING id, username, password_hash, is_admin, created_at, updated_at`, username, passwordHash, isAdmin, now, ).Scan(&u.ID, &u.Username, &u.PasswordHash, &u.IsAdmin, &u.CreatedAt, &u.UpdatedAt) if err != nil { return nil, fmt.Errorf("创建用户失败: %w", err) } return &u, nil }