Files
ttstd-infinite-canvas/backend/internal/handler/admin_login_log_routes.go
2026-10-13 05:31:30 +08:00

65 lines
1.8 KiB
Go

package handler
import (
"log"
"yingce/backend/internal/service"
"github.com/gin-gonic/gin"
)
func loginRequestContext(c *gin.Context) service.LoginContext {
return service.LoginContext{IP: c.ClientIP(), UserAgent: c.Request.UserAgent()}
}
// 补充 JSON 校验和频控等在认证域调用之前被拒绝的请求;不读取或保存原始请求正文。
func rejectedLoginAudit(svc *service.Service, method string) gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
if c.Writer.Status() < 400 || c.GetBool("login_audit_handled") {
return
}
if err := svc.RecordRejectedLogin(method, loginRequestContext(c), c.Writer.Status()); err != nil {
log.Printf("rejected login audit write failed: method=%s status=%d error=%v", method, c.Writer.Status(), err)
}
}
}
func registerAdminLoginLogRoutes(r *gin.RouterGroup, svc *service.Service) {
r.GET("/admin/login-logs", func(c *gin.Context) {
actor, err := currentUser(c, svc)
if err != nil {
failService(c, err)
return
}
if err := svc.RequireAdmin(actor); err != nil {
failService(c, err)
return
}
page, limit, err := parsePaginationQuery(c, 20)
if err != nil {
fail(c, 400, err)
return
}
query := service.LoginLogQuery{Keyword: c.Query("keyword"), Event: c.Query("event"), Method: c.Query("method"), Result: c.Query("result"), IP: c.Query("ip"), From: c.Query("from"), To: c.Query("to")}
result, err := svc.AdminLoginLogs(actor, query, page, limit)
if err != nil {
failService(c, err)
return
}
ok(c, result)
})
r.GET("/admin/login-logs/:id", func(c *gin.Context) {
actor, err := currentUser(c, svc)
if err != nil {
failService(c, err)
return
}
event, err := svc.AdminLoginLog(actor, c.Param("id"))
if err != nil {
failService(c, err)
return
}
ok(c, gin.H{"log": event})
})
}