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) } }