This repository has been archived on 2026-06-21. You can view files and clone it, but cannot push or open issues or pull requests.
Files
MetaLab/internal/router/api.go
Victor_Jay 2ea9788ec7 fix: 关注状态 API 添加 Optional 认证中间件
- /api/users/:uid/follow-status 等公开 GET 接口缺少 Optional 认证
- 导致 GetGinUser 无法获取当前用户 uid,始终返回 i_follow=false
- 关注按钮加载时无法显示正确初始状态(始终显示"关注")
- 三条 GET 接口统一加入 authMdw.Optional() 组
- 不影响未登录用户(未登录依然返回 false)
2026-06-03 13:11:56 +08:00

199 lines
7.0 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 (
"metazone.cc/metalab/internal/config"
"metazone.cc/metalab/internal/middleware"
"github.com/gin-gonic/gin"
)
// setupAPIRoutes 注册 API 路由
func setupAPIRoutes(r *gin.Engine, cfg *config.Config, d *dependencies) {
// --- 设置页 API需登录 ---
settingsAPI := r.Group("/api/settings")
settingsAPI.Use(d.authMdw.Required())
settingsAPI.Use(d.authMdw.BannedWriteGuard())
settingsAPI.Use(middleware.CSRF(cfg))
{
settingsAPI.PUT("/profile", d.settingsCtrl.UpdateProfile)
settingsAPI.POST("/avatar", d.settingsCtrl.UploadAvatar)
settingsAPI.PUT("/password", middleware.SensitiveRateLimit(d.rateLimiter), d.settingsCtrl.ChangePassword)
settingsAPI.POST("/delete-account", middleware.SensitiveRateLimit(d.rateLimiter), d.settingsCtrl.DeleteAccount)
settingsAPI.GET("/audit-status", d.settingsCtrl.AuditStatus)
// 登录管理
settingsAPI.GET("/sessions", d.settingsCtrl.ListSessions)
settingsAPI.DELETE("/sessions/:sid", d.settingsCtrl.DestroySession)
settingsAPI.POST("/sessions/destroy-others", d.settingsCtrl.DestroyOtherSessions)
settingsAPI.PUT("/sessions/:sid/remark", d.settingsCtrl.UpdateSessionRemark)
// 通知偏好
settingsAPI.GET("/notify-prefs", d.settingsCtrl.GetNotifyPrefs)
settingsAPI.PUT("/notify-prefs", d.settingsCtrl.UpdateNotifyPref)
}
// --- 消息中心 API需登录 ---
messagesAPI := r.Group("/api/messages")
messagesAPI.Use(d.authMdw.Required())
messagesAPI.Use(d.authMdw.BannedWriteGuard())
messagesAPI.Use(middleware.CSRF(cfg))
{
messagesAPI.GET("/unread", d.messageCtrl.UnreadCount)
messagesAPI.POST("/:id/read", d.messageCtrl.MarkRead)
messagesAPI.POST("/read-all", d.messageCtrl.MarkAllRead)
}
// --- 积分/等级 API需登录 ---
levelAPI := r.Group("/api/level")
levelAPI.Use(d.authMdw.Required())
levelAPI.Use(d.authMdw.BannedWriteGuard())
levelAPI.Use(middleware.CSRF(cfg))
{
levelAPI.POST("/checkin", middleware.SensitiveRateLimit(d.rateLimiter), d.levelCtrl.CheckIn)
levelAPI.GET("/info", d.levelCtrl.GetLevel)
}
// --- 认证 API ---
api := r.Group("/api")
api.Use(middleware.CSRF(cfg))
{
api.POST("/auth/check-email", d.authCtrl.CheckEmail)
api.POST("/auth/register", d.authCtrl.Register)
api.POST("/auth/login", d.authCtrl.Login)
api.POST("/auth/confirm-restore", d.authCtrl.ConfirmRestore)
api.POST("/auth/logout", d.authCtrl.Logout)
api.POST("/auth/refresh", d.authCtrl.RefreshToken)
// 帖子公开 API无需登录
api.GET("/posts", d.postCtrl.ListAPI)
api.GET("/posts/:id", d.postCtrl.ShowAPI)
}
// --- 帖子 API需登录 ---
postsAPI := r.Group("/api/posts")
postsAPI.Use(d.authMdw.Required())
postsAPI.Use(d.authMdw.BannedWriteGuard())
postsAPI.Use(middleware.CSRF(cfg))
{
postsAPI.POST("/:id/submit", d.postCtrl.Submit)
postsAPI.POST("/upload-image", d.postCtrl.UploadImage)
}
// --- 创作中心 API需登录 ---
studioAPI := r.Group("/api/studio")
studioAPI.Use(d.authMdw.Required())
studioAPI.Use(d.authMdw.BannedWriteGuard())
studioAPI.Use(middleware.CSRF(cfg))
{
studioAPI.GET("/overview", d.studioCtrl.OverviewAPI)
studioAPI.GET("/posts", d.studioCtrl.ListPostsAPI)
studioAPI.POST("/posts", d.studioCtrl.Create)
studioAPI.PUT("/posts/:id", d.studioCtrl.Update)
studioAPI.DELETE("/posts/:id", d.studioCtrl.Delete)
studioAPI.POST("/posts/:id/submit", d.studioCtrl.Submit)
}
// --- 域能 API需登录 ---
energyAPI := r.Group("/api/energy")
energyAPI.Use(d.authMdw.Required())
energyAPI.Use(d.authMdw.BannedWriteGuard())
energyAPI.Use(middleware.CSRF(cfg))
{
energyAPI.POST("/energize", d.energyCtrl.Energize)
energyAPI.GET("/info", d.energyCtrl.GetEnergyInfo)
energyAPI.GET("/logs", d.energyCtrl.GetEnergyLogs)
}
// --- 评论 API部分需登录 ---
// 公开读取
commentsPublic := r.Group("/api/posts/:id/comments")
{
commentsPublic.GET("", d.commentCtrl.ListRootComments)
commentsPublic.GET("/:root_id/replies", d.commentCtrl.ListReplies)
}
// 需要登录的操作
commentsAPI := r.Group("/api")
commentsAPI.Use(d.authMdw.Required())
commentsAPI.Use(d.authMdw.BannedWriteGuard())
commentsAPI.Use(middleware.CSRF(cfg))
{
commentsAPI.POST("/posts/:id/comments", d.commentCtrl.CreateRoot)
commentsAPI.POST("/comments/:id/reply", d.commentCtrl.CreateReply)
commentsAPI.DELETE("/comments/:id", d.commentCtrl.Delete)
commentsAPI.GET("/users/search", d.commentCtrl.SearchUsers)
commentsAPI.POST("/comments/upload-image", d.commentCtrl.UploadImage)
}
// --- 赞/踩 API ---
// 公开:查询反应状态(未登录返回 none + 点赞数)
r.GET("/api/posts/:id/reaction", d.reactionCtrl.GetReaction)
// 需登录:切换赞/踩
reactionAPI := r.Group("/api/posts/:id")
reactionAPI.Use(d.authMdw.Required())
reactionAPI.Use(d.authMdw.BannedWriteGuard())
reactionAPI.Use(middleware.CSRF(cfg))
{
reactionAPI.POST("/like", d.reactionCtrl.ToggleLike)
reactionAPI.POST("/dislike", d.reactionCtrl.ToggleDislike)
}
// --- 关注 API ---
// 公开Optional 认证以获取当前用户关注状态,未登录返回 false
followPublic := r.Group("/api/users/:uid")
followPublic.Use(d.authMdw.Optional())
{
followPublic.GET("/follow-status", d.followCtrl.GetStatus)
followPublic.GET("/followers", d.followCtrl.Followers)
followPublic.GET("/following", d.followCtrl.Following)
}
// 需登录:切换关注
followAPI := r.Group("/api/users/:uid")
followAPI.Use(d.authMdw.Required())
followAPI.Use(d.authMdw.BannedWriteGuard())
followAPI.Use(middleware.CSRF(cfg))
{
followAPI.POST("/follow", d.followCtrl.Toggle)
}
// --- 收藏夹 API ---
// 公开:文章收藏状态(未登录返回 false
r.GET("/api/posts/:id/folder-status", d.favoriteCtrl.GetPostStatus)
// 公开:查看公开收藏夹内容
r.GET("/api/folders/:id/posts", d.favoriteCtrl.ListFolderItems)
// 需登录:收藏操作
folderAPI := r.Group("/api/folders")
folderAPI.Use(d.authMdw.Required())
folderAPI.Use(d.authMdw.BannedWriteGuard())
folderAPI.Use(middleware.CSRF(cfg))
{
folderAPI.GET("", d.favoriteCtrl.ListFolders)
folderAPI.POST("", d.favoriteCtrl.CreateFolder)
folderAPI.PUT("/:id", d.favoriteCtrl.UpdateFolder)
folderAPI.DELETE("/:id", d.favoriteCtrl.DeleteFolder)
folderAPI.POST("/:id/posts", d.favoriteCtrl.AddToFolder)
folderAPI.DELETE("/:id/posts/:postId", d.favoriteCtrl.RemoveFromFolder)
}
// 需登录切换收藏Toggle
favToggleAPI := r.Group("/api/posts/:id")
favToggleAPI.Use(d.authMdw.Required())
favToggleAPI.Use(d.authMdw.BannedWriteGuard())
favToggleAPI.Use(middleware.CSRF(cfg))
{
favToggleAPI.POST("/favorite", d.favoriteCtrl.ToggleFavorite)
}
// --- 空间/隐私设置 API需登录 ---
spaceAPI := r.Group("/api/space")
spaceAPI.Use(d.authMdw.Required())
spaceAPI.Use(d.authMdw.BannedWriteGuard())
spaceAPI.Use(middleware.CSRF(cfg))
{
spaceAPI.PUT("/privacy", d.spaceCtrl.UpdatePrivacy)
}
// --- Studio 趋势 API需登录 ---
trendsAPI := r.Group("/api/studio")
trendsAPI.Use(d.authMdw.Required())
{
trendsAPI.GET("/trends", d.studioCtrl.TrendsAPI)
}
}