Files
Felis/internal/api/handlers_auth.go
T

31 lines
1.3 KiB
Go

package api
import (
"net/http"
"felis.lolicon.best/internal/metrics"
)
// Passwordless auth handlers (spec §B). Staff (Owner/Operator) authenticate via
// email-OTP / passkey + in-game approve on op.console; players via bind code or
// email-OTP on console. There is NO password login path. This file holds only the
// logout handler — the login doors live in handlers_auth_email.go (email OTP),
// handlers_onboard.go (bind code), and the deferred passkey-login slice.
// handleLogout revokes the presented session and clears the cookie (spec §B). It
// is mounted Public and idempotent: it reads the cookie directly, so it works even
// when the session has already expired and never errors on a missing one. Ending
// a live session is audited under its account; a dead cookie leaves no row.
func (a *API) handleLogout(w http.ResponseWriter, r *http.Request) {
if c, err := r.Cookie(sessionCookieName); err == nil && c.Value != "" {
hash := hashCookie(c.Value)
u, uerr := a.Repo.SessionUser(r.Context(), hash, a.now())
if err := a.Repo.RevokeSession(r.Context(), hash); err == nil && uerr == nil {
metrics.SessionsRevokedTotal.WithLabelValues("logout").Inc()
a.auditEntry(r, AuditEntry{Actor: u.Username, ActorUserID: u.ID, Action: "auth.logout"})
}
}
clearSessionCookie(w)
writeJSON(w, http.StatusOK, map[string]any{"ok": true})
}