完善站点运营设置:分路由管理、登录可见评论、邮件模板内联与关闭注册 SSR。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-23 00:17:00 +08:00
parent acde7ee288
commit 6f054a903c
98 changed files with 8239 additions and 2073 deletions

View File

@@ -85,6 +85,7 @@ func clearAuthCookies(c *gin.Context, secure bool) {
// RegisterRequest 注册请求
type RegisterRequest struct {
Code string `json:"code"`
Username string `json:"username" binding:"required,min=3,max=32"`
Email string `json:"email" binding:"omitempty,email"`
Password string `json:"password" binding:"required,min=6,max=64"`
@@ -92,8 +93,8 @@ type RegisterRequest struct {
// LoginRequest 登录请求
type LoginRequest struct {
Username string `json:"username" binding:"required"`
Password string `json:"password" binding:"required"`
Username string `json:"username" binding:"required,max=128"`
Password string `json:"password" binding:"required,max=128"`
}
// Register 用户注册:成功后直接签发登录态(注册即登录,免去手动再登一次)
@@ -110,6 +111,17 @@ func (h *Handlers) Register(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
security, err := h.Ops.Security()
if err != nil {
c.JSON(503, gin.H{"error": "注册暂不可用"})
return
}
if security.VerifyEmail {
if err = h.Ops.ConsumeCode(req.Email, "register", req.Code); err != nil {
c.JSON(400, gin.H{"error": "请先完成邮箱验证"})
return
}
}
user, err := h.Auth.Register(req.Username, req.Email, req.Password)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
@@ -146,8 +158,17 @@ func (h *Handlers) Login(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
cfg, e := h.Ops.Security()
if !h.quotaResponse(c, 0, e) {
return
}
wait, e := h.Ops.FailureWait(req.Username, c.ClientIP(), cfg)
if !h.quotaResponse(c, wait, e) {
return
}
accessToken, refreshToken, user, err := h.Auth.Login(req.Username, req.Password, c.ClientIP(), c.Request.UserAgent())
if err != nil {
h.Ops.RecordFailure(req.Username, c.ClientIP(), cfg)
// 登录失败也留痕:用户存在时带 user_id(封禁/错密),不存在时为 0
h.AdminUser.RecordLogin(
h.Auth.GetUserIDByUsername(req.Username), req.Username,
@@ -164,6 +185,7 @@ func (h *Handlers) Login(c *gin.Context) {
// 登录成功留痕(IP/UA/时间)
h.AdminUser.RecordLogin(user.ID, req.Username, c.ClientIP(), c.Request.UserAgent(), true)
// dev 模式不设 Secure,生产环境需 HTTPS
h.Ops.ClearFailure(req.Username)
setAuthCookies(c, accessToken, refreshToken, !h.Cfg.DevMode)
c.JSON(http.StatusOK, gin.H{
"user": gin.H{