fix player/session id distinction and add /user/me api endpoint
This commit is contained in:
parent
61db7de4cb
commit
a044844d8b
3
main.go
3
main.go
@ -38,6 +38,7 @@ func main() {
|
|||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.Post("/user/register", s.Register)
|
r.Post("/user/register", s.Register)
|
||||||
r.Post("/user/login", s.Login)
|
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)
|
http.ListenAndServe(":8080", r)
|
||||||
}
|
}
|
||||||
|
@ -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
|
// based on the session cookie content. If there is no such cookie, or its
|
||||||
// value is invalid, the request fails with a 403 error.
|
// value is invalid, the request fails with a 401 error.
|
||||||
func WithPlayerID(sessions player.RowQuerier) func(http.Handler) http.Handler {
|
func WithSession(sessions player.RowQuerier) func(http.Handler) http.Handler {
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
c, err := r.Cookie(sessionCookie)
|
c, err := r.Cookie(sessionCookie)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
id, err := player.ParseSession(c.Value)
|
id, err := player.ParseSession(c.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
p, err := player.FromSession(r.Context(), sessions, id, time.Now())
|
p, err := player.FromSession(r.Context(), sessions, id, time.Now())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Forbidden", http.StatusForbidden)
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctx := with(r.Context(), p)
|
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.
|
// Session returns the session ID set by WithSession in the request context.
|
||||||
func PlayerID(ctx context.Context) player.ID {
|
func Session(ctx context.Context) player.Session {
|
||||||
return value[player.ID](ctx)
|
return value[player.Session](ctx)
|
||||||
}
|
}
|
||||||
|
30
server.go
30
server.go
@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -20,14 +21,14 @@ import (
|
|||||||
type Server struct {
|
type Server struct {
|
||||||
l *lobby.Lobby
|
l *lobby.Lobby
|
||||||
|
|
||||||
creds credsDB
|
creds db
|
||||||
sessions player.Execer
|
sessions db
|
||||||
|
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
pp map[player.ID]*websocket.Conn
|
pp map[player.ID]*websocket.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
type credsDB interface {
|
type db interface {
|
||||||
player.RowQuerier
|
player.RowQuerier
|
||||||
player.Execer
|
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)
|
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.
|
// Queue connects players to games. The connection immediately upgrades.
|
||||||
// This handler MUST be wrapped in [serve.WithPlayerID].
|
// This handler MUST be wrapped in [serve.WithPlayerID].
|
||||||
func (s *Server) Queue(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) Queue(w http.ResponseWriter, r *http.Request) {
|
||||||
p := serve.PlayerID(r.Context())
|
id := serve.Session(r.Context())
|
||||||
if p == (player.ID{}) {
|
if id == (player.Session{}) {
|
||||||
panic("missing player ID")
|
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)
|
person, err := s.accept(w, r, p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||||
|
Loading…
Reference in New Issue
Block a user