13c53fea0a
- 管理员可管理任意用户笔记(读取/修改/删除/回收站/标签/图谱/FTS 全平台) - 普通用户仍数据隔离, 越权返回404 - 新增注册开关: 管理员后台⚙设置可开/关, 支持REGISTRATION_ENABLED环境变量 - 注册关闭时前台/登录页隐藏注册入口, 注册接口返回400 - 冒烟测试扩展到91用例全过
130 lines
4.6 KiB
Go
130 lines
4.6 KiB
Go
package router
|
|
|
|
import (
|
|
"github.com/gin-gonic/gin"
|
|
"note-manager/config"
|
|
"note-manager/handler"
|
|
"note-manager/middleware"
|
|
)
|
|
|
|
// Setup 初始化路由
|
|
func Setup(r *gin.Engine, noteHandler *handler.NoteHandler, authHandler *handler.AuthHandler, adminHandler *handler.AdminHandler, imageHandler *handler.ImageHandler, cfg *config.Config) *gin.Engine {
|
|
// 全局中间件
|
|
r.Use(middleware.CORS())
|
|
r.Use(middleware.CurrentUser()) // 解析当前用户 ID(游客为 0),供公开/混合路由使用
|
|
|
|
// 静态文件服务(图片)
|
|
r.Static("/uploads", cfg.UploadDir)
|
|
|
|
// ─────────── 认证接口(多租户账号)───────────
|
|
auth := r.Group("/api/auth")
|
|
{
|
|
auth.POST("/register", authHandler.Register) // 首个用户自动成为 admin
|
|
auth.POST("/login", authHandler.Login)
|
|
auth.POST("/logout", authHandler.Logout)
|
|
auth.GET("/me", authHandler.Me)
|
|
}
|
|
|
|
// ─────────── 公开 API(登录用户看自己的;游客看公开笔记)───────────
|
|
api := r.Group("/api")
|
|
{
|
|
notes := api.Group("/notes")
|
|
{
|
|
notes.GET("", noteHandler.ListNotes)
|
|
notes.GET("/search", noteHandler.SearchNotes)
|
|
notes.GET("/:id", noteHandler.GetNote) // 公开安全版:游客只看公开无密码;登录用户看自己的
|
|
notes.POST("/:id/access", noteHandler.AccessNote) // 密码验证访问
|
|
}
|
|
|
|
api.GET("/categories", noteHandler.GetCategories)
|
|
api.GET("/tags", noteHandler.GetTags)
|
|
api.GET("/tree", noteHandler.GetPublicTree) // 前台树(登录=自己,游客=公开)
|
|
|
|
// 分享 JSON 接口(公开)
|
|
api.GET("/share/:token", noteHandler.GetSharedNote)
|
|
}
|
|
|
|
// ─────────── 管理(个人工作区)API(需登录)───────────
|
|
adminApi := r.Group("/admin/api")
|
|
adminApi.Use(middleware.AuthRequired())
|
|
{
|
|
// 笔记写操作
|
|
adminApi.POST("/notes", noteHandler.CreateNote)
|
|
adminApi.GET("/notes/:id", noteHandler.GetAdminNote)
|
|
adminApi.PUT("/notes/:id", noteHandler.UpdateNote)
|
|
adminApi.DELETE("/notes/:id", noteHandler.DeleteNote)
|
|
|
|
// 回收站
|
|
adminApi.GET("/trash", noteHandler.ListTrash)
|
|
adminApi.POST("/restore/:id", noteHandler.RestoreNote)
|
|
adminApi.POST("/purge/:id", noteHandler.PurgeNote)
|
|
adminApi.POST("/empty-trash", noteHandler.EmptyTrash)
|
|
|
|
// 版本历史
|
|
adminApi.GET("/notes/:id/versions", noteHandler.ListVersions)
|
|
adminApi.POST("/notes/:id/restore-version", noteHandler.RestoreVersion)
|
|
|
|
// 分享
|
|
adminApi.POST("/notes/:id/share", noteHandler.CreateShare)
|
|
adminApi.POST("/notes/:id/revoke-share", noteHandler.RevokeShare)
|
|
|
|
// 导入导出
|
|
adminApi.GET("/export/:id", noteHandler.ExportNote)
|
|
adminApi.GET("/export-all", noteHandler.ExportAll)
|
|
adminApi.POST("/import", noteHandler.ImportNotes)
|
|
|
|
// 完整树 + 图片上传
|
|
adminApi.GET("/tree", noteHandler.GetTree)
|
|
adminApi.POST("/upload", imageHandler.Upload)
|
|
|
|
// 自动保存草稿
|
|
adminApi.POST("/notes/:id/draft", noteHandler.SaveDraft)
|
|
adminApi.DELETE("/notes/:id/draft", noteHandler.DiscardDraft)
|
|
|
|
// 双向链接 / 知识图谱
|
|
adminApi.GET("/notes/:id/backlinks", noteHandler.GetBacklinks)
|
|
adminApi.GET("/graph", noteHandler.GetKnowledgeGraph)
|
|
|
|
// 标签管理
|
|
adminApi.GET("/tags/usage", noteHandler.GetTagUsage)
|
|
adminApi.POST("/tags/rename", noteHandler.RenameTag)
|
|
adminApi.POST("/tags/merge", noteHandler.MergeTag)
|
|
adminApi.DELETE("/tags", noteHandler.DeleteTag)
|
|
|
|
// 平台设置(注册开关,管理员)
|
|
adminApi.GET("/settings/registration", authHandler.GetRegistrationStatus)
|
|
adminApi.PUT("/settings/registration", authHandler.SetRegistration)
|
|
}
|
|
|
|
// ─────────── 后台管理路由 ───────────
|
|
admin := r.Group("/admin")
|
|
{
|
|
admin.GET("/login", adminHandler.LoginPage)
|
|
admin.POST("/login", adminHandler.Login)
|
|
admin.POST("/logout", adminHandler.Logout)
|
|
admin.GET("/auth", adminHandler.CheckAuth)
|
|
admin.GET("/", adminHandler.IndexPage)
|
|
}
|
|
|
|
// ─────────── 分享阅读页 ───────────
|
|
r.GET("/share/:token", noteHandler.SharePage)
|
|
|
|
// 健康检查
|
|
r.GET("/health", func(c *gin.Context) {
|
|
c.JSON(200, gin.H{"status": "ok"})
|
|
})
|
|
|
|
// 前端页面 - 根路径返回展示页面
|
|
r.GET("/", func(c *gin.Context) {
|
|
c.File("./web/index.html")
|
|
})
|
|
|
|
// PWA 静态资源(manifest / service worker / 图标)
|
|
r.StaticFile("/manifest.json", "./web/manifest.json")
|
|
r.StaticFile("/sw.js", "./web/sw.js")
|
|
r.StaticFile("/icon-192.png", "./web/icon-192.png")
|
|
r.StaticFile("/icon-512.png", "./web/icon-512.png")
|
|
|
|
return r
|
|
}
|