forked from alterminal/alterminal
65 lines
1.7 KiB
Go
65 lines
1.7 KiB
Go
package cli
|
|
|
|
import (
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"gorm.io/gorm"
|
|
|
|
"alterminal/internal/auth"
|
|
"alterminal/internal/store"
|
|
)
|
|
|
|
// runUpdatePassword 解析旗標並重設指定帳號的密碼。此為管理用指令,
|
|
// 不需驗證舊密碼;密碼更新成功後一併撤銷該使用者所有 Session,
|
|
// 避免既有登入在密碼重設後續存。
|
|
func runUpdatePassword(args []string) error {
|
|
fs := flag.NewFlagSet("update-password", flag.ExitOnError)
|
|
username := fs.String("username", "", "登入帳號(必填)")
|
|
password := fs.String("password", "", "新密碼(選填;省略時於終端機輸入)")
|
|
fs.Parse(args)
|
|
|
|
name := strings.TrimSpace(*username)
|
|
if name == "" {
|
|
return errors.New("username 不可為空")
|
|
}
|
|
pw, err := resolvePassword(*password)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
db, err := store.Open()
|
|
if err != nil {
|
|
return fmt.Errorf("database: %w", err)
|
|
}
|
|
|
|
u, err := findUserByUsername(db, name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := u.SetPassword(pw); err != nil {
|
|
return fmt.Errorf("hash password: %w", err)
|
|
}
|
|
revoked, err := auth.UpdateUserPassword(db, u)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fmt.Printf("密碼更新成功:id=%d username=%s(已撤銷 %d 個 Session)\n", u.ID, u.Username, revoked)
|
|
return nil
|
|
}
|
|
|
|
// findUserByUsername 以帳號查詢使用者,查無時回傳可讀的錯誤。
|
|
func findUserByUsername(db *gorm.DB, username string) (*auth.User, error) {
|
|
var u auth.User
|
|
err := db.Where("username = ?", username).First(&u).Error
|
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
return nil, fmt.Errorf("username %q 不存在", username)
|
|
}
|
|
if err != nil {
|
|
return nil, fmt.Errorf("query user: %w", err)
|
|
}
|
|
return &u, nil
|
|
}
|