Some checks failed
Build and Deploy (service.xpcool.com) / build-and-deploy (push) Failing after 31s
将 api 层校验规则提示语、service 层 gerror.Wrap 与 response.Error 错误信息、panic 未注册提示统一改为中文,并同步中文化 cmd 路由注释 与变更记录。仅涉及注释、文档与字符串改动,无业务逻辑变更。
84 lines
2.6 KiB
Go
84 lines
2.6 KiB
Go
// Package admin_system_login_log 提供管理员登录日志服务:写(Record,登录成功/失败落库)与读(List,分页查询)。
|
||
package admin_system_login_log
|
||
|
||
import (
|
||
"context"
|
||
|
||
"github.com/gogf/gf/v2/errors/gerror"
|
||
|
||
"service.xpcool.com/internal/dao"
|
||
"service.xpcool.com/internal/model/do"
|
||
"service.xpcool.com/internal/model/dto"
|
||
"service.xpcool.com/internal/model/entity"
|
||
)
|
||
|
||
// LoginEvent 管理员登录日志事件。
|
||
type LoginEvent struct {
|
||
Username string
|
||
IP string
|
||
UserAgent string
|
||
Status int // 1 成功, 0 失败
|
||
FailReason string // 失败原因(成功时为空)
|
||
}
|
||
|
||
// IAdminLoginLog 登录日志服务接口:审计写入 + 分页查询。
|
||
type IAdminLoginLog interface {
|
||
Record(context.Context, LoginEvent) error
|
||
List(context.Context, dto.LoginLogQuery) ([]*dto.LoginLogItem, int, error)
|
||
}
|
||
|
||
var localAdminLoginLog IAdminLoginLog
|
||
|
||
type adminLoginLog struct{}
|
||
|
||
func AdminLoginLog() IAdminLoginLog {
|
||
if localAdminLoginLog == nil {
|
||
panic("AdminLoginLog 实现未注册")
|
||
}
|
||
return localAdminLoginLog
|
||
}
|
||
func RegisterAdminLoginLog(i IAdminLoginLog) { localAdminLoginLog = i }
|
||
|
||
func NewAdminLoginLog() IAdminLoginLog { return &adminLoginLog{} }
|
||
|
||
// Record 写入一条登录日志(成功或失败)。
|
||
func (s *adminLoginLog) Record(ctx context.Context, e LoginEvent) error {
|
||
_, err := dao.AdminLoginLog.Ctx(ctx).Data(do.AdminLoginLog{
|
||
Username: e.Username, Ip: e.IP, UserAgent: e.UserAgent,
|
||
Status: e.Status, FailReason: e.FailReason,
|
||
}).Insert()
|
||
return gerror.Wrap(err, "写入登录日志失败")
|
||
}
|
||
|
||
// List 分页查询管理员登录日志,支持账号与结果过滤(Status 为 nil 时不过滤)。
|
||
func (s *adminLoginLog) List(ctx context.Context, q dto.LoginLogQuery) ([]*dto.LoginLogItem, int, error) {
|
||
m := dao.AdminLoginLog.Ctx(ctx)
|
||
if q.Username != "" {
|
||
m = m.WhereLike("username", "%"+q.Username+"%")
|
||
}
|
||
if q.Status != nil {
|
||
m = m.Where(do.AdminLoginLog{Status: *q.Status})
|
||
}
|
||
total, err := m.Count()
|
||
if err != nil {
|
||
return nil, 0, gerror.Wrap(err, "统计登录日志总数失败")
|
||
}
|
||
if total == 0 {
|
||
return nil, 0, nil
|
||
}
|
||
var list []entity.AdminLoginLog
|
||
if err = m.Page(q.Page, q.Size).OrderDesc("id").Scan(&list); err != nil {
|
||
return nil, 0, gerror.Wrap(err, "查询登录日志列表失败")
|
||
}
|
||
items := make([]*dto.LoginLogItem, 0, len(list))
|
||
for i := range list {
|
||
l := &list[i]
|
||
items = append(items, &dto.LoginLogItem{
|
||
Id: l.Id, Username: l.Username, IP: l.Ip, UserAgent: l.UserAgent,
|
||
Status: l.Status, FailReason: l.FailReason,
|
||
CreatedAt: l.CreatedAt.Layout("2006-01-02 15:04:05"),
|
||
})
|
||
}
|
||
return items, total, nil
|
||
}
|