Files
hi-server/internal/handler/lottery_routes.go
T
shanshanzhong147 92cf2921dd 修复(#3): 抽奖 Stage 1 后台审计 IP/UA 丢失 + 冒烟脚本 Bearer 前缀
Closes HIF-3 (Stage 1 P1 defects from QA smoke report)

F2: admin_action_log.ip / user_agent 恒为空
- 根因:requestMeta 从 ctx 读裸字符串 key,全库无 writer 塞
- 修复:新增 AdminMetaMiddleware 用 typed constant.CtxKeyIP / CtxKeyUserAgent
- 挂载:lottery admin 组末尾(不 gate access)
- 回归护栏:UsesTypedKey + IgnoresBareStringKeys 双向断言 typed key,防止未来退化回裸字符串

F3: qa/lottery/stage1_curl.sh Bearer 前缀
- 删除两处 Bearer 前缀 + 加注释说明 ppanel AuthMiddleware 不 strip

单测 5 用例全绿;scope 严格限于 lottery admin 组,其它路径零改动;无 DB 变更。

Merged: architect review 后,将触发 staging 二次部署 — 期望这次能一并解决 shanshanzhong147 手工 SSH 后 Lottery.Enable=true 未生效的问题(若真是 mount/restart 未正确 pick up)。
2026-07-09 07:45:58 -07:00

45 lines
2.4 KiB
Go

package handler
import (
"github.com/gin-gonic/gin"
adminLottery "github.com/perfect-panel/server/internal/handler/admin/lottery"
publicLottery "github.com/perfect-panel/server/internal/handler/public/lottery"
"github.com/perfect-panel/server/internal/middleware"
"github.com/perfect-panel/server/internal/svc"
)
// registerLotteryRoutes wires the Stage 1 lottery endpoints. Kept in its own
// file to avoid ballooning routes.go and to make the lottery surface easy to
// audit end-to-end. The path prefix "/v1/lottery" is under the user middleware
// stack (AuthMiddleware + DeviceMiddleware); "/v1/admin/lottery" uses the
// admin-detecting AuthMiddleware (path contains "admin" segment).
func registerLotteryRoutes(router *gin.Engine, serverCtx *svc.ServiceContext) {
userGroup := router.Group("/v1/lottery")
userGroup.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))
{
userGroup.GET("/config", publicLottery.QueryLotteryConfigHandler(serverCtx))
userGroup.POST("/draw", publicLottery.DrawLotteryHandler(serverCtx))
userGroup.GET("/records", publicLottery.QueryLotteryRecordsHandler(serverCtx))
userGroup.POST("/claim", publicLottery.ClaimLotteryPrizeHandler(serverCtx))
}
adminGroup := router.Group("/v1/admin/lottery")
adminGroup.Use(middleware.AuthMiddleware(serverCtx), middleware.AdminMetaMiddleware())
{
adminGroup.POST("/activities", adminLottery.CreateLotteryActivityHandler(serverCtx))
adminGroup.PUT("/activities", adminLottery.UpdateLotteryActivityHandler(serverCtx))
adminGroup.GET("/activities", adminLottery.ListLotteryActivitiesHandler(serverCtx))
adminGroup.GET("/activities/detail", adminLottery.GetLotteryActivityHandler(serverCtx))
adminGroup.POST("/activities/publish", adminLottery.PublishLotteryActivityHandler(serverCtx))
adminGroup.POST("/activities/pause", adminLottery.PauseLotteryActivityHandler(serverCtx))
adminGroup.PUT("/activities/rules", adminLottery.UpdateLotteryRulesHandler(serverCtx))
adminGroup.POST("/prizes", adminLottery.CreateLotteryPrizeHandler(serverCtx))
adminGroup.PUT("/prizes", adminLottery.UpdateLotteryPrizeHandler(serverCtx))
adminGroup.DELETE("/prizes", adminLottery.DeleteLotteryPrizeHandler(serverCtx))
adminGroup.GET("/prizes", adminLottery.ListLotteryPrizesHandler(serverCtx))
adminGroup.POST("/chances/grant", adminLottery.GrantLotteryChanceHandler(serverCtx))
}
}