Files
mce/internal/router/admin.go
Victor_Jay 2449a27eb5
Some checks failed
CI / Lint + Build (push) Has been cancelled
refactor: CSP nonce替代unsafe-inline, HSTS始终启用, router/api拆分, 管理后台+用户设置页拆分, DB健康降级, 时区配置, UID统一解析, CI接入
审计修复:
- CSP: unsafe-inline移除, nonce替代; unsafe-eval保留供Vditor使用
- HSTS: 始终启用(不再依赖release模式)
- Controller Exp: common.GetGinExp包装, 不再直接读context
- UID解析: common.ParseUIDParam统一, follow/admin controller改用

重构:
- router/api.go(198行)拆为7个域文件: auth/settings/posts/comments/reactions/social/studio
- 管理后台站点设置: 单页拆为4个子页(brand/security/registration/content)+子菜单
- 前台用户设置页: 1201行拆为6个独立模板+6个独立JS文件

新增:
- DB健康检测中间件(middleware/db_health.go): 5s ping+降级页面
- 时区配置: config.yaml server.timezone→time.Local初始化
- .gitea/workflows/ci.yml: strict模式CI流水线
2026-06-22 03:06:24 +08:00

141 lines
5.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package router
import (
"metazone.cc/mce/internal/config"
"metazone.cc/mce/internal/middleware"
"metazone.cc/mce/internal/model"
"github.com/gin-gonic/gin"
)
// setupAdminRoutes 注册管理后台页面和 API 路由
func setupAdminRoutes(r *gin.Engine, cfg *config.Config, d *dependencies) {
// --- 管理后台 SSR 页面 ---
adminPages := r.Group("/admin")
adminPages.Use(d.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("/", d.adminCtrl.Dashboard)
adminPages.GET("/users", d.adminCtrl.UsersPage,
middleware.RequirePageRole(model.RoleAdmin))
adminPages.GET("/audits", d.auditCtrl.AuditPage,
middleware.RequirePageRole(model.RoleAdmin))
adminPages.GET("/posts", d.adminPostCtrl.PostsPage)
adminPages.GET("/site-settings", d.siteSettingCtrl.SiteSettingsPage,
middleware.RequirePageRole(model.RoleOwner))
adminPages.GET("/settings/brand", d.siteSettingCtrl.BrandPage,
middleware.RequirePageRole(model.RoleOwner))
adminPages.GET("/settings/security", d.siteSettingCtrl.SecurityPage,
middleware.RequirePageRole(model.RoleOwner))
adminPages.GET("/settings/registration", d.siteSettingCtrl.RegistrationPage,
middleware.RequirePageRole(model.RoleOwner))
adminPages.GET("/settings/content", d.siteSettingCtrl.ContentPage,
middleware.RequirePageRole(model.RoleOwner))
adminPages.GET("/energy", d.adminEnergyCtrl.EnergyPage)
adminPages.GET("/energy/logs", d.adminEnergyCtrl.EnergyLogPage)
adminPages.GET("/energy/fund-logs", d.adminEnergyCtrl.FundLogPage)
adminPages.GET("/comments", d.adminCommentCtrl.CommentsPage)
adminPages.GET("/announcements", d.announcementCtrl.Page)
adminPages.GET("/categories", d.categoryCtrl.Page)
}
// --- 管理后台 API ---
adminAPI := r.Group("/api/admin")
adminAPI.Use(d.authMdw.Required())
adminAPI.Use(middleware.RequireMinRole(model.RoleAdmin))
adminAPI.Use(d.authMdw.BannedWriteGuard())
adminAPI.Use(middleware.CSRF(cfg))
{
adminAPI.GET("/users", d.adminCtrl.ListUsers)
adminAPI.PUT("/users/:uid/status", d.adminCtrl.UpdateUserStatus)
adminAPI.POST("/users/:uid/reset-token", d.adminCtrl.ResetToken)
adminAPI.GET("/audits", d.auditCtrl.ListAudits)
adminAPI.POST("/audits/:id/approve", d.auditCtrl.Approve)
adminAPI.POST("/audits/:id/reject", d.auditCtrl.Reject)
}
// --- 站点设置 API仅 owner ---
siteSettingsAPI := r.Group("/api/admin/site-settings")
siteSettingsAPI.Use(d.authMdw.Required())
siteSettingsAPI.Use(middleware.RequireMinRole(model.RoleOwner))
siteSettingsAPI.Use(d.authMdw.BannedWriteGuard())
siteSettingsAPI.Use(middleware.CSRF(cfg))
{
siteSettingsAPI.GET("", d.siteSettingCtrl.GetSettings)
siteSettingsAPI.PUT("", d.siteSettingCtrl.UpdateSetting)
siteSettingsAPI.PUT("/bool", d.siteSettingCtrl.UpdateBoolSetting)
siteSettingsAPI.GET("/bool", d.siteSettingCtrl.GetBoolSetting)
}
// --- 帖子管理 APIadmin+ ---
adminPostAPI := r.Group("/api/admin/posts")
adminPostAPI.Use(d.authMdw.Required())
adminPostAPI.Use(middleware.RequireMinRole(model.RoleAdmin))
adminPostAPI.Use(d.authMdw.BannedWriteGuard())
adminPostAPI.Use(middleware.CSRF(cfg))
{
adminPostAPI.POST("/:id/approve", d.adminPostCtrl.Approve)
adminPostAPI.POST("/:id/reject", d.adminPostCtrl.Reject)
adminPostAPI.POST("/:id/lock", d.adminPostCtrl.Lock)
adminPostAPI.POST("/:id/unlock", d.adminPostCtrl.Unlock)
adminPostAPI.POST("/:id/pin", d.adminPostCtrl.Pin)
adminPostAPI.POST("/:id/unpin", d.adminPostCtrl.Unpin)
adminPostAPI.POST("/:id/restore", d.adminPostCtrl.Restore)
}
// --- 域能管理 APIadmin+system_operation 仅 owner ---
adminEnergyAPI := r.Group("/api/admin/energy")
adminEnergyAPI.Use(d.authMdw.Required())
adminEnergyAPI.Use(middleware.RequireMinRole(model.RoleAdmin))
adminEnergyAPI.Use(d.authMdw.BannedWriteGuard())
adminEnergyAPI.Use(middleware.CSRF(cfg))
{
adminEnergyAPI.POST("/adjust", d.adminEnergyCtrl.AdjustEnergy)
adminEnergyAPI.GET("/logs", d.adminEnergyCtrl.ListEnergyLogs)
adminEnergyAPI.GET("/fund-balance", d.adminEnergyCtrl.GetFundBalance)
adminEnergyAPI.GET("/fund-logs", d.adminEnergyCtrl.ListFundLogs)
}
// --- 评论管理 APIadmin+ ---
adminCommentAPI := r.Group("/api/admin/comments")
adminCommentAPI.Use(d.authMdw.Required())
adminCommentAPI.Use(middleware.RequireMinRole(model.RoleAdmin))
adminCommentAPI.Use(d.authMdw.BannedWriteGuard())
adminCommentAPI.Use(middleware.CSRF(cfg))
{
adminCommentAPI.GET("", d.adminCommentCtrl.ListComments)
adminCommentAPI.DELETE("/:id", d.adminCommentCtrl.Delete)
}
// --- 公告管理 APImoderator+ ---
announcementAPI := r.Group("/api/admin/announcements")
announcementAPI.Use(d.authMdw.Required())
announcementAPI.Use(middleware.RequireMinRole(model.RoleModerator))
announcementAPI.Use(d.authMdw.BannedWriteGuard())
announcementAPI.Use(middleware.CSRF(cfg))
{
announcementAPI.GET("", d.announcementCtrl.List)
announcementAPI.POST("", d.announcementCtrl.Create)
announcementAPI.PUT("/:id", d.announcementCtrl.Update)
announcementAPI.DELETE("/:id", d.announcementCtrl.Delete)
}
// --- 分类管理 APImoderator+ ---
categoryAPI := r.Group("/api/admin/categories")
categoryAPI.Use(d.authMdw.Required())
categoryAPI.Use(middleware.RequireMinRole(model.RoleModerator))
categoryAPI.Use(d.authMdw.BannedWriteGuard())
categoryAPI.Use(middleware.CSRF(cfg))
{
categoryAPI.GET("", d.categoryCtrl.List)
categoryAPI.POST("", d.categoryCtrl.Create)
categoryAPI.PUT("/:id", d.categoryCtrl.Update)
categoryAPI.DELETE("/:id", d.categoryCtrl.Delete)
}
}