add logout button

This commit is contained in:
Branden J Brown 2024-02-02 17:30:35 -06:00
parent 8a07105316
commit 2314b61671
3 changed files with 49 additions and 5 deletions

View File

@ -34,9 +34,22 @@ func SetSession(w http.ResponseWriter, s player.Session) {
}) })
} }
// WithSession is a middleware that adds a player ID to the request context // RemoveSession clears the session token cookie on a response.
// based on the session cookie content. If there is no such cookie, or its func RemoveSession(w http.ResponseWriter) {
// value is invalid, the request fails with a 401 error. http.SetCookie(w, &http.Cookie{
Name: sessionCookie,
Value: "",
Path: "/",
Expires: time.Unix(0, 0),
Secure: true,
HttpOnly: true,
SameSite: http.SameSiteLaxMode,
})
}
// WithSession is a middleware that adds a player ID and session 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 401 error.
func WithSession(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) {
@ -55,7 +68,7 @@ func WithSession(sessions player.RowQuerier) func(http.Handler) http.Handler {
http.Error(w, "unauthorized", http.StatusUnauthorized) http.Error(w, "unauthorized", http.StatusUnauthorized)
return return
} }
ctx := with(r.Context(), p) ctx := with(with(r.Context(), id), p)
next.ServeHTTP(w, r.WithContext(ctx)) next.ServeHTTP(w, r.WithContext(ctx))
}) })
} }
@ -65,3 +78,8 @@ func WithSession(sessions player.RowQuerier) func(http.Handler) http.Handler {
func ReqPlayer(ctx context.Context) player.ID { func ReqPlayer(ctx context.Context) player.ID {
return value[player.ID](ctx) return value[player.ID](ctx)
} }
// ReqSession returns the session ID set by WithSession in the request context.
func ReqSession(ctx context.Context) player.Session {
return value[player.Session](ctx)
}

View File

@ -147,6 +147,30 @@ 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) Logout(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
slog := slog.With(
slog.String("remote", r.RemoteAddr),
slog.String("forwarded-for", r.Header.Get("X-Forwarded-For")),
slog.String("user-agent", r.UserAgent()),
)
id := serve.ReqSession(ctx)
if id == (player.Session{}) {
slog.WarnContext(ctx, "no session on logout")
http.Error(w, "what", http.StatusUnauthorized)
panic("unreachable")
}
err := player.Logout(ctx, s.sessions, id)
if err != nil {
slog.ErrorContext(ctx, "logout failed", "err", err.Error())
http.Error(w, "something went wrong", http.StatusInternalServerError)
return
}
serve.RemoveSession(w)
slog.InfoContext(ctx, "logged out", "session", id)
http.Redirect(w, r, "/", http.StatusSeeOther)
}
func (s *Server) Me(w http.ResponseWriter, r *http.Request) { func (s *Server) Me(w http.ResponseWriter, r *http.Request) {
id := serve.ReqPlayer(r.Context()) id := serve.ReqPlayer(r.Context())
if id == (player.ID{}) { if id == (player.ID{}) {

View File

@ -13,7 +13,8 @@
<TheLogin /> <TheLogin />
</v-row> </v-row>
<v-row v-else-if="!loadingMe" class="d-flex justify-center"> <v-row v-else-if="!loadingMe" class="d-flex justify-center">
<v-btn @click="clickPlay" color="primary">Play</v-btn> <v-btn @click="clickPlay" class="mx-4" color="primary">Play</v-btn>
<v-btn class="mx-4">Log Out</v-btn>
</v-row> </v-row>
</v-container> </v-container>
<v-container v-else-if="loading" class="fill-height"> <v-container v-else-if="loading" class="fill-height">
@ -83,5 +84,6 @@ onMounted(async () => {
} catch { } catch {
me.value = null; me.value = null;
} }
me.value = 'a';
}); });
</script> </script>