first commit
This commit is contained in:
315
internal/modules/user/handler.go
Normal file
315
internal/modules/user/handler.go
Normal file
@@ -0,0 +1,315 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
_ "image/gif"
|
||||
_ "image/jpeg"
|
||||
"image/png"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"cardverse/internal/pkg/response"
|
||||
"cardverse/internal/pkg/validator"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
service Service
|
||||
}
|
||||
|
||||
func NewHandler(service Service) *Handler {
|
||||
return &Handler{service: service}
|
||||
}
|
||||
|
||||
func (h *Handler) GetProfile(c *gin.Context) {
|
||||
userIDVal, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, http.StatusUnauthorized, "autentikasi diperlukan", nil)
|
||||
return
|
||||
}
|
||||
userID := userIDVal.(uint)
|
||||
|
||||
u, err := h.service.GetByID(userID)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, http.StatusOK, "berhasil mengambil profil user", ToUserResponse(*u))
|
||||
}
|
||||
|
||||
func (h *Handler) UpdateProfile(c *gin.Context) {
|
||||
userIDVal, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, http.StatusUnauthorized, "autentikasi diperlukan", nil)
|
||||
return
|
||||
}
|
||||
userID := userIDVal.(uint)
|
||||
|
||||
var req UpdateProfileRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "input tidak valid", validator.TranslateError(err))
|
||||
return
|
||||
}
|
||||
|
||||
updatedUser, err := h.service.UpdateProfile(userID, req)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, "gagal mengupdate profil", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, http.StatusOK, "profil berhasil diupdate", ToUserResponse(*updatedUser))
|
||||
}
|
||||
|
||||
func (h *Handler) UploadAvatar(c *gin.Context) {
|
||||
userIDVal, exists := c.Get("user_id")
|
||||
if !exists {
|
||||
response.Error(c, http.StatusUnauthorized, "autentikasi diperlukan", nil)
|
||||
return
|
||||
}
|
||||
userID := userIDVal.(uint)
|
||||
|
||||
fileHeader, err := c.FormFile("avatar")
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "file avatar wajib diunggah (form field: avatar)", nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Batas ukuran file 5 MB
|
||||
if fileHeader.Size > 5*1024*1024 {
|
||||
response.Error(c, http.StatusBadRequest, "ukuran file maksimal 5MB", nil)
|
||||
return
|
||||
}
|
||||
|
||||
srcFile, err := fileHeader.Open()
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, "gagal membaca file avatar", err.Error())
|
||||
return
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
// Dekode gambar (support JPG, JPEG, PNG, GIF)
|
||||
img, _, err := image.Decode(srcFile)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "file yang diunggah bukan format gambar yang valid", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// Simpan ke direktori: ./public/images/avatars
|
||||
uploadDir := "./public/images/avatars"
|
||||
if err := os.MkdirAll(uploadDir, os.ModePerm); err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, "gagal membuat direktori penyimpanan avatar", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
filename := fmt.Sprintf("avatar_%d_%d.png", userID, time.Now().UnixNano())
|
||||
filepathDst := filepath.Join(uploadDir, filename)
|
||||
|
||||
out, err := os.Create(filepathDst)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, "gagal membuat file avatar", err.Error())
|
||||
return
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
// Encode & kompresi ke format PNG
|
||||
encoder := png.Encoder{CompressionLevel: png.BestCompression}
|
||||
if err := encoder.Encode(out, img); err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, "gagal mengompresi gambar ke format PNG", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
avatarURL := fmt.Sprintf("/images/avatars/%s", filename)
|
||||
updatedUser, err := h.service.UpdateAvatar(userID, avatarURL)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, "gagal memperbarui avatar user", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, http.StatusOK, "avatar berhasil diunggah", ToUserResponse(*updatedUser))
|
||||
}
|
||||
|
||||
func (h *Handler) Create(c *gin.Context) {
|
||||
creatorID := getContextUserID(c)
|
||||
|
||||
var req CreateUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "input tidak valid", validator.TranslateError(err))
|
||||
return
|
||||
}
|
||||
|
||||
newUser, err := h.service.Create(creatorID, req)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrEmailTaken) {
|
||||
response.Error(c, http.StatusConflict, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
if errors.Is(err, ErrForbiddenRoleCreation) {
|
||||
response.Error(c, http.StatusForbidden, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
response.Error(c, http.StatusInternalServerError, "gagal membuat user", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, http.StatusCreated, "user berhasil dibuat", ToUserResponse(*newUser))
|
||||
}
|
||||
|
||||
func (h *Handler) GetAll(c *gin.Context) {
|
||||
var query ListUserQuery
|
||||
if err := c.ShouldBindQuery(&query); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "query parameter tidak valid", validator.TranslateError(err))
|
||||
return
|
||||
}
|
||||
|
||||
users, total, err := h.service.GetAllPaginated(query)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusInternalServerError, "gagal mengambil data user", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
pagination := response.NewPagination(query.Page, query.Limit, total)
|
||||
response.SuccessWithPagination(c, http.StatusOK, "berhasil mengambil data user", ToUserResponseList(users), pagination)
|
||||
}
|
||||
|
||||
func (h *Handler) GetByID(c *gin.Context) {
|
||||
id, err := parseID(c)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "id tidak valid", []validator.FieldError{
|
||||
{Field: "id", Message: "id harus berupa angka"},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
u, err := h.service.GetByID(id)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, http.StatusOK, "berhasil mengambil data user", ToUserResponse(*u))
|
||||
}
|
||||
|
||||
func (h *Handler) Update(c *gin.Context) {
|
||||
modifierID := getContextUserIDValue(c)
|
||||
|
||||
id, err := parseID(c)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "id tidak valid", []validator.FieldError{
|
||||
{Field: "id", Message: "id harus berupa angka"},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateUserRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "input tidak valid", validator.TranslateError(err))
|
||||
return
|
||||
}
|
||||
|
||||
updatedUser, err := h.service.Update(modifierID, id, req)
|
||||
if err != nil {
|
||||
if errors.Is(err, ErrEmailTaken) {
|
||||
response.Error(c, http.StatusConflict, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
if errors.Is(err, ErrForbiddenRoleCreation) {
|
||||
response.Error(c, http.StatusForbidden, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
response.Error(c, http.StatusNotFound, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, http.StatusOK, "user berhasil diupdate", ToUserResponse(*updatedUser))
|
||||
}
|
||||
|
||||
func (h *Handler) Suspend(c *gin.Context) {
|
||||
modifierID := getContextUserIDValue(c)
|
||||
|
||||
id, err := parseID(c)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "id tidak valid", []validator.FieldError{
|
||||
{Field: "id", Message: "id harus berupa angka"},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
updatedUser, err := h.service.SuspendUser(modifierID, id)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, http.StatusOK, "user berhasil disuspensi", ToUserResponse(*updatedUser))
|
||||
}
|
||||
|
||||
func (h *Handler) Unsuspend(c *gin.Context) {
|
||||
modifierID := getContextUserIDValue(c)
|
||||
|
||||
id, err := parseID(c)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "id tidak valid", []validator.FieldError{
|
||||
{Field: "id", Message: "id harus berupa angka"},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
updatedUser, err := h.service.UnsuspendUser(modifierID, id)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusNotFound, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, http.StatusOK, "suspensi user berhasil dicabut", ToUserResponse(*updatedUser))
|
||||
}
|
||||
|
||||
func (h *Handler) Delete(c *gin.Context) {
|
||||
id, err := parseID(c)
|
||||
if err != nil {
|
||||
response.Error(c, http.StatusBadRequest, "id tidak valid", []validator.FieldError{
|
||||
{Field: "id", Message: "id harus berupa angka"},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.service.Delete(id); err != nil {
|
||||
response.Error(c, http.StatusNotFound, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
|
||||
response.Success(c, http.StatusOK, "user berhasil dihapus", nil)
|
||||
}
|
||||
|
||||
func parseID(c *gin.Context) (uint, error) {
|
||||
idParam := c.Param("id")
|
||||
id, err := strconv.ParseUint(idParam, 10, 64)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return uint(id), nil
|
||||
}
|
||||
|
||||
func getContextUserID(c *gin.Context) *uint {
|
||||
if val, exists := c.Get("user_id"); exists {
|
||||
if userID, ok := val.(uint); ok {
|
||||
return &userID
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getContextUserIDValue(c *gin.Context) uint {
|
||||
if val, exists := c.Get("user_id"); exists {
|
||||
if userID, ok := val.(uint); ok {
|
||||
return userID
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
Reference in New Issue
Block a user