From bd9f1369a017589976231756ba512e57ced03a79 Mon Sep 17 00:00:00 2001 From: lbenedar Date: Thu, 19 Mar 2026 17:21:50 +0300 Subject: [PATCH] ch13.3 --- cmd/api/routes.go | 2 ++ cmd/api/users.go | 59 ++++++++++++++++++++++++++++++++++++++++++ internal/data/users.go | 6 ++--- 3 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 cmd/api/users.go diff --git a/cmd/api/routes.go b/cmd/api/routes.go index 28b6270..5410c5e 100644 --- a/cmd/api/routes.go +++ b/cmd/api/routes.go @@ -20,5 +20,7 @@ func (app *application) routes() http.Handler { router.HandlerFunc(http.MethodPatch, "/v1/movies/:id", app.updateMovieHandler) router.HandlerFunc(http.MethodDelete, "/v1/movies/:id", app.deleteMovieHandler) + router.HandlerFunc(http.MethodPost, "/v1/users", app.registerUserHandler) + return app.recoverPanic(app.rateLimit(router)) } diff --git a/cmd/api/users.go b/cmd/api/users.go new file mode 100644 index 0000000..2fa3992 --- /dev/null +++ b/cmd/api/users.go @@ -0,0 +1,59 @@ +package main + +import ( + "errors" + "net/http" + + "gitea.local.lab/Lbenedar/greenlight/internal/data" + "gitea.local.lab/Lbenedar/greenlight/internal/validator" +) + +func (app *application) registerUserHandler(w http.ResponseWriter, r *http.Request) { + var input struct { + Name string `json:"name"` + Email string `json:"email"` + Password string `json:"password"` + } + + err := app.readJSON(w, r, &input) + if err != nil { + app.badRequestResponse(w, r, err) + return + } + + user := &data.User{ + Name: input.Name, + Email: input.Email, + Activated: false, + } + + err = user.Password.Set(input.Password) + if err != nil { + app.serverErrorResponse(w, r, err) + return + } + + v := validator.New() + + if data.ValidateUser(v, user); !v.Valid() { + app.failedValidationResponse(w, r, v.Errors) + return + } + + err = app.models.Users.Insert(user) + if err != nil { + switch { + case errors.Is(err, data.ErrDuplicateEmail): + v.AddError("email", "a user with this email address already exists") + app.failedValidationResponse(w, r, v.Errors) + default: + app.serverErrorResponse(w, r, err) + } + return + } + + err = app.writeJSON(w, http.StatusCreated, envelope{"user": user}, nil) + if err != nil { + app.serverErrorResponse(w, r, err) + } +} diff --git a/internal/data/users.go b/internal/data/users.go index 7779022..d203e98 100644 --- a/internal/data/users.go +++ b/internal/data/users.go @@ -75,7 +75,7 @@ func ValidateUser(v *validator.Validator, user *User) { ValidatePasswordPlaintext(v, *user.Password.plaintext) } - if user.Password.hash != nil { + if user.Password.hash == nil { panic("missing password hash for user") } } @@ -97,7 +97,7 @@ func (m UserModel) Insert(user *User) error { err := m.DB.QueryRowContext(ctx, query, args...).Scan(&user.ID, &user.CreatedAt, &user.Version) if err != nil { switch { - case err.Error() == `pq: duplicate key value violates unique constraint "users_email_key"`: + case err.Error() == `pq: duplicate key value violates unique constraint "users_email_key" (23505)`: return ErrDuplicateEmail default: return err @@ -161,7 +161,7 @@ func (m UserModel) Update(user *User) error { err := m.DB.QueryRowContext(ctx, query, args...).Scan(&user.Version) if err != nil { switch { - case err.Error() == `pq: duplicate key value violates unique constraint "users_email_key"`: + case err.Error() == `pq: duplicate key value violates unique constraint "users_email_key" (23505)`: return ErrDuplicateEmail default: return err