// Package audit fournit le journal d'audit de ProxmoxPanel. // Toutes les actions sensibles (connexion, mises à jour, modifications config) y sont tracées. package audit import ( "database/sql" "encoding/json" "time" ) // Entry représente une entrée dans le journal d'audit. type Entry struct { ID int64 `json:"id"` UserID *int64 `json:"user_id,omitempty"` Username string `json:"username"` Action string `json:"action"` Resource string `json:"resource,omitempty"` Details string `json:"details,omitempty"` IP string `json:"ip,omitempty"` CreatedAt time.Time `json:"created_at"` } // Logger est le service d'audit. type Logger struct { db *sql.DB } // New crée un nouveau Logger d'audit. func New(db *sql.DB) *Logger { return &Logger{db: db} } // Log enregistre une action dans le journal d'audit. func (l *Logger) Log(userID *int64, username, action, resource string, details any, ip string) { var detailsStr string if details != nil { if s, ok := details.(string); ok { detailsStr = s } else if data, err := json.Marshal(details); err == nil { detailsStr = string(data) } } // Insertion non bloquante — on ignore les erreurs pour ne pas perturber le flux principal l.db.Exec(` INSERT INTO audit_log (user_id, username, action, resource, details, ip, created_at) VALUES (?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) `, userID, username, action, resource, detailsStr, ip) } // GetEntries retourne les dernières entrées du journal, paginées. func (l *Logger) GetEntries(limit, offset int) ([]Entry, error) { rows, err := l.db.Query(` SELECT id, user_id, username, action, resource, details, ip, created_at FROM audit_log ORDER BY created_at DESC LIMIT ? OFFSET ? `, limit, offset) if err != nil { return nil, err } defer rows.Close() var entries []Entry for rows.Next() { var e Entry var userID sql.NullInt64 var resource, details, ip sql.NullString if err := rows.Scan(&e.ID, &userID, &e.Username, &e.Action, &resource, &details, &ip, &e.CreatedAt); err != nil { continue } if userID.Valid { e.UserID = &userID.Int64 } e.Resource = resource.String e.Details = details.String e.IP = ip.String entries = append(entries, e) } return entries, rows.Err() }