Add user management
This commit is contained in:
@@ -0,0 +1,269 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"log"
|
||||
"quay/app/models"
|
||||
"quay/app/repository"
|
||||
"quay/internal/security"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v3"
|
||||
)
|
||||
|
||||
type UserHandler struct {
|
||||
Repo repository.UserRepository
|
||||
}
|
||||
|
||||
func NewUserHandler(repo repository.UserRepository) *UserHandler {
|
||||
return &UserHandler{Repo: repo}
|
||||
}
|
||||
|
||||
func (h *UserHandler) GetAllUsers(c fiber.Ctx) error {
|
||||
users, err := h.Repo.GetAllUsers()
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return c.Status(fiber.StatusNotFound).JSON(&models.APIError{
|
||||
Message: "User not found",
|
||||
})
|
||||
}
|
||||
log.Println("Error getting user: ", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(&models.APIError{
|
||||
Message: "Unexpected error while getting site",
|
||||
})
|
||||
}
|
||||
|
||||
if users == nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(&models.APIError{
|
||||
Message: "User not found",
|
||||
})
|
||||
}
|
||||
|
||||
for i := range users {
|
||||
users[i].HashedPassword = ""
|
||||
}
|
||||
|
||||
return c.JSON(users)
|
||||
}
|
||||
|
||||
// GetUserById godoc
|
||||
// @Summary Get user by ID
|
||||
// @Description Get a single user by its ID
|
||||
// @Tags Users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "User ID"
|
||||
// @Success 200 {object} models.User
|
||||
// @Failure 404 {object} models.APIError
|
||||
// @Failure 500 {object} models.APIError
|
||||
func (h *UserHandler) GetUserById(c fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
user, err := h.Repo.GetUserById(id)
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return c.Status(fiber.StatusNotFound).JSON(&models.APIError{
|
||||
Message: "User not found",
|
||||
})
|
||||
}
|
||||
log.Println("Error getting user: ", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(&models.APIError{
|
||||
Message: "Unexpected error while getting site",
|
||||
})
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(&models.APIError{
|
||||
Message: "User not found",
|
||||
})
|
||||
}
|
||||
|
||||
user.HashedPassword = ""
|
||||
|
||||
return c.JSON(user)
|
||||
}
|
||||
|
||||
// GetUserByName godoc
|
||||
// @Summary Get user by Name
|
||||
// @Description Get a single user by its Name
|
||||
// @Tags Users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param name path string true "User Name"
|
||||
// @Success 200 {object} models.User
|
||||
// @Failure 404 {object} models.APIError
|
||||
// @Failure 500 {object} models.APIError
|
||||
func (h *UserHandler) GetUserByName(c fiber.Ctx) error {
|
||||
name := c.Params("name")
|
||||
|
||||
user, err := h.Repo.GetUserByName(name)
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return c.Status(fiber.StatusNotFound).JSON(&models.APIError{
|
||||
Message: "User not found",
|
||||
})
|
||||
}
|
||||
log.Println("Error getting user: ", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(&models.APIError{
|
||||
Message: "Unexpected error while getting site",
|
||||
})
|
||||
}
|
||||
|
||||
if user == nil {
|
||||
return c.Status(fiber.StatusNotFound).JSON(&models.APIError{
|
||||
Message: "User not found",
|
||||
})
|
||||
}
|
||||
|
||||
user.HashedPassword = ""
|
||||
|
||||
return c.JSON(user)
|
||||
}
|
||||
|
||||
// CreateUser godoc
|
||||
// @Summary Create a new user
|
||||
// @Description Create a new user with the provided name, role, and password
|
||||
// @Tags Users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} models.User
|
||||
// @Failure 400 {object} models.APIError
|
||||
// @Failure 409 {object} models.APIError
|
||||
// @Failure 500 {object} models.APIError
|
||||
func (h *UserHandler) CreateUser(c fiber.Ctx) error {
|
||||
var createUserRequest models.CreateUserRequest
|
||||
|
||||
if err := c.Bind().Body(&createUserRequest); err != nil {
|
||||
log.Println("Error parsing body: ", err)
|
||||
return c.Status(fiber.StatusBadRequest).JSON(&models.APIError{
|
||||
Message: "Invalid request body",
|
||||
})
|
||||
}
|
||||
|
||||
if err := models.ValidateCreateUserRequest(&createUserRequest); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(&models.APIError{
|
||||
Message: "Invalid request body: " + err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
hashedPassword, err := security.HashPassword(createUserRequest.Password)
|
||||
if err != nil {
|
||||
log.Println("Error hashing password: ", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(&models.APIError{
|
||||
Message: "Unexpected error while hashing password",
|
||||
})
|
||||
}
|
||||
|
||||
user := models.User{
|
||||
Name: createUserRequest.Name,
|
||||
Role: createUserRequest.Role,
|
||||
HashedPassword: hashedPassword,
|
||||
CreatedAt: time.Now().UTC().Format(time.DateTime),
|
||||
}
|
||||
|
||||
err = h.Repo.CreateUser(&user)
|
||||
if err != nil {
|
||||
log.Println("Error creating user: ", err)
|
||||
if errors.Is(err, repository.ErrUserAlreadyExists) {
|
||||
return c.Status(fiber.StatusConflict).JSON(&models.APIError{
|
||||
Message: "User name already taken",
|
||||
})
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(&models.APIError{
|
||||
Message: "Unexpected error while creating user",
|
||||
})
|
||||
}
|
||||
|
||||
return c.JSON(user)
|
||||
}
|
||||
|
||||
// UpdateUser godoc
|
||||
// @Summary Update an existing user
|
||||
// @Description Update an existing user with the provided name, role, and password
|
||||
// @Tags Users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "User ID"
|
||||
// @Success 200 {object} models.User
|
||||
// @Failure 400 {object} models.APIError
|
||||
// @Failure 404 {object} models.APIError
|
||||
// @Failure 409 {object} models.APIError
|
||||
// @Failure 500 {object} models.APIError
|
||||
func (h *UserHandler) UpdateUser(c fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
var updateUserRequest models.UpdateUserRequest
|
||||
|
||||
if err := c.Bind().Body(&updateUserRequest); err != nil {
|
||||
log.Println("Error parsing body: ", err)
|
||||
return c.Status(fiber.StatusBadRequest).JSON(&models.APIError{
|
||||
Message: "Invalid request body",
|
||||
})
|
||||
}
|
||||
|
||||
if err := models.ValidateUpdateUserRequest(&updateUserRequest); err != nil {
|
||||
return c.Status(fiber.StatusBadRequest).JSON(&models.APIError{
|
||||
Message: "Invalid request body: " + err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
user := models.User{
|
||||
ID: id,
|
||||
Name: updateUserRequest.Name,
|
||||
Role: updateUserRequest.Role,
|
||||
}
|
||||
|
||||
err := h.Repo.UpdateUser(&user)
|
||||
if err != nil {
|
||||
log.Println("Error updating user: ", err)
|
||||
if errors.Is(err, repository.ErrUserAlreadyExists) {
|
||||
return c.Status(fiber.StatusConflict).JSON(&models.APIError{
|
||||
Message: "User name already taken",
|
||||
})
|
||||
}
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(&models.APIError{
|
||||
Message: "Unexpected error while updating user",
|
||||
})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
|
||||
// DeleteUser godoc
|
||||
// @Summary Delete a user
|
||||
// @Description Delete a user by its ID
|
||||
// @Tags Users
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "User ID"
|
||||
// @Success 204 "No Content"
|
||||
// @Failure 404 {object} models.APIError
|
||||
// @Failure 500 {object} models.APIError
|
||||
func (h *UserHandler) DeleteUser(c fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
|
||||
if _, err := h.Repo.GetUserById(id); err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return c.Status(fiber.StatusNotFound).JSON(&models.APIError{
|
||||
Message: "User not found",
|
||||
})
|
||||
}
|
||||
log.Println("Error checking user before delete: ", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(&models.APIError{
|
||||
Message: "Unexpected error while deleting user",
|
||||
})
|
||||
}
|
||||
|
||||
err := h.Repo.DeleteUser(id)
|
||||
if err != nil {
|
||||
log.Println("Error deleting user: ", err)
|
||||
return c.Status(fiber.StatusInternalServerError).JSON(&models.APIError{
|
||||
Message: "Unexpected error while deleting user",
|
||||
})
|
||||
}
|
||||
|
||||
return c.SendStatus(fiber.StatusNoContent)
|
||||
}
|
||||
Reference in New Issue
Block a user