Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions internal/db/query/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 11 additions & 19 deletions internal/db/query/users.sql_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions internal/db/sql/users.sql
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ RETURNING *;
UPDATE users
SET name = $1,
email = $2,
role = $3,
email_verified = $4
WHERE id = $5
role = $3
WHERE id = $4
RETURNING *;

-- name: DeleteUser :exec
Expand Down
222 changes: 219 additions & 3 deletions internal/users/handler.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package users

import (
"github.com/gorilla/mux"
"net/http"
"strconv"
"time"

"github.com/aveloper/blog/internal/db/query"
Expand All @@ -24,6 +26,91 @@ func NewHandler(log *zap.Logger, reader *request.Reader, jsonWriter *response.JS
return &Handler{log: log, reader: reader, jsonWriter: jsonWriter, repository: repository}
}

func (h *Handler) getUser() http.HandlerFunc {
// TODO: Add better password validation(verify for special characters, number etc.

type Response struct {
ID int32 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Role string `json:"role"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

return func(w http.ResponseWriter, r *http.Request) {

params := mux.Vars(r)
id, err := strconv.Atoi(params["id"])
if err != nil {
h.log.Error("ID should be int type", zap.Error(err))
h.jsonWriter.BadRequest(w, r, &UserNotFound{})
return
}


user, err := h.repository.GetUser(r.Context(), int32(id))
if err != nil {
// TODO: Handle user constraint errors separately
h.log.Error("Failed get the user from DB", zap.Error(err))
h.jsonWriter.BadRequest(w, r, &UserNotFound{ID: int32(id)})
return
}

resp := &Response{
ID: user.ID,
Name: user.Name,
Email: user.Email,
Role: string(user.Role),
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}


h.jsonWriter.Ok(w, r, resp)
}
}

func (h *Handler) getAllUser() http.HandlerFunc {
type Response struct {
ID int32 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Role string `json:"role"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

return func(w http.ResponseWriter, r *http.Request) {
// FIXME: Hash password before saving
users, err := h.repository.GetAllUsers(r.Context())
if err != nil {
// TODO: Handle user constraint errors separately
h.log.Error("Failed get all the user from DB", zap.Error(err))
h.jsonWriter.BadRequest(w, r, &UserNotFound{})
return
}

resp := make([]Response, 0)

for _, user := range users {
r := Response{
ID: user.ID,
Name: user.Name,
Email: user.Email,
Role: string(user.Role),
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}

resp = append(resp, r)
}

h.jsonWriter.Ok(w, r, resp)
}
}


func (h *Handler) addUser() http.HandlerFunc {
// TODO: Add better password validation(verify for special characters, number etc.
type Request struct {
Expand All @@ -38,7 +125,6 @@ func (h *Handler) addUser() http.HandlerFunc {
Name string `json:"name"`
Email string `json:"email"`
Role string `json:"role"`
EmailVerified bool `json:"email_verified"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Expand Down Expand Up @@ -70,13 +156,143 @@ func (h *Handler) addUser() http.HandlerFunc {
Name: user.Name,
Email: user.Email,
Role: string(user.Role),
EmailVerified: user.EmailVerified,
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}

// TODO: Send verification Email

h.jsonWriter.Ok(w, r, resp)
}
}

func (h *Handler) updateUser() http.HandlerFunc{
type Request struct {
ID int32 `json:"id" validate:"required"`
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
Role string `json:"role" validate:"required,oneof=admin editor author contributor"`
}

type Response struct {
ID int32 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Role string `json:"role"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

return func(w http.ResponseWriter, r *http.Request) {
req := &Request{}

ok := h.reader.ReadJSONAndValidate(w, r, req)
if !ok {
return
}

user, err := h.repository.UpdateUser(r.Context(), query.UpdateUserParams{
ID: req.ID,
Name: req.Name,
Email: req.Email,
Role: query.UserRole(req.Role),
})
if err != nil {
// TODO: Handle user constraint errors separately
h.log.Error("Failed adding user to DB", zap.Error(err))
h.jsonWriter.DefaultError(w, r)
return
}

resp := &Response{
ID: user.ID,
Name: user.Name,
Email: user.Email,
Role: string(user.Role),
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}


h.jsonWriter.Ok(w, r, resp)
}
}

func (h *Handler) updateUserPassword() http.HandlerFunc{
type Request struct {
ID int32 `json:"id" validate:"required"`
Password string `json:"password" validate:"required,gte=8"`
}

type Response struct {
ID int32 `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
Role string `json:"role"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

return func(w http.ResponseWriter, r *http.Request) {
req := &Request{}

ok := h.reader.ReadJSONAndValidate(w, r, req)
if !ok {
return
}

user, err := h.repository.UpdateUserPassword(r.Context(), query.UpdateUserPasswordParams{
ID: req.ID,
Password: req.Password,
})
if err != nil {
// TODO: Handle user constraint errors separately
h.log.Error("Failed updating user password to DB", zap.Error(err))
h.jsonWriter.DefaultError(w, r)
return
}

resp := &Response{
ID: user.ID,
Name: user.Name,
Email: user.Email,
Role: string(user.Role),
CreatedAt: user.CreatedAt,
UpdatedAt: user.UpdatedAt,
}


h.jsonWriter.Ok(w, r, resp)
}
}

func (h *Handler) DeleteUser() http.HandlerFunc {
type Request struct {
ID int32 `json:"id" validate:"required"`
}

type Response struct {
Message string `json:"message"`
}

return func(w http.ResponseWriter, r *http.Request) {
req := &Request{}

ok := h.reader.ReadJSONAndValidate(w, r, req)
if !ok {
return
}

err := h.repository.DeleteUser(r.Context(), req.ID)
if err != nil {
h.log.Error("Failed to delete user from DB", zap.Error(err))
h.jsonWriter.DefaultError(w, r)
return
}

resp := &Response{
Message: "User successfully deleted",
}

h.jsonWriter.Ok(w, r, resp)
}
}
Loading