vibes
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"halcyon/store"
|
||||
)
|
||||
|
||||
// clientIP is the address a request really came from. Behind our own reverse
|
||||
// proxy (a loopback or private peer) the proxy's X-Forwarded-For names it;
|
||||
// otherwise the header is untrusted and ignored.
|
||||
func clientIP(r *http.Request) string {
|
||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
host = r.RemoteAddr
|
||||
}
|
||||
if ip := net.ParseIP(host); ip != nil && (ip.IsLoopback() || ip.IsPrivate()) {
|
||||
if xff := r.Header.Get("X-Forwarded-For"); xff != "" {
|
||||
first := strings.TrimSpace(strings.Split(xff, ",")[0])
|
||||
if net.ParseIP(first) != nil {
|
||||
return first
|
||||
}
|
||||
}
|
||||
}
|
||||
return host
|
||||
}
|
||||
|
||||
func sha256Hex(b []byte) string {
|
||||
h := sha256.Sum256(b)
|
||||
return hex.EncodeToString(h[:])
|
||||
}
|
||||
|
||||
// audit records something a player did. It is best effort: a failure to write
|
||||
// the log is reported but never fails the player's request.
|
||||
func (s *Server) audit(r *http.Request, player int64, action string, ship int64, slot int, detail map[string]any) {
|
||||
if detail == nil {
|
||||
detail = map[string]any{}
|
||||
}
|
||||
b, _ := json.Marshal(detail)
|
||||
err := s.st.AddAudit(context.WithoutCancel(r.Context()), store.AuditEntry{
|
||||
At: time.Now().Unix(), PlayerID: player, Action: action, Ship: ship, Slot: slot,
|
||||
Detail: string(b), IP: clientIP(r),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("audit: could not record %s for player %d: %v", action, player, err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user