Files
Gardomatic/internal/api/sessions.go
T
kleiax 904d14b64c
CI / test (push) Canceled after 0s
Initial commit
2026-09-12 22:22:17 +02:00

98 lines
2.3 KiB
Go

package api
import (
"crypto/rand"
"errors"
"net/http"
"time"
"gardomatic.kleiax.de/internal/auth"
"gardomatic.kleiax.de/internal/platform/validate"
"gardomatic.kleiax.de/internal/storage"
)
const authenticatedUserIDSessionKey = "authenticatedUserID"
const (
accountSessionIDKey = "accountSessionID"
accountSessionCreatedAtKey = "accountSessionCreatedAt"
)
func (app *application) createSessionHandler(w http.ResponseWriter, r *http.Request) {
var input struct {
Email string `json:"email"`
Password string `json:"password"`
}
err := app.readJSON(w, r, &input)
if err != nil {
app.badRequestResponse(w, r, err)
return
}
v := validate.New()
storage.ValidateEmail(v, input.Email)
auth.ValidatePasswordPlaintext(v, input.Password)
if !v.Valid() {
app.failedValidationResponse(w, r, v.Errors)
return
}
user, err := app.models.Users.GetByEmail(input.Email)
if err != nil {
switch {
case errors.Is(err, storage.ErrRecordNotFound):
app.invalidCredentialsResponse(w, r)
default:
app.serverErrorResponse(w, r, err)
}
return
}
match, err := user.Password.Matches(input.Password)
if err != nil {
app.serverErrorResponse(w, r, err)
return
}
if !match {
app.invalidCredentialsResponse(w, r)
return
}
if err := app.sessions.RenewToken(r.Context()); err != nil {
app.serverErrorResponse(w, r, err)
return
}
app.sessions.Put(r.Context(), authenticatedUserIDSessionKey, user.ID)
app.sessions.Put(r.Context(), accountSessionIDKey, rand.Text())
app.sessions.Put(r.Context(), accountSessionCreatedAtKey, time.Now().UTC().Unix())
if err := app.writeJSON(w, http.StatusCreated, envelope{"user": user}, nil); err != nil {
app.serverErrorResponse(w, r, err)
}
}
func (app *application) showSessionHandler(w http.ResponseWriter, r *http.Request) {
user, found := app.contextGetAuthenticatedUser(r)
if !found {
app.authenticationRequiredResponse(w, r)
return
}
if err := app.writeJSON(w, http.StatusOK, envelope{"user": user}, nil); err != nil {
app.serverErrorResponse(w, r, err)
}
}
func (app *application) deleteSessionHandler(w http.ResponseWriter, r *http.Request) {
if err := app.sessions.Destroy(r.Context()); err != nil {
app.serverErrorResponse(w, r, err)
return
}
w.WriteHeader(http.StatusNoContent)
}