Move HTTP handler logic out of main into internal api and server packages, slimming main to a thin entrypoint. Bundles bug fixes: login nil-panic, empty-password validation, chirp sort ordering, duplicate-email 409, and restricting the file server to the assets directory.
90 lines
1.8 KiB
Go
90 lines
1.8 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/StevanFreeborn/chirpy/internal/api"
|
|
"github.com/StevanFreeborn/chirpy/internal/auth"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type userUpgradeData struct {
|
|
UserId string `json:"user_id"`
|
|
}
|
|
|
|
type webhookEvent struct {
|
|
Event string `json:"event"`
|
|
Data any `json:"-"`
|
|
}
|
|
|
|
// UnmarshalJSON captures the raw event data so it can be decoded into the
|
|
// concrete type for the event name.
|
|
func (p *webhookEvent) UnmarshalJSON(b []byte) error {
|
|
type Alias webhookEvent
|
|
|
|
aux := &struct {
|
|
*Alias
|
|
RawData json.RawMessage `json:"data"`
|
|
}{
|
|
Alias: (*Alias)(p),
|
|
}
|
|
|
|
if err := json.Unmarshal(b, aux); err != nil {
|
|
return err
|
|
}
|
|
|
|
switch p.Event {
|
|
case "user.upgraded":
|
|
var data userUpgradeData
|
|
|
|
if err := json.Unmarshal(aux.RawData, &data); err != nil {
|
|
return err
|
|
}
|
|
|
|
p.Data = data
|
|
default:
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// HandleWebhooks processes Polka webhook events, e.g. upgrading a user to
|
|
// Chirpy Red.
|
|
func (s *Server) HandleWebhooks(w http.ResponseWriter, r *http.Request) {
|
|
apiKey, err := auth.GetAPIKey(r.Header)
|
|
|
|
if err != nil || apiKey != s.polkaKey {
|
|
api.WriteError(w, http.StatusUnauthorized, "You are not authorized to perform this action")
|
|
return
|
|
}
|
|
|
|
event, err := api.DecodeJSON[webhookEvent](r)
|
|
|
|
if err != nil {
|
|
api.WriteError(w, http.StatusInternalServerError, "Unable to deserialize webhook event")
|
|
return
|
|
}
|
|
|
|
switch v := event.Data.(type) {
|
|
case userUpgradeData:
|
|
validUserId, err := uuid.Parse(v.UserId)
|
|
|
|
if err != nil {
|
|
api.WriteError(w, http.StatusNotFound, "Unable to upgrade user")
|
|
return
|
|
}
|
|
|
|
_, err = s.db.UpgradeUser(r.Context(), validUserId)
|
|
|
|
if err != nil {
|
|
api.WriteError(w, http.StatusNotFound, "Unable to upgrade user")
|
|
return
|
|
}
|
|
|
|
api.WriteJSON(w, http.StatusNoContent, nil)
|
|
default:
|
|
api.WriteJSON(w, http.StatusNoContent, nil)
|
|
}
|
|
}
|