fix login error
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
// Copyright 2026 tamakyi. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
|
||||
"github.com/tamakyi/TamaBox/internal/conf"
|
||||
"github.com/tamakyi/TamaBox/internal/db"
|
||||
)
|
||||
|
||||
// Restore 恢复被自助停用的账号。
|
||||
//
|
||||
// 自助停用(Deactivate)只清空内容、保留用户行作「身份占位」(软删除),
|
||||
// 因此恢复只需清掉 deleted_at;内容已不可找回。
|
||||
//
|
||||
// 用法:TamaBox restore --email [email protected]
|
||||
//
|
||||
// TamaBox restore --domain someone --password 'new-password'
|
||||
var Restore = &cli.Command{
|
||||
Name: "restore",
|
||||
Usage: "Restore a deactivated account (clears the identity placeholder)",
|
||||
Action: runRestore,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "email",
|
||||
Usage: "Email of the deactivated account",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "domain",
|
||||
Usage: "Custom domain of the deactivated account",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "password",
|
||||
Usage: "Optional: reset the password to this value (min 8 chars)",
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "yes",
|
||||
Usage: "Skip confirmation",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func runRestore(ctx *cli.Context) error {
|
||||
if err := conf.Init(); err != nil {
|
||||
return errors.Wrap(err, "load configuration")
|
||||
}
|
||||
|
||||
dbType := conf.Database.Type
|
||||
if dbType == "postgres" {
|
||||
conf.Database.DSN = conf.PostgresDsn()
|
||||
} else {
|
||||
conf.Database.DSN = conf.MySQLDsn()
|
||||
}
|
||||
|
||||
database, err := db.Init(dbType, conf.Database.DSN)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "connect to database")
|
||||
}
|
||||
|
||||
email := ctx.String("email")
|
||||
domain := ctx.String("domain")
|
||||
if email == "" && domain == "" {
|
||||
return errors.New("must provide --email or --domain")
|
||||
}
|
||||
newPassword := ctx.String("password")
|
||||
if newPassword != "" && len(newPassword) < 8 {
|
||||
return errors.New("password must be at least 8 characters")
|
||||
}
|
||||
|
||||
// 用 Unscoped 查找:待恢复的账号必然是软删除状态,普通查询看不见
|
||||
var user db.User
|
||||
query := database.WithContext(ctx.Context).Unscoped()
|
||||
if email != "" {
|
||||
query = query.Where("email = ?", email)
|
||||
} else {
|
||||
query = query.Where("domain = ?", domain)
|
||||
}
|
||||
if err := query.First(&user).Error; err != nil {
|
||||
return errors.Wrap(err, "find user to restore")
|
||||
}
|
||||
if !user.DeletedAt.Valid {
|
||||
return errors.Errorf("账号 %q 未被停用,无需恢复", user.Domain)
|
||||
}
|
||||
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"id": user.ID,
|
||||
"name": user.Name,
|
||||
"email": user.Email,
|
||||
"domain": user.Domain,
|
||||
}).Warn("准备恢复以下已停用账号(提问/追问/私聊等内容在停用时已被删除,无法找回)")
|
||||
|
||||
if !ctx.Bool("yes") {
|
||||
logrus.Warn("输入大写 YES 确认执行恢复:")
|
||||
var answer string
|
||||
if _, err := fmtScan(&answer); err != nil {
|
||||
return errors.Wrap(err, "read confirmation")
|
||||
}
|
||||
if answer != "YES" {
|
||||
return errors.New("已取消")
|
||||
}
|
||||
}
|
||||
|
||||
if err := db.Users.Reactivate(ctx.Context, user.ID); err != nil {
|
||||
return errors.Wrap(err, "reactivate user")
|
||||
}
|
||||
|
||||
// 密码重置必须在恢复之后:UpdatePassword 走普通作用域,软删除状态下找不到该用户
|
||||
if newPassword != "" {
|
||||
if err := db.Users.UpdatePassword(ctx.Context, user.ID, newPassword); err != nil {
|
||||
return errors.Wrap(err, "reset password")
|
||||
}
|
||||
logrus.WithField("user_id", user.ID).Info("账号已恢复,密码已重置")
|
||||
return nil
|
||||
}
|
||||
|
||||
logrus.WithField("user_id", user.ID).Info("账号已恢复(密码未改动,如原主已忘记密码请用 --password 重置)")
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user