feat: 支持管理员自助修改密码 (#57)

This commit is contained in:
chengma
2026-08-09 16:49:28 +08:00
parent 2cbb98f09c
commit 008bb87620
12 changed files with 446 additions and 19 deletions
+26 -4
View File
@@ -12,6 +12,7 @@ package web
import (
"database/sql"
"net/http"
"net/url"
"time"
"github.com/gin-gonic/gin"
@@ -44,6 +45,8 @@ func Register(r *gin.Engine, db *sql.DB, onlineThreshold time.Duration) {
// 登录中间件只挂业务网页组,绝不能挂在整个 Engine。
pages := r.Group("/", CSRFMiddleware(), AuthRequired(db))
pages.POST("/logout", h.Logout)
account := pages.Group("/account", AdminRequired())
account.POST("/change-password", h.ChangePassword)
// 打开根路径直接进第一个模块
pages.GET("/", func(c *gin.Context) {
@@ -97,11 +100,16 @@ func Register(r *gin.Engine, db *sql.DB, onlineThreshold time.Duration) {
// page 组装每个页面都要的公共数据(导航高亮、标题、CSRF token)。
func page(c *gin.Context, active, title string, extra gin.H) gin.H {
actor := currentUser(c)
data := gin.H{
"Active": active,
"Title": title,
"CSRFToken": csrfToken(c),
"CurrentUser": currentUser(c),
"Active": active,
"Title": title,
"CSRFToken": csrfToken(c),
"CurrentUser": actor,
"PasswordChangeOpen": actor != nil && actor.IsAdmin() && c.Query("change_password") == "1",
"PasswordChangeError": c.Query("password_error"),
"PasswordChangeField": c.Query("password_field"),
"PasswordReturnPath": passwordReturnPath(c.Request.URL.RequestURI()),
}
for k, v := range extra {
data[k] = v
@@ -109,6 +117,20 @@ func page(c *gin.Context, active, title string, extra gin.H) gin.H {
return data
}
// passwordReturnPath 保留用户所在业务页和原筛选条件,但移除改密弹窗自己的反馈参数。
func passwordReturnPath(raw string) string {
parsed, err := url.Parse(safeNext(raw))
if err != nil {
return "/shopee"
}
query := parsed.Query()
query.Del("change_password")
query.Del("password_error")
query.Del("password_field")
parsed.RawQuery = query.Encode()
return parsed.RequestURI()
}
// fail 渲染一个错误页。
//
// 错误信息要说清三件事:发生了什么、保住了什么、下一步做什么。