* fix:修复权限问题 * fix:修复项目key类型错误问题 * fix:修复rbac权限问题 * fix:修复api密钥未及时失效的问题 * improve:优化渠道调度稳定性 * improve:优化路由 * fix:修复项目预算控制缺陷 * fix:加强限流等安全措施 * feat:添加限流相关字段的前端展示及接口字段 * improve:优化注册时密码要求,只需要字母和数字即可 * feat(setting):添加注册限流设置 * improve:优化前端数字类型转换 * chore:rbac权限放行 --------- Co-authored-by: chengqian <wuchengqian@kkidc.com> Co-authored-by: qian <wuchengqian5@163.com>
105 lines
3.0 KiB
Go
105 lines
3.0 KiB
Go
package cmd
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
|
||
"github.com/gogf/gf/v2/frame/g"
|
||
"github.com/gogf/gf/v2/os/gcmd"
|
||
|
||
"github.com/qianfree/team-api/internal/dao"
|
||
"github.com/qianfree/team-api/internal/logic/common"
|
||
do "github.com/qianfree/team-api/internal/model/do"
|
||
"github.com/qianfree/team-api/internal/utility/crypto"
|
||
)
|
||
|
||
var resetPwdCmd = gcmd.Command{
|
||
Name: "reset-pwd",
|
||
Usage: "reset-pwd -u <username> -p <password>",
|
||
Brief: "重置管理员账号密码",
|
||
Func: func(ctx context.Context, parser *gcmd.Parser) error {
|
||
username := parser.GetOpt("u", "admin").String()
|
||
password := parser.GetOpt("p").String()
|
||
|
||
if password == "" {
|
||
fmt.Println("用法: team-api reset-pwd -u <用户名> -p <新密码>")
|
||
fmt.Println(" -u 管理员用户名(默认 admin)")
|
||
fmt.Println(" -p 新密码(必填,至少8位,需含字母和数字)")
|
||
return nil
|
||
}
|
||
|
||
// Validate password policy
|
||
if err := common.ValidatePassword(password); err != nil {
|
||
fmt.Println(err.Error())
|
||
return nil
|
||
}
|
||
|
||
// Hash password using the same crypto.HashPassword used by Login/InitSuperAdmin
|
||
passwordHash, err := crypto.HashPassword(password)
|
||
if err != nil {
|
||
return fmt.Errorf("密码加密失败: %w", err)
|
||
}
|
||
|
||
// Check user exists, get id and status
|
||
var user struct {
|
||
Id int64 `orm:"id"`
|
||
Status string `orm:"status"`
|
||
}
|
||
err = dao.SysAdminUsers.Ctx(ctx).
|
||
Where("username", username).
|
||
Fields("id,status").
|
||
Scan(&user)
|
||
if err != nil {
|
||
return fmt.Errorf("查询用户失败: %w", err)
|
||
}
|
||
if user.Id == 0 {
|
||
fmt.Printf("用户 '%s' 不存在\n", username)
|
||
return nil
|
||
}
|
||
|
||
// Update password and reactivate account in case it was disabled
|
||
_, err = dao.SysAdminUsers.Ctx(ctx).
|
||
Where("id", user.Id).
|
||
Data(do.SysAdminUsers{
|
||
PasswordHash: passwordHash,
|
||
Status: "active",
|
||
}).
|
||
Update()
|
||
if err != nil {
|
||
return fmt.Errorf("更新密码失败: %w", err)
|
||
}
|
||
|
||
// 回读数据库验证哈希是否正确落盘(诊断 ORM 写入问题)
|
||
storedHash, err := dao.SysAdminUsers.Ctx(ctx).
|
||
Where("id", user.Id).
|
||
Fields("password_hash").
|
||
Value()
|
||
if err != nil {
|
||
return fmt.Errorf("回读密码哈希失败: %w", err)
|
||
}
|
||
storedHashStr := storedHash.String()
|
||
if !crypto.VerifyPassword(password, storedHashStr) {
|
||
return fmt.Errorf("密码已写入但回读校验失败,哈希长度=%d,预期=60(bcrypt)。请检查数据库连接与 password_hash 字段是否被截断",
|
||
len(storedHashStr))
|
||
}
|
||
|
||
// 清理该用户的所有会话(避免老会话残留导致登录状态异常)
|
||
_, _ = g.DB().Model("sys_sessions").Ctx(ctx).
|
||
Where("user_type", "admin").
|
||
Where("user_id", user.Id).
|
||
Delete()
|
||
|
||
fmt.Printf("已重置用户 '%s' 的密码,回读校验通过,旧会话已清理\n", username)
|
||
fmt.Printf(" - 用户ID: %d\n", user.Id)
|
||
fmt.Printf(" - 原状态: %s → active\n", user.Status)
|
||
return nil
|
||
},
|
||
}
|
||
|
||
func init() {
|
||
err := Main.AddCommand(&resetPwdCmd)
|
||
if err != nil {
|
||
panic(fmt.Sprintf("注册 reset-pwd 命令失败: %v", err))
|
||
}
|
||
}
|