Files
nl-pms-api/internal/router/router.go
2026-08-15 17:04:47 +08:00

138 lines
5.2 KiB
Go
Raw Permalink 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 (
"net/http"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"nl-pms-api/internal/config"
"nl-pms-api/internal/controller"
"nl-pms-api/internal/middleware"
"nl-pms-api/internal/service"
)
// New 组装路由:公开 healthz/authJWT 保护同步/设置/资料/团队/文件/后台。
// 若配置了 base_path如 /pms-api全部路由挂在该前缀下适配不剥路径的反代。
func New(cfg *config.Config, db *gorm.DB) *gin.Engine {
if cfg.Env != "dev" {
gin.SetMode(gin.ReleaseMode)
}
r := gin.New()
r.Use(gin.Logger(), gin.Recovery(), middleware.AttachClientIP())
r.MaxMultipartMemory = 32 << 20
if len(cfg.TrustedProxies) > 0 {
_ = r.SetTrustedProxies(cfg.TrustedProxies)
} else {
// 空切片=不信任任何反代ClientIP 用 RemoteAddr避免默认信任全部
_ = r.SetTrustedProxies([]string{})
}
root := r.Group(cfg.BasePath)
root.GET("/healthz", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"ok": true, "service": "nl-pms-api"})
})
authSvc := &service.AuthService{DB: db, Cfg: cfg}
authC := &controller.AuthController{Svc: authSvc}
syncC := &controller.SyncController{Svc: &service.SyncService{DB: db}}
settingsC := &controller.SettingsController{Svc: &service.SettingsService{DB: db}}
profileC := &controller.ProfileController{
Svc: &service.ProfileService{DB: db},
AvatarHist: &service.AvatarHistoryService{DB: db},
}
noticeC := &controller.NoticeController{Svc: &service.NoticeService{DB: db}}
fileC := &controller.FileController{Svc: &service.FileService{DB: db, Cfg: cfg}}
teamC := &controller.TeamController{Svc: &service.TeamService{DB: db}}
adminSvc := &service.AdminService{DB: db}
secSvc := &service.AdminSecurityService{DB: db}
relSvc := &service.ReleaseService{DB: db, Cfg: cfg}
actSvc := &service.ActivityService{DB: db}
adminC := &controller.AdminController{Admin: adminSvc, Sec: secSvc, Rel: relSvc, Act: actSvc}
actC := &controller.ActivityController{Svc: actSvc}
aiC := &controller.AIController{Admin: adminSvc}
appC := &controller.AppController{Rel: relSvc}
pub := root.Group("/api/v1")
pub.POST("/auth/register", authC.Register)
pub.POST("/auth/login", authC.Login)
pub.POST("/auth/refresh", authC.Refresh)
api := root.Group("/api/v1", middleware.RequireJWT(cfg.JWTSecret), middleware.RejectDisabled(db))
api.POST("/auth/change-password", authC.ChangePassword)
api.POST("/sync/push", syncC.Push)
api.GET("/sync/pull", syncC.Pull)
api.GET("/settings", settingsC.Get) // ?prefix=fest_img:
api.GET("/settings/global/:name", settingsC.GetGlobal)
api.GET("/settings/:name", settingsC.Get)
api.PUT("/settings/:name", middleware.RequireStepUpForGlobalSetting(db), settingsC.Put)
api.GET("/profile", profileC.Get)
api.PUT("/profile", profileC.Put)
api.GET("/profile/avatars", profileC.ListAvatars)
api.POST("/profile/avatars", profileC.PushAvatar)
api.DELETE("/profile/avatars/:id", profileC.DeleteAvatar)
api.GET("/notices", noticeC.List)
api.POST("/teams", teamC.Create)
api.GET("/teams", teamC.List)
api.PUT("/teams/:id", teamC.Rename)
api.PUT("/teams/:id/digest-time", teamC.SetDigestTime)
api.DELETE("/teams/:id", teamC.Dissolve)
api.POST("/teams/:id/leave", teamC.Leave)
api.GET("/teams/:id/members", teamC.Members)
api.POST("/teams/:id/invite", teamC.Invite)
api.PUT("/teams/:id/members/:userId/role", teamC.SetRole)
api.DELETE("/teams/:id/members/:userId", teamC.RemoveMember)
api.POST("/teams/:id/tasks", teamC.TaskSave)
api.PUT("/teams/:id/tasks/:taskId", teamC.TaskSave)
api.PUT("/teams/:id/tasks/:taskId/status", teamC.TaskSetStatus)
api.POST("/teams/:id/tasks/:taskId/urge", teamC.TaskUrge)
api.DELETE("/teams/:id/tasks/:taskId", teamC.TaskDelete)
api.GET("/teams/:id/tasks", teamC.TaskList)
api.GET("/teams/:id/shared", teamC.SharedItems)
api.POST("/teams/:id/shared/urge", teamC.UrgeShared)
api.POST("/teams/:id/reports", teamC.ReportSubmit)
api.GET("/teams/:id/reports/:date", teamC.ReportBoardGet)
api.POST("/teams/:id/reports/urge", teamC.ReportUrge)
api.PUT("/teams/:id/digests/:date", teamC.DigestSave)
api.POST("/files", fileC.Upload)
api.GET("/files", fileC.List)
api.DELETE("/files/:id", fileC.Delete)
api.POST("/activity/ping", actC.Ping)
api.GET("/ai/policy", aiC.Policy)
api.POST("/ai/usage", aiC.Usage)
api.GET("/app/latest", appC.Latest)
api.GET("/app/download/:version", appC.Download)
admin := api.Group("/admin", middleware.RequireAdmin())
admin.GET("/totp/status", adminC.TOTPStatus)
admin.POST("/totp/setup", adminC.TOTPSetupBegin)
admin.POST("/totp/confirm", adminC.TOTPSetupConfirm)
admin.POST("/stepup", adminC.StepUp)
admin.GET("/stats/overview", adminC.Overview)
admin.GET("/users", adminC.ListUsers)
admin.GET("/teams", adminC.ListTeams)
admin.GET("/releases", adminC.ListReleases)
adminWrite := admin.Group("", middleware.RequireAdminStepUp(db))
adminWrite.PATCH("/users/:id", adminC.PatchUser)
adminWrite.PATCH("/teams/:id", adminC.PatchTeam)
adminWrite.POST("/releases", adminC.UploadRelease)
adminWrite.POST("/releases/:id/publish", adminC.PublishRelease)
files := root.Group("/files", func(c *gin.Context) {
c.Header("Cache-Control", "public, max-age=31536000, immutable")
})
files.Static("/", cfg.StorageDir)
return r
}