65 lines
1.8 KiB
Go
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})
|
|
})
|
|
}
|