From e4b2edb3bf508cc6e7b06f739150409c28dc0ef3 Mon Sep 17 00:00:00 2001 From: shirainbown Date: Fri, 19 Jun 2026 18:59:32 +0800 Subject: [PATCH] feat: add comprehensive operation logs for all critical actions - Login/Logout: record user authentication events with source IP - Login failed: record failed login attempts for security audit - Export: record data export operations - Machine status change: record online/offline transitions with reason - SSH sync: record automatic SSH sync success/failure with error details - All auto-generated logs use username='system' and empty source_ip --- server/handlers/auth.go | 15 +++++++++++++++ server/handlers/export.go | 5 +++++ server/services/ping.go | 13 +++++++++++++ 3 files changed, 33 insertions(+) diff --git a/server/handlers/auth.go b/server/handlers/auth.go index 83a2984..ee6b797 100644 --- a/server/handlers/auth.go +++ b/server/handlers/auth.go @@ -27,10 +27,16 @@ func (h *AuthHandler) Login(c *gin.Context) { return } if req.Username != h.Cfg.AdminUser { + // 记录登录失败日志 + var entityID int64 = 0 + middleware.LogOperation("login_failed", "user", &entityID, req.Username, "", "invalid credentials", c.ClientIP(), req.Username) c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid credentials"}) return } if !checkPassword(req.Password, h.Cfg.AdminPass) { + // 记录登录失败日志 + var entityID int64 = 0 + middleware.LogOperation("login_failed", "user", &entityID, req.Username, "", "invalid credentials", c.ClientIP(), req.Username) c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid credentials"}) return } @@ -40,13 +46,22 @@ func (h *AuthHandler) Login(c *gin.Context) { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } + // 记录登录成功日志 + var entityID int64 = 0 + middleware.LogOperation("login", "user", &entityID, req.Username, "", "", c.ClientIP(), req.Username) c.JSON(http.StatusOK, gin.H{"username": req.Username, "is_admin": true}) } func (h *AuthHandler) Logout(c *gin.Context) { session := sessions.Default(c) + user := session.Get(middleware.AdminSessionKey) session.Delete(middleware.AdminSessionKey) _ = session.Save() + // 记录登出日志 + if user != nil { + var entityID int64 = 0 + middleware.LogOperation("logout", "user", &entityID, user.(string), "", "", c.ClientIP(), user.(string)) + } c.JSON(http.StatusOK, gin.H{"message": "logged out"}) } diff --git a/server/handlers/export.go b/server/handlers/export.go index 5478bd7..5bfd0bc 100644 --- a/server/handlers/export.go +++ b/server/handlers/export.go @@ -68,6 +68,11 @@ func (h *ExportHandler) Export(c *gin.Context) { b, _ := json.MarshalIndent(data, "", " ") filename := "lan-manager-backup-" + time.Now().Format("20060102") + ".json" c.Header("Content-Disposition", "attachment; filename="+filename) + + // 记录导出日志 + var entityID int64 = 0 + middleware.LogOperation("export", "system", &entityID, "json-export", "", "", c.ClientIP(), middleware.CurrentUser(c)) + c.Data(http.StatusOK, "application/json", b) } diff --git a/server/services/ping.go b/server/services/ping.go index 1a05ed4..51d3c1c 100644 --- a/server/services/ping.go +++ b/server/services/ping.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "lan-manager/server/db" + "lan-manager/server/middleware" "lan-manager/server/models" "lan-manager/server/utils" "net" @@ -199,6 +200,9 @@ func handlePingResult(m *machinePing, res PingResult) { fmt.Printf("[Ping] %s -> online=false, reason=%s\n", m.ip, reason) } _, _ = db.DB.Exec(`INSERT INTO offline_logs (machine_id, reason, started_at) VALUES (?, ?, CURRENT_TIMESTAMP)`, m.id, reason) + // 记录状态变化日志 + var entityID int64 = m.id + middleware.LogOperation("status_change", "machine", &entityID, m.ip, "online", "offline: "+reason, "", "system") m.wasOnline = false return } @@ -219,6 +223,9 @@ func handlePingResult(m *machinePing, res PingResult) { _, _ = db.DB.Exec(`UPDATE offline_logs SET ended_at=CURRENT_TIMESTAMP, duration_seconds=? WHERE id=?`, duration, logID) _, _ = db.DB.Exec(`UPDATE machines SET total_offline_seconds=total_offline_seconds+? WHERE id=?`, duration, m.id) } + // 记录状态恢复日志 + var entityID int64 = m.id + middleware.LogOperation("status_change", "machine", &entityID, m.ip, "offline", "online", "", "system") m.wasOnline = true return } @@ -338,9 +345,15 @@ func StartSSHSyncService() { result, err := GetSSHInfo(machine.ip, machine.sshPort, machine.username, plainPass) if err != nil { fmt.Printf("[SSH] sync failed for %s:%d: %v\n", machine.ip, machine.sshPort, err) + // 记录 SSH 同步失败日志 + var entityID int64 = machine.id + middleware.LogOperation("sync_ssh_failed", "machine", &entityID, machine.ip, "", err.Error(), "", "system") return } saveSSHResult(machine.id, machine.ip, machine.sshPort, result) + // 记录 SSH 同步成功日志 + var entityID int64 = machine.id + middleware.LogOperation("sync_ssh", "machine", &entityID, machine.ip, "", "success", "", "system") }(m) } wg.Wait()