refactor: 拆分 middleware/router 为单一职责文件,新增站点设置管理页面

middleware:
- 拆分 auth.go → auth.go + auth_token.go + auth_parser.go + auth_admin.go
- 拆分 csrf.go → csrf.go + csrf_token.go
- 拆分 ratelimit.go → ratelimit.go + ratelimit_core.go + ratelimit_cleanup.go
- 修复 import 未使用/缺失问题

router:
- 拆分 router.go → admin.go + api.go + frontend.go + deps_core.go + deps_extra.go

feat(admin): 站点设置管理页面
- 新增 SSR 页面 /admin/site-settings(仅 Owner)
- 审核开关 Toggle 即时保存
- 通用设置展示
- 侧边栏新增站点设置入口
- 注册 UpdateBoolSetting/GetBoolSetting API 路由
This commit is contained in:
2026-05-27 15:03:04 +08:00
parent a19b1fcb51
commit 7bc2dbd970
20 changed files with 774 additions and 446 deletions

View File

@ -1,16 +1,8 @@
package router
import (
"net/http"
"metazone.cc/metalab/internal/common"
"metazone.cc/metalab/internal/config"
"metazone.cc/metalab/internal/controller"
adminCtrl "metazone.cc/metalab/internal/controller/admin"
"metazone.cc/metalab/internal/middleware"
"metazone.cc/metalab/internal/model"
"metazone.cc/metalab/internal/repository"
"metazone.cc/metalab/internal/service"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
@ -18,159 +10,11 @@ import (
// Setup 注册所有路由
func Setup(r *gin.Engine, db *gorm.DB, cfg *config.Config, siteSettings *config.SiteSettings) {
// --- 全局中间件 ---
r.Use(middleware.SecurityHeaders())
// --- 依赖注入 ---
userRepo := repository.NewUserRepo(db)
tokenSvc := service.NewTokenService(cfg, userRepo)
authService := service.NewAuthService(userRepo, tokenSvc, cfg)
rateLimiter := middleware.NewRateLimiter()
authCtrl := controller.NewAuthController(authService, tokenSvc, rateLimiter, cfg)
avatarSvc := service.NewAvatarService(userRepo)
authMdw := middleware.NewAuthMiddleware(cfg, userRepo)
deps := buildDeps(db, cfg, siteSettings)
// 管理后台
adminService := service.NewAdminService(userRepo)
adminController := adminCtrl.NewAdminController(adminService)
// 审核系统
auditRepo := repository.NewAuditRepo(db)
notificationRepo := repository.NewNotificationRepo(db)
notificationService := service.NewNotificationService(notificationRepo)
auditService := service.NewAuditService(auditRepo, userRepo, siteSettings, cfg.Audit, notificationService)
auditController := adminCtrl.NewAuditController(auditService, userRepo)
// 消息中心
messageController := controller.NewMessageController(notificationService)
// 站点设置
siteSettingService := service.NewSiteSettingService(siteSettings)
auditDefaults := &service.AuditDefaults{
Enabled: cfg.Audit.Enabled,
UsernameAudit: cfg.Audit.UsernameAudit,
AvatarAudit: cfg.Audit.AvatarAudit,
BioAudit: cfg.Audit.BioAudit,
}
siteSettingController := adminCtrl.NewSiteSettingController(siteSettingService, auditDefaults)
// 个人设置(需要审核服务)
settingsCtrl := controller.NewSettingsController(authService, avatarSvc, auditService)
// --- 页面路由CSRF 仅下发 token不验证——页面 GET 被豁免) ---
pages := r.Group("/")
pages.Use(authMdw.Optional())
pages.Use(middleware.CSRF(cfg))
pages.Use(func(c *gin.Context) {
// 页面路由:确保每个页面都下发 CSRF Cookie
middleware.SetCSRFToken(c, cfg)
c.Next()
})
{
pages.GET("/", func(c *gin.Context) {
c.HTML(http.StatusOK, "home/index.html", common.BuildPageData(c, gin.H{
"Title": "首页",
"ExtraCSS": "/static/css/home.css",
}))
})
// 个人设置页(需登录,/:tab 为伪静态子页面)
pages.GET("/settings", func(c *gin.Context) {
c.Redirect(http.StatusFound, "/settings/profile")
})
pages.GET("/settings/:tab", settingsCtrl.SettingsPage)
// 消息中心需登录noindex
pages.GET("/messages", messageController.MessagesPage)
}
// 认证页面(已登录自动跳走)
authPages := r.Group("/auth")
authPages.Use(authMdw.Optional())
authPages.Use(middleware.CSRF(cfg))
authPages.Use(func(c *gin.Context) {
middleware.SetCSRFToken(c, cfg)
c.Next()
})
{
authPages.GET("/register", authCtrl.RegisterPage)
authPages.GET("/login", authCtrl.LoginPage)
}
// --- 设置页 API需登录 ---
settingsAPI := r.Group("/api/settings")
settingsAPI.Use(authMdw.Required())
settingsAPI.Use(middleware.CSRF(cfg))
{
settingsAPI.PUT("/profile", settingsCtrl.UpdateProfile)
settingsAPI.POST("/avatar", settingsCtrl.UploadAvatar)
settingsAPI.PUT("/password", settingsCtrl.ChangePassword)
settingsAPI.POST("/delete-account", settingsCtrl.DeleteAccount)
// 查询当前用户的待审核状态
settingsAPI.GET("/audit-status", settingsCtrl.AuditStatus)
}
// --- 消息中心 API需登录 ---
messagesAPI := r.Group("/api/messages")
messagesAPI.Use(authMdw.Required())
messagesAPI.Use(middleware.CSRF(cfg))
{
messagesAPI.GET("/unread", messageController.UnreadCount)
messagesAPI.POST("/:id/read", messageController.MarkRead)
messagesAPI.POST("/read-all", messageController.MarkAllRead)
}
// --- 管理后台 SSR 页面(认证失败 302 跳首页) ---
adminPages := r.Group("/admin")
adminPages.Use(authMdw.AdminAuth())
adminPages.Use(middleware.RequirePageRole(model.RoleModerator))
adminPages.Use(middleware.CSRF(cfg))
adminPages.Use(func(c *gin.Context) {
middleware.SetCSRFToken(c, cfg)
c.Next()
})
{
adminPages.GET("/", adminController.Dashboard)
adminPages.GET("/users", adminController.UsersPage,
middleware.RequirePageRole(model.RoleAdmin))
adminPages.GET("/audits", auditController.AuditPage,
middleware.RequirePageRole(model.RoleAdmin))
}
// --- 管理后台 APIJSON 响应) ---
adminAPI := r.Group("/api/admin")
adminAPI.Use(authMdw.Required())
adminAPI.Use(middleware.RequireMinRole(model.RoleAdmin))
adminAPI.Use(middleware.CSRF(cfg))
{
adminAPI.GET("/users", adminController.ListUsers)
adminAPI.PUT("/users/:uid/status", adminController.UpdateUserStatus)
adminAPI.POST("/users/:uid/reset-token", adminController.ResetToken)
// 审核 API
adminAPI.GET("/audits", auditController.ListAudits)
adminAPI.POST("/audits/:id/approve", auditController.Approve)
adminAPI.POST("/audits/:id/reject", auditController.Reject)
}
// --- 站点设置 API仅 owner 可访问) ---
siteSettingsAPI := r.Group("/api/admin/site-settings")
siteSettingsAPI.Use(authMdw.Required())
siteSettingsAPI.Use(middleware.RequireMinRole(model.RoleOwner))
siteSettingsAPI.Use(middleware.CSRF(cfg))
{
siteSettingsAPI.GET("", siteSettingController.GetSettings)
siteSettingsAPI.PUT("", siteSettingController.UpdateSetting)
}
// --- API 路由CSRF 严格验证) ---
api := r.Group("/api")
api.Use(middleware.CSRF(cfg))
{
api.POST("/auth/check-email", authCtrl.CheckEmail)
api.POST("/auth/register", authCtrl.Register)
api.POST("/auth/login", authCtrl.Login)
api.POST("/auth/confirm-restore", authCtrl.ConfirmRestore)
api.POST("/auth/logout", authCtrl.Logout)
api.POST("/auth/refresh", authCtrl.RefreshToken)
}
setupFrontendRoutes(r, cfg, deps)
setupAPIRoutes(r, cfg, deps)
setupAdminRoutes(r, cfg, deps)
}