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
This commit is contained in:
shirainbown
2026-06-19 18:59:32 +08:00
parent 396783e8a0
commit e4b2edb3bf
3 changed files with 33 additions and 0 deletions

View File

@@ -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"})
}

View File

@@ -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)
}

View File

@@ -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()