package services import ( "fmt" "github.com/engigu/baihu-panel/internal/constant" "github.com/engigu/baihu-panel/internal/database" "github.com/engigu/baihu-panel/internal/eventbus" "github.com/engigu/baihu-panel/internal/models" "github.com/engigu/baihu-panel/internal/utils" ) type LoginLogService struct{} func NewLoginLogService() *LoginLogService { return &LoginLogService{} } // Create 创建登录日志 func (s *LoginLogService) Create(username, ip, userAgent, status, message string) error { log := &models.LoginLog{ ID: utils.GenerateID(), Username: username, IP: ip, UserAgent: userAgent, Status: status, Message: message, } return database.DB.Create(log).Error } // SubscribeEvents 注册订阅事件 func (s *LoginLogService) SubscribeEvents(bus *eventbus.EventBus) { // 用户登录事件 bus.Subscribe(constant.EventUserLogin, func(e eventbus.Event) { payload, ok := e.Payload.(map[string]interface{}) if !ok { return } username, _ := payload["username"].(string) ip, _ := payload["ip"].(string) userAgent, _ := payload["userAgent"].(string) status, _ := payload["status"].(string) message, _ := payload["message"].(string) s.Create(username, ip, userAgent, status, message) // 如果登录成功,触发系统通知 if status == "success" { bus.Publish(eventbus.Event{ Type: constant.EventSystemNotice, Payload: map[string]interface{}{ "title": "登录提醒", "content": fmt.Sprintf("用户 %s 已从 IP %s 登录系统", username, ip), "level": constant.LogLevelWarning, }, }) } }) // 暴力破解防御触发事件 bus.Subscribe(constant.EventBruteForceLogin, func(e eventbus.Event) { payload, ok := e.Payload.(map[string]interface{}) if !ok { return } username, _ := payload["username"].(string) ip, _ := payload["ip"].(string) userAgent, _ := payload["userAgent"].(string) s.Create(username, ip, userAgent, "failed", "尝试次数过多,由于暴力破解防御机制已锁定") // 触发系统通知 bus.Publish(eventbus.Event{ Type: constant.EventSystemNotice, Payload: map[string]interface{}{ "title": "系统安全警告", "content": fmt.Sprintf("检测到 IP %s 正在尝试暴力破解用户 %s", ip, username), "level": constant.LogLevelError, }, }) }) } // List 获取登录日志列表 func (s *LoginLogService) List(page, pageSize int, username string) ([]models.LoginLog, int64, error) { var logs []models.LoginLog var total int64 query := database.DB.Model(&models.LoginLog{}) if username != "" { query = query.Where("username LIKE ?", "%"+username+"%") } if err := query.Count(&total).Error; err != nil { return nil, 0, err } offset := (page - 1) * pageSize if err := query.Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&logs).Error; err != nil { return nil, 0, err } return logs, total, nil } // CleanOldLogs 清理指定天数前的日志 func (s *LoginLogService) CleanOldLogs(days int) (int64, error) { result := database.DB.Exec("DELETE FROM "+models.LoginLog{}.TableName()+" WHERE created_at < datetime('now', ?)", "-"+string(rune(days))+" days") return result.RowsAffected, result.Error }