feat(server): 新增修改密码接口 POST /api/auth/password(验原密码、作废会话)
This commit is contained in:
1 parent
ad2322d558
commit
4cbf5a74f0
13 files changed
+528
-20
No files matched your search
@@ -63,6 +63,43 @@ func (s *server) me(w http.ResponseWriter, r *http.Request) (any, error) {
|
||||
return userDTO(u), nil
|
||||
}
|
||||
|
||||
type changePasswordInput struct {
|
||||
CurrentPassword string `json:"currentPassword"`
|
||||
NewPassword string `json:"newPassword"`
|
||||
}
|
||||
|
||||
// changePassword 修改当前登录用户的密码:先验原密码,再改密并作废全部会话。
|
||||
func (s *server) changePassword(w http.ResponseWriter, r *http.Request) (any, error) {
|
||||
u := middleware.User(r.Context())
|
||||
if u.Role == auth.RoleGuest {
|
||||
return nil, &apiError{status: http.StatusUnauthorized, code: "AUTH_REQUIRED", message: "请先登录"}
|
||||
}
|
||||
|
||||
var in changePasswordInput
|
||||
if err := decodeJSON(r, &in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(in.NewPassword) < 8 {
|
||||
return nil, badRequest("新密码至少 8 位", nil)
|
||||
}
|
||||
if in.NewPassword == in.CurrentPassword {
|
||||
return nil, badRequest("新密码不能与原密码相同", nil)
|
||||
}
|
||||
// 会话被盗后不能直接改密,必须再验一次原密码
|
||||
if err := s.auth.VerifyPassword(r.Context(), u.ID, in.CurrentPassword); err != nil {
|
||||
return nil, &apiError{status: http.StatusUnauthorized, code: "AUTH_FAILED", message: "原密码不正确"}
|
||||
}
|
||||
if err := s.auth.SetPassword(r.Context(), u.Username, in.NewPassword, false); err != nil {
|
||||
return nil, internal(err)
|
||||
}
|
||||
|
||||
// SetPassword 已作废全部会话,这里清掉 Cookie 让前端引导重新登录
|
||||
s.auth.ClearSessionCookie(w)
|
||||
s.auth.ClearCSRFCookie(w)
|
||||
s.audit(r.Context(), "auth.change_password", "user", u.ID, nil, map[string]any{"username": u.Username})
|
||||
return map[string]any{"relogin": true}, nil
|
||||
}
|
||||
|
||||
func userDTO(u *auth.User) currentUserDTO {
|
||||
dto := currentUserDTO{
|
||||
ID: u.ID,
|
||||
|
||||
@@ -139,6 +139,7 @@ func (s *server) routes(mux *http.ServeMux) {
|
||||
mux.HandleFunc("POST /api/auth/login", s.handle(s.login))
|
||||
mux.HandleFunc("POST /api/auth/logout", s.handle(s.logout))
|
||||
mux.HandleFunc("GET /api/auth/me", s.handle(s.me))
|
||||
mux.HandleFunc("POST /api/auth/password", s.handle(s.changePassword))
|
||||
|
||||
// 系统配置(guest 一律 403)
|
||||
mux.HandleFunc("GET /api/settings", s.read(auth.RoleAdmin, s.getSettingsHandler))
|
||||
|
||||
Reference in new issue
Block a user