fix player/session id distinction and add /user/me api endpoint

This commit is contained in:
Branden J Brown 2024-02-01 21:38:44 -06:00
parent 61db7de4cb
commit a044844d8b
3 changed files with 36 additions and 15 deletions

View File

@ -38,6 +38,7 @@ func main() {
r := chi.NewRouter()
r.Post("/user/register", s.Register)
r.Post("/user/login", s.Login)
r.With(serve.WithPlayerID(sessions)).Get("/queue", s.Queue)
r.With(serve.WithSession(sessions)).Get("/user/me", s.Me)
r.With(serve.WithSession(sessions)).Get("/queue", s.Queue)
http.ListenAndServe(":8080", r)
}

View File

@ -34,25 +34,25 @@ func SetSession(w http.ResponseWriter, s player.Session) {
})
}
// WithPlayerID is a middleware that adds a player ID to the request context
// WithSession is a middleware that adds a player ID to the request context
// based on the session cookie content. If there is no such cookie, or its
// value is invalid, the request fails with a 403 error.
func WithPlayerID(sessions player.RowQuerier) func(http.Handler) http.Handler {
// value is invalid, the request fails with a 401 error.
func WithSession(sessions player.RowQuerier) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
c, err := r.Cookie(sessionCookie)
if err != nil {
http.Error(w, "Forbidden", http.StatusForbidden)
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
id, err := player.ParseSession(c.Value)
if err != nil {
http.Error(w, "Forbidden", http.StatusForbidden)
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
p, err := player.FromSession(r.Context(), sessions, id, time.Now())
if err != nil {
http.Error(w, "Forbidden", http.StatusForbidden)
http.Error(w, "unauthorized", http.StatusUnauthorized)
return
}
ctx := with(r.Context(), p)
@ -61,7 +61,7 @@ func WithPlayerID(sessions player.RowQuerier) func(http.Handler) http.Handler {
}
}
// Player returns the player ID set by WithPlayerID in the request context.
func PlayerID(ctx context.Context) player.ID {
return value[player.ID](ctx)
// Session returns the session ID set by WithSession in the request context.
func Session(ctx context.Context) player.Session {
return value[player.Session](ctx)
}

View File

@ -2,6 +2,7 @@ package main
import (
"context"
"encoding/json"
"errors"
"log/slog"
"net/http"
@ -20,14 +21,14 @@ import (
type Server struct {
l *lobby.Lobby
creds credsDB
sessions player.Execer
creds db
sessions db
mu sync.Mutex
pp map[player.ID]*websocket.Conn
}
type credsDB interface {
type db interface {
player.RowQuerier
player.Execer
}
@ -133,13 +134,32 @@ func (s *Server) Login(w http.ResponseWriter, r *http.Request) {
slog.InfoContext(ctx, "logged in", "player", p, "id", id)
}
func (s *Server) Me(w http.ResponseWriter, r *http.Request) {
id := serve.Session(r.Context())
if id == (player.Session{}) {
panic("missing player ID")
}
p, err := player.FromSession(r.Context(), s.sessions, id, time.Now())
if err != nil {
panic("session with no player id: " + err.Error())
}
q := struct {
ID player.ID `json:"id"`
}{p}
json.NewEncoder(w).Encode(q)
}
// Queue connects players to games. The connection immediately upgrades.
// This handler MUST be wrapped in [serve.WithPlayerID].
func (s *Server) Queue(w http.ResponseWriter, r *http.Request) {
p := serve.PlayerID(r.Context())
if p == (player.ID{}) {
id := serve.Session(r.Context())
if id == (player.Session{}) {
panic("missing player ID")
}
p, err := player.FromSession(r.Context(), s.sessions, id, time.Now())
if p == (player.ID{}) {
panic("session with no player id: " + err.Error())
}
person, err := s.accept(w, r, p)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)