Some checks failed
Build and Deploy (service.xpcool.com) / build-and-deploy (push) Failing after 5m7s
- 新增 9 张房屋相关数据表(社区/楼宇/房源/价格快照/交易/设施/社区设施/学区/偏好) - 添加菜单权限种子数据并绑定超级管理员角色 - 生成 DAO 层代码和实体对象 - 实现房屋模块 API 接口(社区/房源/看板)和控制器服务层 - 支持多平台软关联匹配、笋盘标记和低可信度标记功能 - 更新超级管理员账号为 xxcool/xxCool@2026 - 调整 RBAC 菜单结构,移除管理员管理功能,新增日志管理菜单 - 修复 RBAC 安全漏洞,确保禁用角色权限失效 - 重构认证模块,将登录相关接口迁移到统一包结构下 - 移除废弃的管理模块和工具类接口定义 - 为通用工具包添加中文注释和文档说明
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 implementation not registered")
|
||
}
|
||
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, "insert login log")
|
||
}
|
||
|
||
// 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, "count login logs")
|
||
}
|
||
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, "query login logs")
|
||
}
|
||
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
|
||
}
|