mirror of
https://github.com/MengMengCode/VoCat.git
synced 2026-08-13 03:13:43 +08:00
69 lines
1.9 KiB
Go
69 lines
1.9 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"vocat/internal/store"
|
|
)
|
|
|
|
// recordAudit writes one security-relevant event to the audit trail. Failures
|
|
// are logged but never block the request being audited.
|
|
func (s *Server) recordAudit(
|
|
ctx context.Context,
|
|
actor string,
|
|
action string,
|
|
entityType string,
|
|
entityID string,
|
|
outcome string,
|
|
remoteAddr string,
|
|
) {
|
|
if s.store == nil {
|
|
return
|
|
}
|
|
_, err := s.store.AppendAuditEvent(ctx, store.AuditEvent{
|
|
Actor: actor,
|
|
Action: action,
|
|
EntityType: entityType,
|
|
EntityID: entityID,
|
|
Outcome: outcome,
|
|
RemoteAddr: remoteAddr,
|
|
CreatedAt: time.Now().UTC(),
|
|
})
|
|
if err != nil {
|
|
s.logger.Warn("write audit event failed", "action", action, "error", err)
|
|
}
|
|
}
|
|
|
|
// audit records an event for an already-authenticated request, resolving the
|
|
// actor from the session and the source address from the raw connection (proxy
|
|
// headers are deliberately not trusted for the audit trail).
|
|
func (s *Server) audit(r *http.Request, action string, entityType string, entityID string, outcome string) {
|
|
actor := ""
|
|
if s.auth != nil {
|
|
if cookie, err := r.Cookie(sessionCookieName); err == nil && cookie.Value != "" {
|
|
if session, authErr := s.auth.Authenticate(r.Context(), cookie.Value); authErr == nil {
|
|
actor = session.Principal.Username
|
|
}
|
|
}
|
|
}
|
|
s.recordAudit(r.Context(), actor, action, entityType, entityID, outcome, requestRemoteHost(r))
|
|
}
|
|
|
|
// auditAuth records an authentication event where no session exists yet (the
|
|
// actor is the username that was attempted).
|
|
func (s *Server) auditAuth(r *http.Request, username string, outcome string) {
|
|
s.recordAudit(r.Context(), username, "auth.login", "session", username, outcome, requestRemoteHost(r))
|
|
}
|
|
|
|
func requestRemoteHost(r *http.Request) string {
|
|
host, _, err := net.SplitHostPort(strings.TrimSpace(r.RemoteAddr))
|
|
if err != nil {
|
|
return strings.TrimSpace(r.RemoteAddr)
|
|
}
|
|
return host
|
|
}
|