2024-10-26 21:19:11 +02:00
|
|
|
package handler
|
2024-10-23 22:16:51 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"log"
|
|
|
|
"net/http"
|
|
|
|
"time"
|
|
|
|
|
2024-10-24 22:40:26 +02:00
|
|
|
"github.com/finchrelia/chirpy-server/internal/auth"
|
2024-10-25 23:31:57 +02:00
|
|
|
"github.com/finchrelia/chirpy-server/internal/database"
|
2024-10-23 22:16:51 +02:00
|
|
|
"github.com/google/uuid"
|
|
|
|
)
|
|
|
|
|
|
|
|
type User struct {
|
2024-10-24 22:40:26 +02:00
|
|
|
ID uuid.UUID `json:"id"`
|
|
|
|
CreatedAt time.Time `json:"created_at"`
|
|
|
|
UpdatedAt time.Time `json:"updated_at"`
|
|
|
|
Email string `json:"email"`
|
|
|
|
HashedPassword string `json:"-"`
|
2024-10-26 15:03:14 +02:00
|
|
|
ChirpyRed bool `json:"is_chirpy_red"`
|
2024-10-23 22:16:51 +02:00
|
|
|
}
|
|
|
|
|
2024-10-26 21:19:11 +02:00
|
|
|
func (cfg *APIConfig) CreateUsers(w http.ResponseWriter, r *http.Request) {
|
2024-10-23 22:16:51 +02:00
|
|
|
type parameters struct {
|
2024-10-24 22:40:26 +02:00
|
|
|
Email string `json:"email"`
|
|
|
|
Password string `json:"password"`
|
2024-10-23 22:16:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
decoder := json.NewDecoder(r.Body)
|
|
|
|
params := parameters{}
|
|
|
|
err := decoder.Decode(¶ms)
|
|
|
|
if err != nil {
|
2024-10-26 21:19:11 +02:00
|
|
|
log.Printf("Error decoding parameters: %v", err)
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2024-10-23 22:16:51 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
defer r.Body.Close()
|
2024-10-24 22:40:26 +02:00
|
|
|
|
|
|
|
hashedPassword, err := auth.HashPassword(params.Password)
|
|
|
|
if err != nil {
|
2024-10-26 21:19:11 +02:00
|
|
|
log.Printf("Error hashing password: %v", err)
|
2024-10-24 22:40:26 +02:00
|
|
|
}
|
2024-10-25 23:31:57 +02:00
|
|
|
newDBUser, err := cfg.DB.CreateUser(r.Context(), database.CreateUserParams{
|
|
|
|
Email: params.Email,
|
|
|
|
HashedPassword: hashedPassword,
|
|
|
|
})
|
2024-10-23 22:16:51 +02:00
|
|
|
if err != nil {
|
2024-10-26 21:19:11 +02:00
|
|
|
log.Printf("Error creating user %s: %v", params.Email, err)
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2024-10-23 22:16:51 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
newId := newDBUser.ID
|
2024-10-26 21:19:11 +02:00
|
|
|
JsonResponse(w, http.StatusCreated, User{
|
2024-10-23 22:16:51 +02:00
|
|
|
ID: newId,
|
|
|
|
CreatedAt: newDBUser.CreatedAt,
|
|
|
|
UpdatedAt: newDBUser.UpdatedAt,
|
|
|
|
Email: newDBUser.Email,
|
2024-10-26 15:03:14 +02:00
|
|
|
ChirpyRed: newDBUser.IsChirpyRed,
|
2024-10-26 21:19:11 +02:00
|
|
|
})
|
2024-10-23 22:16:51 +02:00
|
|
|
}
|
2024-10-26 15:03:14 +02:00
|
|
|
|
2024-10-26 21:19:11 +02:00
|
|
|
func (cfg *APIConfig) UpdateUsers(w http.ResponseWriter, r *http.Request) {
|
2024-10-26 15:03:14 +02:00
|
|
|
token, err := auth.GetBearerToken(r.Header)
|
|
|
|
if err != nil {
|
2024-10-26 21:19:11 +02:00
|
|
|
log.Printf("Error extracting token: %v", err)
|
|
|
|
w.WriteHeader(http.StatusUnauthorized)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
userId, err := auth.ValidateJWT(token, cfg.JWT)
|
|
|
|
if err != nil {
|
2024-10-26 21:19:11 +02:00
|
|
|
log.Printf("Invalid JWT: %v", err)
|
|
|
|
w.WriteHeader(http.StatusUnauthorized)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
type parameters struct {
|
|
|
|
Email string `json:"email"`
|
|
|
|
Password string `json:"password"`
|
|
|
|
}
|
|
|
|
|
|
|
|
decoder := json.NewDecoder(r.Body)
|
|
|
|
params := parameters{}
|
|
|
|
err = decoder.Decode(¶ms)
|
|
|
|
if err != nil {
|
2024-10-26 21:19:11 +02:00
|
|
|
log.Printf("Error decoding parameters: %v", err)
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
|
|
|
|
hashedPassword, err := auth.HashPassword(params.Password)
|
|
|
|
if err != nil {
|
2024-10-26 21:19:11 +02:00
|
|
|
log.Printf("Error hashing password: %v", err)
|
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
credentialsQueryParams := database.UpdateUserCredentialsParams{
|
|
|
|
ID: userId,
|
|
|
|
Email: params.Email,
|
|
|
|
HashedPassword: hashedPassword,
|
|
|
|
}
|
|
|
|
updatedCredentials, err := cfg.DB.UpdateUserCredentials(r.Context(), credentialsQueryParams)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Error updating user credentials: %v", err)
|
2024-10-26 21:19:11 +02:00
|
|
|
w.WriteHeader(http.StatusInternalServerError)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
2024-10-26 21:19:11 +02:00
|
|
|
JsonResponse(w, http.StatusOK, User{
|
2024-10-26 15:03:14 +02:00
|
|
|
ID: userId,
|
|
|
|
CreatedAt: updatedCredentials.CreatedAt,
|
|
|
|
UpdatedAt: updatedCredentials.UpdatedAt,
|
|
|
|
Email: updatedCredentials.Email,
|
|
|
|
ChirpyRed: updatedCredentials.IsChirpyRed,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-10-26 21:19:11 +02:00
|
|
|
func (cfg *APIConfig) SubscribeUser(w http.ResponseWriter, r *http.Request) {
|
2024-10-26 15:03:14 +02:00
|
|
|
_, err := auth.GetAPIKey(r.Header)
|
|
|
|
if err != nil {
|
2024-10-26 21:19:11 +02:00
|
|
|
log.Printf("Error extracting apiKey: %v", err)
|
|
|
|
w.WriteHeader(http.StatusUnauthorized)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
type parameters struct {
|
|
|
|
Event string `json:"event"`
|
|
|
|
Data map[string]string `json:"data"`
|
|
|
|
}
|
|
|
|
decoder := json.NewDecoder(r.Body)
|
|
|
|
params := parameters{}
|
|
|
|
err = decoder.Decode(¶ms)
|
|
|
|
if err != nil {
|
2024-10-26 21:19:11 +02:00
|
|
|
log.Printf("Error decoding parameters: %v", err)
|
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
defer r.Body.Close()
|
|
|
|
|
|
|
|
if params.Event != "user.upgraded" {
|
2024-10-26 21:19:11 +02:00
|
|
|
w.WriteHeader(http.StatusNoContent)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
paramsUserIdString := params.Data["user_id"]
|
|
|
|
paramsUserId, err := uuid.Parse(paramsUserIdString)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("Specified user_id is not a valid UUID: %v", err)
|
2024-10-26 21:19:11 +02:00
|
|
|
w.WriteHeader(http.StatusBadRequest)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
err = cfg.DB.UpgradeUser(r.Context(), paramsUserId)
|
|
|
|
if err != nil {
|
|
|
|
log.Printf("No user matches user_id given: %v", err)
|
2024-10-26 21:19:11 +02:00
|
|
|
w.WriteHeader(http.StatusNotFound)
|
2024-10-26 15:03:14 +02:00
|
|
|
return
|
|
|
|
}
|
2024-10-26 21:19:11 +02:00
|
|
|
w.WriteHeader(http.StatusNoContent)
|
2024-10-26 15:03:14 +02:00
|
|
|
}
|