fix&refact: improve code and add field in trash c and trash cdetail
This commit is contained in:
parent
9a2481be09
commit
9f1a4eb8fa
|
@ -4,13 +4,15 @@ import "strings"
|
||||||
|
|
||||||
type RequestTrashCategoryDTO struct {
|
type RequestTrashCategoryDTO struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
Icon string `json:"icon"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseTrashCategoryDTO struct {
|
type ResponseTrashCategoryDTO struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
CreatedAt string `json:"createdAt"`
|
Icon string `json:"icon"`
|
||||||
UpdatedAt string `json:"updatedAt"`
|
CreatedAt string `json:"createdAt"`
|
||||||
|
UpdatedAt string `json:"updatedAt"`
|
||||||
Details []ResponseTrashDetailDTO `json:"details,omitempty"`
|
Details []ResponseTrashDetailDTO `json:"details,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package dto
|
package dto
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"rijig/utils"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,13 +18,13 @@ type UserResponseDTO struct {
|
||||||
UpdatedAt string `json:"updatedAt"`
|
UpdatedAt string `json:"updatedAt"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateUserDTO struct {
|
type RequestUserDTO struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *UpdateUserDTO) Validate() (map[string][]string, bool) {
|
func (r *RequestUserDTO) Validate() (map[string][]string, bool) {
|
||||||
errors := make(map[string][]string)
|
errors := make(map[string][]string)
|
||||||
|
|
||||||
if strings.TrimSpace(r.Name) == "" {
|
if strings.TrimSpace(r.Name) == "" {
|
||||||
|
@ -33,10 +33,14 @@ func (r *UpdateUserDTO) Validate() (map[string][]string, bool) {
|
||||||
|
|
||||||
if strings.TrimSpace(r.Phone) == "" {
|
if strings.TrimSpace(r.Phone) == "" {
|
||||||
errors["phone"] = append(errors["phone"], "Phone number is required")
|
errors["phone"] = append(errors["phone"], "Phone number is required")
|
||||||
} else if !IsValidPhoneNumber(r.Phone) {
|
} else if !utils.IsValidPhoneNumber(r.Phone) {
|
||||||
errors["phone"] = append(errors["phone"], "Invalid phone number format. Use +62 followed by 9-13 digits")
|
errors["phone"] = append(errors["phone"], "Invalid phone number format. Use +62 followed by 9-13 digits")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.TrimSpace(r.Email) != "" && !utils.IsValidEmail(r.Email) {
|
||||||
|
errors["email"] = append(errors["email"], "Invalid email format")
|
||||||
|
}
|
||||||
|
|
||||||
if len(errors) > 0 {
|
if len(errors) > 0 {
|
||||||
return errors, false
|
return errors, false
|
||||||
}
|
}
|
||||||
|
@ -44,18 +48,6 @@ func (r *UpdateUserDTO) Validate() (map[string][]string, bool) {
|
||||||
return nil, true
|
return nil, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsUpdateValidPhoneNumber(phone string) bool {
|
|
||||||
|
|
||||||
re := regexp.MustCompile(`^\+62\d{9,13}$`)
|
|
||||||
return re.MatchString(phone)
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsUPdateValidEmail(email string) bool {
|
|
||||||
|
|
||||||
re := regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
|
|
||||||
return re.MatchString(email)
|
|
||||||
}
|
|
||||||
|
|
||||||
type UpdatePasswordDTO struct {
|
type UpdatePasswordDTO struct {
|
||||||
OldPassword string `json:"old_password"`
|
OldPassword string `json:"old_password"`
|
||||||
NewPassword string `json:"new_password"`
|
NewPassword string `json:"new_password"`
|
||||||
|
@ -71,8 +63,8 @@ func (u *UpdatePasswordDTO) Validate() (map[string][]string, bool) {
|
||||||
|
|
||||||
if u.NewPassword == "" {
|
if u.NewPassword == "" {
|
||||||
errors["new_password"] = append(errors["new_password"], "New password is required")
|
errors["new_password"] = append(errors["new_password"], "New password is required")
|
||||||
} else if len(u.NewPassword) < 8 {
|
} else if !utils.IsValidPassword(u.NewPassword) {
|
||||||
errors["new_password"] = append(errors["new_password"], "Password must be at least 8 characters long")
|
errors["new_password"] = append(errors["new_password"], "Password must contain at least one uppercase letter, one digit, and one special character")
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.ConfirmNewPassword == "" {
|
if u.ConfirmNewPassword == "" {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package handler
|
package handler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"log"
|
||||||
"rijig/dto"
|
"rijig/dto"
|
||||||
"rijig/internal/services"
|
"rijig/internal/services"
|
||||||
"rijig/utils"
|
"rijig/utils"
|
||||||
|
@ -22,7 +23,13 @@ func (h *TrashHandler) CreateCategory(c *fiber.Ctx) error {
|
||||||
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
|
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
|
||||||
}
|
}
|
||||||
|
|
||||||
categoryResponse, err := h.TrashService.CreateCategory(request)
|
iconTrash, err := c.FormFile("icon")
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error retrieving card photo from request: %v", err)
|
||||||
|
return utils.ErrorResponse(c, "Card photo is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
categoryResponse, err := h.TrashService.CreateCategory(request, iconTrash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to create category: "+err.Error())
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Failed to create category: "+err.Error())
|
||||||
}
|
}
|
||||||
|
@ -84,7 +91,13 @@ func (h *TrashHandler) UpdateCategory(c *fiber.Ctx) error {
|
||||||
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid request body"}})
|
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid request body"}})
|
||||||
}
|
}
|
||||||
|
|
||||||
updatedCategory, err := h.TrashService.UpdateCategory(id, request)
|
iconTrash, err := c.FormFile("icon")
|
||||||
|
if err != nil && err.Error() != "File not found" {
|
||||||
|
log.Printf("Error retrieving icon trash from request: %v", err)
|
||||||
|
return utils.ErrorResponse(c, "icon trash is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedCategory, err := h.TrashService.UpdateCategory(id, request, iconTrash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Error updating category: "+err.Error())
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, "Error updating category: "+err.Error())
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,138 +4,98 @@ import (
|
||||||
"rijig/dto"
|
"rijig/dto"
|
||||||
"rijig/internal/services"
|
"rijig/internal/services"
|
||||||
"rijig/utils"
|
"rijig/utils"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserProfileHandler struct {
|
type UserHandler struct {
|
||||||
UserProfileService services.UserProfileService
|
userService services.UserService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserProfileHandler(userProfileService services.UserProfileService) *UserProfileHandler {
|
func NewUserHandler(userService services.UserService) *UserHandler {
|
||||||
return &UserProfileHandler{UserProfileService: userProfileService}
|
return &UserHandler{userService: userService}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UserProfileHandler) GetUserProfile(c *fiber.Ctx) error {
|
func (h *UserHandler) UpdateUserAvatarHandler(c *fiber.Ctx) error {
|
||||||
|
|
||||||
|
userID := c.Locals("userID").(string)
|
||||||
|
|
||||||
|
avatar, err := c.FormFile("avatar")
|
||||||
|
if err != nil {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusBadRequest, "No avatar file provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
updatedUser, err := h.userService.UpdateUserAvatar(userID, avatar)
|
||||||
|
if err != nil {
|
||||||
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return utils.SuccessResponse(c, updatedUser, "Avatar updated successfully")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *UserHandler) GetUserByIDHandler(c *fiber.Ctx) error {
|
||||||
|
// userID := c.Params("id")
|
||||||
userID, ok := c.Locals("userID").(string)
|
userID, ok := c.Locals("userID").(string)
|
||||||
if !ok || userID == "" {
|
if !ok || userID == "" {
|
||||||
return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found")
|
return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
userProfile, err := h.UserProfileService.GetUserProfile(userID)
|
user, err := h.userService.GetUserByID(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return utils.GenericResponse(c, fiber.StatusNotFound, err.Error())
|
return utils.GenericResponse(c, fiber.StatusNotFound, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.SuccessResponse(c, userProfile, "User profile retrieved successfully")
|
return utils.SuccessResponse(c, user, "User retrieved successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UserProfileHandler) GetUserProfileById(c *fiber.Ctx) error {
|
func (h *UserHandler) GetAllUsersHandler(c *fiber.Ctx) error {
|
||||||
userID := c.Params("userid")
|
|
||||||
if userID == "" {
|
page := 1
|
||||||
return utils.ValidationErrorResponse(c, map[string][]string{"userid": {"user ID is required"}})
|
limit := 10
|
||||||
|
|
||||||
|
if p := c.Query("page"); p != "" {
|
||||||
|
page, _ = strconv.Atoi(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// userID, ok := c.Locals("userID").(string)
|
if l := c.Query("limit"); l != "" {
|
||||||
// if !ok || userID == "" {
|
limit, _ = strconv.Atoi(l)
|
||||||
// return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found")
|
|
||||||
// }
|
|
||||||
|
|
||||||
userProfile, err := h.UserProfileService.GetUserProfile(userID)
|
|
||||||
if err != nil {
|
|
||||||
return utils.GenericResponse(c, fiber.StatusNotFound, err.Error())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.SuccessResponse(c, userProfile, "User profile retrieved successfully")
|
users, err := h.userService.GetAllUsers(page, limit)
|
||||||
}
|
|
||||||
|
|
||||||
func (h *UserProfileHandler) GetAllUsers(c *fiber.Ctx) error {
|
|
||||||
users, err := h.UserProfileService.GetAllUsers()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.SuccessResponse(c, users, "All users retrieved successfully")
|
return utils.PaginatedResponse(c, users, page, limit, len(users), "Users retrieved successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UserProfileHandler) GetUsersByRoleID(c *fiber.Ctx) error {
|
func (h *UserHandler) UpdateUserHandler(c *fiber.Ctx) error {
|
||||||
roleID := c.Params("roleid")
|
var request dto.RequestUserDTO
|
||||||
if roleID == "" {
|
if err := c.BodyParser(&request); err != nil {
|
||||||
return utils.ValidationErrorResponse(c, map[string][]string{"roleId": {"Role ID is required"}})
|
return utils.GenericResponse(c, fiber.StatusBadRequest, "Invalid request body")
|
||||||
}
|
}
|
||||||
|
|
||||||
users, err := h.UserProfileService.GetUsersByRoleID(roleID)
|
userID := c.Locals("userID").(string)
|
||||||
|
updatedUser, err := h.userService.UpdateUser(userID, &request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.SuccessResponse(c, users, "Users retrieved successfully")
|
return utils.SuccessResponse(c, updatedUser, "User profile updated successfully")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UserProfileHandler) UpdateUserProfile(c *fiber.Ctx) error {
|
func (h *UserHandler) UpdateUserPasswordHandler(c *fiber.Ctx) error {
|
||||||
var updateData dto.UpdateUserDTO
|
var request dto.UpdatePasswordDTO
|
||||||
if err := c.BodyParser(&updateData); err != nil {
|
if err := c.BodyParser(&request); err != nil {
|
||||||
return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
|
return utils.GenericResponse(c, fiber.StatusBadRequest, "Invalid request body")
|
||||||
}
|
}
|
||||||
|
|
||||||
userID, ok := c.Locals("userID").(string)
|
userID := c.Locals("userID").(string)
|
||||||
if !ok || userID == "" {
|
err := h.userService.UpdateUserPassword(userID, request.OldPassword, request.NewPassword, request.ConfirmNewPassword)
|
||||||
return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
errors, valid := updateData.Validate()
|
|
||||||
if !valid {
|
|
||||||
return utils.ValidationErrorResponse(c, errors)
|
|
||||||
}
|
|
||||||
|
|
||||||
userResponse, err := h.UserProfileService.UpdateUserProfile(userID, updateData)
|
|
||||||
if err != nil {
|
|
||||||
return utils.GenericResponse(c, fiber.StatusConflict, err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return utils.SuccessResponse(c, userResponse, "User profile updated successfully")
|
|
||||||
}
|
|
||||||
|
|
||||||
// func (h *UserProfileHandler) UpdateUserPassword(c *fiber.Ctx) error {
|
|
||||||
// var passwordData dto.UpdatePasswordDTO
|
|
||||||
// if err := c.BodyParser(&passwordData); err != nil {
|
|
||||||
// return utils.ValidationErrorResponse(c, map[string][]string{"body": {"Invalid body"}})
|
|
||||||
// }
|
|
||||||
|
|
||||||
// userID, ok := c.Locals("userID").(string)
|
|
||||||
// if !ok || userID == "" {
|
|
||||||
// return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// errors, valid := passwordData.Validate()
|
|
||||||
// if !valid {
|
|
||||||
// return utils.ValidationErrorResponse(c, errors)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// message, err := h.UserProfileService.UpdateUserPassword(userID, passwordData)
|
|
||||||
// if err != nil {
|
|
||||||
// return utils.GenericResponse(c, fiber.StatusBadRequest, err.Error())
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return utils.GenericResponse(c, fiber.StatusOK, message)
|
|
||||||
// }
|
|
||||||
func (h *UserProfileHandler) UpdateUserAvatar(c *fiber.Ctx) error {
|
|
||||||
|
|
||||||
userID, ok := c.Locals("userID").(string)
|
|
||||||
if !ok || userID == "" {
|
|
||||||
return utils.GenericResponse(c, fiber.StatusUnauthorized, "Unauthorized: User session not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
file, err := c.FormFile("avatar")
|
|
||||||
if err != nil {
|
|
||||||
return utils.GenericResponse(c, fiber.StatusBadRequest, "No avatar file uploaded")
|
|
||||||
}
|
|
||||||
|
|
||||||
message, err := h.UserProfileService.UpdateUserAvatar(userID, file)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
return utils.GenericResponse(c, fiber.StatusInternalServerError, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils.GenericResponse(c, fiber.StatusOK, message)
|
return utils.SuccessResponse(c, nil, "Password updated successfully")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package repositories
|
package repositories
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
|
||||||
"rijig/model"
|
"rijig/model"
|
||||||
|
|
||||||
|
@ -16,6 +18,7 @@ type TrashRepository interface {
|
||||||
GetTrashDetailByID(id string) (*model.TrashDetail, error)
|
GetTrashDetailByID(id string) (*model.TrashDetail, error)
|
||||||
GetDetailsByCategoryID(categoryID string) ([]model.TrashDetail, error)
|
GetDetailsByCategoryID(categoryID string) ([]model.TrashDetail, error)
|
||||||
UpdateCategoryName(id string, newName string) error
|
UpdateCategoryName(id string, newName string) error
|
||||||
|
UpdateCategory(id string, updateTrashCategory *model.TrashCategory) (*model.TrashCategory, error)
|
||||||
UpdateTrashDetail(id string, description string, price float64) error
|
UpdateTrashDetail(id string, description string, price float64) error
|
||||||
DeleteCategory(id string) error
|
DeleteCategory(id string) error
|
||||||
DeleteTrashDetail(id string) error
|
DeleteTrashDetail(id string) error
|
||||||
|
@ -84,6 +87,23 @@ func (r *trashRepository) UpdateCategoryName(id string, newName string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *trashRepository) UpdateCategory(id string, updateTrashCategory *model.TrashCategory) (*model.TrashCategory, error) {
|
||||||
|
var existingtrashCtgry model.TrashCategory
|
||||||
|
if err := r.DB.Where("id = ?", id).First(&existingtrashCtgry).Error; err != nil {
|
||||||
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, fmt.Errorf("trashCategory with ID %s not found", id)
|
||||||
|
}
|
||||||
|
log.Printf("Error fetching trash category for update: %v", err)
|
||||||
|
return nil, fmt.Errorf("error fetching trash category for update: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := r.DB.Save(&existingtrashCtgry).Error; err != nil {
|
||||||
|
log.Printf("Error updating trash category: %v", err)
|
||||||
|
return nil, fmt.Errorf("failed to update trash category: %w", err)
|
||||||
|
}
|
||||||
|
return &existingtrashCtgry, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (r *trashRepository) UpdateTrashDetail(id string, description string, price float64) error {
|
func (r *trashRepository) UpdateTrashDetail(id string, description string, price float64) error {
|
||||||
if err := r.DB.Model(&model.TrashDetail{}).Where("id = ?", id).Updates(model.TrashDetail{Description: description, Price: price}).Error; err != nil {
|
if err := r.DB.Model(&model.TrashDetail{}).Where("id = ?", id).Updates(model.TrashDetail{Description: description, Price: price}).Error; err != nil {
|
||||||
return fmt.Errorf("failed to update trash detail: %v", err)
|
return fmt.Errorf("failed to update trash detail: %v", err)
|
||||||
|
|
|
@ -2,77 +2,76 @@ package repositories
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"rijig/model"
|
"rijig/model"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserProfileRepository interface {
|
type UserProfilRepository interface {
|
||||||
FindByID(userID string) (*model.User, error)
|
FindByID(userID string) (*model.User, error)
|
||||||
|
FindAll(page, limit int) ([]model.User, error)
|
||||||
Update(user *model.User) error
|
Update(user *model.User) error
|
||||||
UpdateAvatar(userID, avatarURL string) error
|
UpdateAvatar(userID, avatarURL string) error
|
||||||
|
UpdatePassword(userID string, newPassword string) error
|
||||||
FindAll() ([]model.User, error)
|
|
||||||
FindByRoleID(roleID string) ([]model.User, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type userProfileRepository struct {
|
type userProfilRepository struct {
|
||||||
DB *gorm.DB
|
DB *gorm.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserProfileRepository(db *gorm.DB) UserProfileRepository {
|
func NewUserProfilRepository(db *gorm.DB) UserProfilRepository {
|
||||||
return &userProfileRepository{DB: db}
|
return &userProfilRepository{DB: db}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *userProfileRepository) FindByID(userID string) (*model.User, error) {
|
func (r *userProfilRepository) FindByID(userID string) (*model.User, error) {
|
||||||
var user model.User
|
var user model.User
|
||||||
err := r.DB.Preload("Role").Where("id = ?", userID).First(&user).Error
|
err := r.DB.Preload("Role").Where("id = ?", userID).First(&user).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == gorm.ErrRecordNotFound {
|
if err == gorm.ErrRecordNotFound {
|
||||||
return nil, fmt.Errorf("user with ID %s not found", userID)
|
return nil, fmt.Errorf("user with ID %s not found", userID)
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, fmt.Errorf("error finding user with ID %s: %v", userID, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if user.Role == nil {
|
if user.Role == nil {
|
||||||
return nil, fmt.Errorf("role not found for this user")
|
return nil, fmt.Errorf("role not found for user ID %s", userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *userProfileRepository) Update(user *model.User) error {
|
func (r *userProfilRepository) FindAll(page, limit int) ([]model.User, error) {
|
||||||
|
var users []model.User
|
||||||
|
offset := (page - 1) * limit
|
||||||
|
err := r.DB.Preload("Role").Offset(offset).Limit(limit).Find(&users).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error finding all users: %v", err)
|
||||||
|
}
|
||||||
|
return users, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *userProfilRepository) Update(user *model.User) error {
|
||||||
err := r.DB.Save(user).Error
|
err := r.DB.Save(user).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("error updating user: %v", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *userProfileRepository) UpdateAvatar(userID, avatarURL string) error {
|
func (r *userProfilRepository) UpdateAvatar(userID, avatarURL string) error {
|
||||||
var user model.User
|
var user model.User
|
||||||
err := r.DB.Model(&user).Where("id = ?", userID).Update("avatar", avatarURL).Error
|
err := r.DB.Model(&user).Where("id = ?", userID).Update("avatar", avatarURL).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("error updating avatar for user ID %s: %v", userID, err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *userProfileRepository) FindAll() ([]model.User, error) {
|
func (r *userProfilRepository) UpdatePassword(userID string, newPassword string) error {
|
||||||
var users []model.User
|
var user model.User
|
||||||
err := r.DB.Preload("Role").Find(&users).Error
|
err := r.DB.Model(&user).Where("id = ?", userID).Update("password", newPassword).Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return fmt.Errorf("error updating password for user ID %s: %v", userID, err)
|
||||||
}
|
}
|
||||||
return users, nil
|
return nil
|
||||||
}
|
|
||||||
|
|
||||||
func (r *userProfileRepository) FindByRoleID(roleID string) ([]model.User, error) {
|
|
||||||
var users []model.User
|
|
||||||
err := r.DB.Preload("Role").Where("role_id = ?", roleID).Find(&users).Error
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return users, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,10 @@ type IdentityCardService interface {
|
||||||
|
|
||||||
type identityCardService struct {
|
type identityCardService struct {
|
||||||
identityCardRepo repositories.IdentityCardRepository
|
identityCardRepo repositories.IdentityCardRepository
|
||||||
userRepo repositories.UserProfileRepository
|
userRepo repositories.UserProfilRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewIdentityCardService(identityCardRepo repositories.IdentityCardRepository, userRepo repositories.UserProfileRepository) IdentityCardService {
|
func NewIdentityCardService(identityCardRepo repositories.IdentityCardRepository, userRepo repositories.UserProfilRepository) IdentityCardService {
|
||||||
return &identityCardService{
|
return &identityCardService{
|
||||||
identityCardRepo: identityCardRepo,
|
identityCardRepo: identityCardRepo,
|
||||||
userRepo: userRepo,
|
userRepo: userRepo,
|
||||||
|
|
|
@ -2,23 +2,29 @@ package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"mime/multipart"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"rijig/dto"
|
"rijig/dto"
|
||||||
"rijig/internal/repositories"
|
"rijig/internal/repositories"
|
||||||
"rijig/model"
|
"rijig/model"
|
||||||
"rijig/utils"
|
"rijig/utils"
|
||||||
|
|
||||||
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TrashService interface {
|
type TrashService interface {
|
||||||
CreateCategory(request dto.RequestTrashCategoryDTO) (*dto.ResponseTrashCategoryDTO, error)
|
CreateCategory(request dto.RequestTrashCategoryDTO, iconTrash *multipart.FileHeader) (*dto.ResponseTrashCategoryDTO, error)
|
||||||
AddDetailToCategory(request dto.RequestTrashDetailDTO) (*dto.ResponseTrashDetailDTO, error)
|
AddDetailToCategory(request dto.RequestTrashDetailDTO) (*dto.ResponseTrashDetailDTO, error)
|
||||||
|
|
||||||
GetCategories() ([]dto.ResponseTrashCategoryDTO, error)
|
GetCategories() ([]dto.ResponseTrashCategoryDTO, error)
|
||||||
GetCategoryByID(id string) (*dto.ResponseTrashCategoryDTO, error)
|
GetCategoryByID(id string) (*dto.ResponseTrashCategoryDTO, error)
|
||||||
GetTrashDetailByID(id string) (*dto.ResponseTrashDetailDTO, error)
|
GetTrashDetailByID(id string) (*dto.ResponseTrashDetailDTO, error)
|
||||||
|
|
||||||
UpdateCategory(id string, request dto.RequestTrashCategoryDTO) (*dto.ResponseTrashCategoryDTO, error)
|
UpdateCategory(id string, request dto.RequestTrashCategoryDTO, iconPath *multipart.FileHeader) (*dto.ResponseTrashCategoryDTO, error)
|
||||||
UpdateDetail(id string, request dto.RequestTrashDetailDTO) (*dto.ResponseTrashDetailDTO, error)
|
UpdateDetail(id string, request dto.RequestTrashDetailDTO) (*dto.ResponseTrashDetailDTO, error)
|
||||||
|
|
||||||
DeleteCategory(id string) error
|
DeleteCategory(id string) error
|
||||||
|
@ -33,14 +39,81 @@ func NewTrashService(trashRepo repositories.TrashRepository) TrashService {
|
||||||
return &trashService{TrashRepo: trashRepo}
|
return &trashService{TrashRepo: trashRepo}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO) (*dto.ResponseTrashCategoryDTO, error) {
|
func (s *trashService) saveIconOfTrash(iconTrash *multipart.FileHeader) (string, error) {
|
||||||
|
pathImage := "/uploads/icontrash/"
|
||||||
|
iconTrashDir := "./public" + os.Getenv("BASE_URL") + pathImage
|
||||||
|
if _, err := os.Stat(iconTrashDir); os.IsNotExist(err) {
|
||||||
|
|
||||||
|
if err := os.MkdirAll(iconTrashDir, os.ModePerm); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to create directory for icon trash: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allowedExtensions := map[string]bool{".jpg": true, ".jpeg": true, ".png": true, ".svg": true}
|
||||||
|
extension := filepath.Ext(iconTrash.Filename)
|
||||||
|
if !allowedExtensions[extension] {
|
||||||
|
return "", fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
||||||
|
}
|
||||||
|
|
||||||
|
iconTrashFIleName := fmt.Sprintf("%s_icontrash%s", uuid.New().String(), extension)
|
||||||
|
iconTrashPath := filepath.Join(iconTrashDir, iconTrashFIleName)
|
||||||
|
|
||||||
|
src, err := iconTrash.Open()
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to open uploaded file: %v", err)
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
dst, err := os.Create(iconTrashPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to create icon trash file: %v", err)
|
||||||
|
}
|
||||||
|
defer dst.Close()
|
||||||
|
|
||||||
|
if _, err := dst.ReadFrom(src); err != nil {
|
||||||
|
return "", fmt.Errorf("failed to save icon trash: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
iconTrashUrl := fmt.Sprintf("%s%s", pathImage, iconTrashFIleName)
|
||||||
|
|
||||||
|
return iconTrashUrl, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteIconTrashFIle(imagePath string) error {
|
||||||
|
if imagePath == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
baseDir := "./public/" + os.Getenv("BASE_URL")
|
||||||
|
absolutePath := baseDir + imagePath
|
||||||
|
|
||||||
|
if _, err := os.Stat(absolutePath); os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("image file not found: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := os.Remove(absolutePath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to delete image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Image deleted successfully: %s", absolutePath)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO, iconTrash *multipart.FileHeader) (*dto.ResponseTrashCategoryDTO, error) {
|
||||||
errors, valid := request.ValidateTrashCategoryInput()
|
errors, valid := request.ValidateTrashCategoryInput()
|
||||||
if !valid {
|
if !valid {
|
||||||
return nil, fmt.Errorf("validation error: %v", errors)
|
return nil, fmt.Errorf("validation error: %v", errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
icontrashPath, err := s.saveIconOfTrash(iconTrash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("gagal menyimpan ikon sampah: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
category := model.TrashCategory{
|
category := model.TrashCategory{
|
||||||
Name: request.Name,
|
Name: request.Name,
|
||||||
|
Icon: icontrashPath,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.TrashRepo.CreateCategory(&category); err != nil {
|
if err := s.TrashRepo.CreateCategory(&category); err != nil {
|
||||||
|
@ -53,6 +126,7 @@ func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO) (*dto
|
||||||
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
|
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
|
||||||
ID: category.ID,
|
ID: category.ID,
|
||||||
Name: category.Name,
|
Name: category.Name,
|
||||||
|
Icon: category.Icon,
|
||||||
CreatedAt: createdAt,
|
CreatedAt: createdAt,
|
||||||
UpdatedAt: updatedAt,
|
UpdatedAt: updatedAt,
|
||||||
}
|
}
|
||||||
|
@ -70,6 +144,7 @@ func (s *trashService) CreateCategory(request dto.RequestTrashCategoryDTO) (*dto
|
||||||
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
|
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
|
||||||
ID: c.ID,
|
ID: c.ID,
|
||||||
Name: c.Name,
|
Name: c.Name,
|
||||||
|
Icon: c.Icon,
|
||||||
CreatedAt: ccreatedAt,
|
CreatedAt: ccreatedAt,
|
||||||
UpdatedAt: cupdatedAt,
|
UpdatedAt: cupdatedAt,
|
||||||
})
|
})
|
||||||
|
@ -129,6 +204,7 @@ func (s *trashService) AddDetailToCategory(request dto.RequestTrashDetailDTO) (*
|
||||||
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
|
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
|
||||||
ID: category.ID,
|
ID: category.ID,
|
||||||
Name: category.Name,
|
Name: category.Name,
|
||||||
|
Icon: category.Icon,
|
||||||
CreatedAt: ccreatedAt,
|
CreatedAt: ccreatedAt,
|
||||||
UpdatedAt: cupdatedAt,
|
UpdatedAt: cupdatedAt,
|
||||||
}
|
}
|
||||||
|
@ -153,6 +229,7 @@ func (s *trashService) GetCategories() ([]dto.ResponseTrashCategoryDTO, error) {
|
||||||
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
|
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
|
||||||
ID: categoryData["id"].(string),
|
ID: categoryData["id"].(string),
|
||||||
Name: categoryData["name"].(string),
|
Name: categoryData["name"].(string),
|
||||||
|
Icon: categoryData["icon"].(string),
|
||||||
CreatedAt: categoryData["createdAt"].(string),
|
CreatedAt: categoryData["createdAt"].(string),
|
||||||
UpdatedAt: categoryData["updatedAt"].(string),
|
UpdatedAt: categoryData["updatedAt"].(string),
|
||||||
})
|
})
|
||||||
|
@ -172,6 +249,7 @@ func (s *trashService) GetCategories() ([]dto.ResponseTrashCategoryDTO, error) {
|
||||||
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
|
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
|
||||||
ID: category.ID,
|
ID: category.ID,
|
||||||
Name: category.Name,
|
Name: category.Name,
|
||||||
|
Icon: category.Icon,
|
||||||
CreatedAt: createdAt,
|
CreatedAt: createdAt,
|
||||||
UpdatedAt: updatedAt,
|
UpdatedAt: updatedAt,
|
||||||
})
|
})
|
||||||
|
@ -196,6 +274,7 @@ func (s *trashService) GetCategoryByID(id string) (*dto.ResponseTrashCategoryDTO
|
||||||
return &dto.ResponseTrashCategoryDTO{
|
return &dto.ResponseTrashCategoryDTO{
|
||||||
ID: categoryData["id"].(string),
|
ID: categoryData["id"].(string),
|
||||||
Name: categoryData["name"].(string),
|
Name: categoryData["name"].(string),
|
||||||
|
Icon: categoryData["icon"].(string),
|
||||||
CreatedAt: categoryData["createdAt"].(string),
|
CreatedAt: categoryData["createdAt"].(string),
|
||||||
UpdatedAt: categoryData["updatedAt"].(string),
|
UpdatedAt: categoryData["updatedAt"].(string),
|
||||||
Details: details,
|
Details: details,
|
||||||
|
@ -213,6 +292,7 @@ func (s *trashService) GetCategoryByID(id string) (*dto.ResponseTrashCategoryDTO
|
||||||
categoryDTO := &dto.ResponseTrashCategoryDTO{
|
categoryDTO := &dto.ResponseTrashCategoryDTO{
|
||||||
ID: category.ID,
|
ID: category.ID,
|
||||||
Name: category.Name,
|
Name: category.Name,
|
||||||
|
Icon: category.Icon,
|
||||||
CreatedAt: createdAt,
|
CreatedAt: createdAt,
|
||||||
UpdatedAt: updatedAt,
|
UpdatedAt: updatedAt,
|
||||||
}
|
}
|
||||||
|
@ -220,13 +300,15 @@ func (s *trashService) GetCategoryByID(id string) (*dto.ResponseTrashCategoryDTO
|
||||||
if category.Details != nil {
|
if category.Details != nil {
|
||||||
var detailsDTO []dto.ResponseTrashDetailDTO
|
var detailsDTO []dto.ResponseTrashDetailDTO
|
||||||
for _, detail := range category.Details {
|
for _, detail := range category.Details {
|
||||||
|
createdAt, _ := utils.FormatDateToIndonesianFormat(detail.CreatedAt)
|
||||||
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(detail.UpdatedAt)
|
||||||
detailsDTO = append(detailsDTO, dto.ResponseTrashDetailDTO{
|
detailsDTO = append(detailsDTO, dto.ResponseTrashDetailDTO{
|
||||||
ID: detail.ID,
|
ID: detail.ID,
|
||||||
CategoryID: detail.CategoryID,
|
CategoryID: detail.CategoryID,
|
||||||
Description: detail.Description,
|
Description: detail.Description,
|
||||||
Price: detail.Price,
|
Price: detail.Price,
|
||||||
CreatedAt: detail.CreatedAt.Format("02-01-2006 15:04"),
|
CreatedAt: createdAt,
|
||||||
UpdatedAt: detail.UpdatedAt.Format("02-01-2006 15:04"),
|
UpdatedAt: updatedAt,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
categoryDTO.Details = detailsDTO
|
categoryDTO.Details = detailsDTO
|
||||||
|
@ -281,27 +363,49 @@ func (s *trashService) GetTrashDetailByID(id string) (*dto.ResponseTrashDetailDT
|
||||||
return detailDTO, nil
|
return detailDTO, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *trashService) UpdateCategory(id string, request dto.RequestTrashCategoryDTO) (*dto.ResponseTrashCategoryDTO, error) {
|
func (s *trashService) UpdateCategory(id string, request dto.RequestTrashCategoryDTO, iconPath *multipart.FileHeader) (*dto.ResponseTrashCategoryDTO, error) {
|
||||||
errors, valid := request.ValidateTrashCategoryInput()
|
errors, valid := request.ValidateTrashCategoryInput()
|
||||||
if !valid {
|
if !valid {
|
||||||
return nil, fmt.Errorf("validation error: %v", errors)
|
return nil, fmt.Errorf("validation error: %v", errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.TrashRepo.UpdateCategoryName(id, request.Name); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to update category: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
category, err := s.TrashRepo.GetCategoryByID(id)
|
category, err := s.TrashRepo.GetCategoryByID(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("category not found: %v", err)
|
return nil, fmt.Errorf("category not found: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if category.Icon != "" {
|
||||||
|
err := deleteIconTrashFIle(category.Icon)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to delete old image: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var iconTrashPath string
|
||||||
|
if iconPath != nil {
|
||||||
|
iconTrashPath, err = s.saveIconOfTrash(iconPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to save card photo: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if iconTrashPath != "" {
|
||||||
|
category.Icon = iconTrashPath
|
||||||
|
}
|
||||||
|
|
||||||
|
category, err = s.TrashRepo.UpdateCategory(id, category)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error updating trash category: %v", err)
|
||||||
|
return nil, fmt.Errorf("failed to update category: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
createdAt, _ := utils.FormatDateToIndonesianFormat(category.CreatedAt)
|
createdAt, _ := utils.FormatDateToIndonesianFormat(category.CreatedAt)
|
||||||
updatedAt, _ := utils.FormatDateToIndonesianFormat(category.UpdatedAt)
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(category.UpdatedAt)
|
||||||
|
|
||||||
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
|
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
|
||||||
ID: category.ID,
|
ID: category.ID,
|
||||||
Name: category.Name,
|
Name: category.Name,
|
||||||
|
Icon: category.Icon,
|
||||||
CreatedAt: createdAt,
|
CreatedAt: createdAt,
|
||||||
UpdatedAt: updatedAt,
|
UpdatedAt: updatedAt,
|
||||||
}
|
}
|
||||||
|
@ -319,6 +423,7 @@ func (s *trashService) UpdateCategory(id string, request dto.RequestTrashCategor
|
||||||
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
|
categoriesDTO = append(categoriesDTO, dto.ResponseTrashCategoryDTO{
|
||||||
ID: c.ID,
|
ID: c.ID,
|
||||||
Name: c.Name,
|
Name: c.Name,
|
||||||
|
Icon: c.Icon,
|
||||||
CreatedAt: ccreatedAt,
|
CreatedAt: ccreatedAt,
|
||||||
UpdatedAt: cupdatedAt,
|
UpdatedAt: cupdatedAt,
|
||||||
})
|
})
|
||||||
|
@ -376,6 +481,7 @@ func (s *trashService) UpdateDetail(id string, request dto.RequestTrashDetailDTO
|
||||||
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
|
categoryResponseDTO := &dto.ResponseTrashCategoryDTO{
|
||||||
ID: category.ID,
|
ID: category.ID,
|
||||||
Name: category.Name,
|
Name: category.Name,
|
||||||
|
Icon: category.Icon,
|
||||||
CreatedAt: ccreatedAt,
|
CreatedAt: ccreatedAt,
|
||||||
UpdatedAt: cupdatedAt,
|
UpdatedAt: cupdatedAt,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,310 +1,193 @@
|
||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
|
||||||
|
|
||||||
"rijig/dto"
|
"rijig/dto"
|
||||||
"rijig/internal/repositories"
|
"rijig/internal/repositories"
|
||||||
"rijig/model"
|
"rijig/model"
|
||||||
"rijig/utils"
|
"rijig/utils"
|
||||||
// "golang.org/x/crypto/bcrypt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var allowedExtensions = []string{".jpg", ".jpeg", ".png"}
|
type UserService interface {
|
||||||
|
GetUserByID(userID string) (*dto.UserResponseDTO, error)
|
||||||
type UserProfileService interface {
|
GetAllUsers(page, limit int) ([]dto.UserResponseDTO, error)
|
||||||
GetUserProfile(userID string) (*dto.UserResponseDTO, error)
|
UpdateUser(userID string, request *dto.RequestUserDTO) (*dto.UserResponseDTO, error)
|
||||||
UpdateUserProfile(userID string, updateData dto.UpdateUserDTO) (*dto.UserResponseDTO, error)
|
UpdateUserAvatar(userID string, avatar *multipart.FileHeader) (*dto.UserResponseDTO, error)
|
||||||
// UpdateUserPassword(userID string, passwordData dto.UpdatePasswordDTO) (string, error)
|
UpdateUserPassword(userID, oldPassword, newPassword, confirmNewPassword string) error
|
||||||
UpdateUserAvatar(userID string, file *multipart.FileHeader) (string, error)
|
|
||||||
|
|
||||||
GetAllUsers() ([]dto.UserResponseDTO, error)
|
|
||||||
GetUsersByRoleID(roleID string) ([]dto.UserResponseDTO, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type userProfileService struct {
|
type userService struct {
|
||||||
UserRepo repositories.UserRepository
|
userRepo repositories.UserProfilRepository
|
||||||
RoleRepo repositories.RoleRepository
|
|
||||||
UserProfileRepo repositories.UserProfileRepository
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUserProfileService(userProfileRepo repositories.UserProfileRepository) UserProfileService {
|
func NewUserService(userRepo repositories.UserProfilRepository) UserService {
|
||||||
return &userProfileService{UserProfileRepo: userProfileRepo}
|
return &userService{userRepo: userRepo}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *userProfileService) prepareUserResponse(user *model.User) *dto.UserResponseDTO {
|
func (s *userService) GetUserByID(userID string) (*dto.UserResponseDTO, error) {
|
||||||
|
user, err := s.userRepo.FindByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error retrieving user by ID: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
userDTO, err := s.formatUserResponse(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error formatting user response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return userDTO, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) GetAllUsers(page, limit int) ([]dto.UserResponseDTO, error) {
|
||||||
|
users, err := s.userRepo.FindAll(page, limit)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error retrieving all users: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var userDTOs []dto.UserResponseDTO
|
||||||
|
for _, user := range users {
|
||||||
|
userDTO, err := s.formatUserResponse(&user)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error formatting user response for userID %s: %v", user.ID, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
userDTOs = append(userDTOs, *userDTO)
|
||||||
|
}
|
||||||
|
|
||||||
|
return userDTOs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) UpdateUser(userID string, request *dto.RequestUserDTO) (*dto.UserResponseDTO, error) {
|
||||||
|
|
||||||
|
errors, valid := request.Validate()
|
||||||
|
if !valid {
|
||||||
|
return nil, fmt.Errorf("validation failed: %v", errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := s.userRepo.FindByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("user not found: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
user.Name = request.Name
|
||||||
|
user.Phone = request.Phone
|
||||||
|
user.Email = request.Email
|
||||||
|
|
||||||
|
err = s.userRepo.Update(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error updating user: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
userDTO, err := s.formatUserResponse(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error formatting updated user response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return userDTO, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) UpdateUserAvatar(userID string, avatar *multipart.FileHeader) (*dto.UserResponseDTO, error) {
|
||||||
|
|
||||||
|
user, err := s.userRepo.FindByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("user not found: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *user.Avatar != "" {
|
||||||
|
err := s.deleteAvatarImage(*user.Avatar)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to delete old image: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
avatarURL, err := s.saveAvatarImage(userID, avatar)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to save avatar image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.userRepo.UpdateAvatar(userID, avatarURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to update avatar in the database: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
userDTO, err := s.formatUserResponse(user)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to format user response: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return userDTO, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) UpdateUserPassword(userID, oldPassword, newPassword, confirmNewPassword string) error {
|
||||||
|
|
||||||
|
// errors, valid := utils.ValidatePasswordUpdate(oldPassword, newPassword, confirmNewPassword)
|
||||||
|
// if !valid {
|
||||||
|
// return fmt.Errorf("password validation error: %v", errors)
|
||||||
|
// }
|
||||||
|
|
||||||
|
user, err := s.userRepo.FindByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("user not found: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Password != oldPassword {
|
||||||
|
return fmt.Errorf("old password is incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.userRepo.UpdatePassword(userID, newPassword)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error updating password: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) formatUserResponse(user *model.User) (*dto.UserResponseDTO, error) {
|
||||||
|
|
||||||
createdAt, _ := utils.FormatDateToIndonesianFormat(user.CreatedAt)
|
createdAt, _ := utils.FormatDateToIndonesianFormat(user.CreatedAt)
|
||||||
updatedAt, _ := utils.FormatDateToIndonesianFormat(user.UpdatedAt)
|
updatedAt, _ := utils.FormatDateToIndonesianFormat(user.UpdatedAt)
|
||||||
|
|
||||||
return &dto.UserResponseDTO{
|
userDTO := &dto.UserResponseDTO{
|
||||||
ID: user.ID,
|
ID: user.ID,
|
||||||
// Username: user.Username,
|
Username: user.Name,
|
||||||
Avatar: user.Avatar,
|
Avatar: user.Avatar,
|
||||||
Name: user.Name,
|
Name: user.Name,
|
||||||
Phone: user.Phone,
|
Phone: user.Phone,
|
||||||
Email: user.Email,
|
Email: user.Email,
|
||||||
// EmailVerified: user.EmailVerified,
|
EmailVerified: user.PhoneVerified,
|
||||||
RoleName: user.Role.RoleName,
|
RoleName: user.Role.RoleName,
|
||||||
CreatedAt: createdAt,
|
CreatedAt: createdAt,
|
||||||
UpdatedAt: updatedAt,
|
UpdatedAt: updatedAt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return userDTO, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *userProfileService) GetUserProfile(userID string) (*dto.UserResponseDTO, error) {
|
func (s *userService) saveAvatarImage(userID string, avatar *multipart.FileHeader) (string, error) {
|
||||||
|
|
||||||
cacheKey := fmt.Sprintf("userProfile:%s", userID)
|
pathImage := "/uploads/avatars/"
|
||||||
cachedData, err := utils.GetJSONData(cacheKey)
|
avatarDir := "./public" + os.Getenv("BASE_URL") + pathImage
|
||||||
if err == nil && cachedData != nil {
|
|
||||||
|
|
||||||
userResponse := &dto.UserResponseDTO{}
|
|
||||||
if data, ok := cachedData["data"].(string); ok {
|
|
||||||
if err := json.Unmarshal([]byte(data), userResponse); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return userResponse, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := s.UserProfileRepo.FindByID(userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("user not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
userResponse := s.prepareUserResponse(user)
|
|
||||||
|
|
||||||
cacheData := map[string]interface{}{
|
|
||||||
"data": userResponse,
|
|
||||||
}
|
|
||||||
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error caching user profile to Redis: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return userResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *userProfileService) GetAllUsers() ([]dto.UserResponseDTO, error) {
|
|
||||||
users, err := s.UserProfileRepo.FindAll()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response []dto.UserResponseDTO
|
|
||||||
for _, user := range users {
|
|
||||||
response = append(response, dto.UserResponseDTO{
|
|
||||||
ID: user.ID,
|
|
||||||
// Username: user.Username,
|
|
||||||
Avatar: user.Avatar,
|
|
||||||
Name: user.Name,
|
|
||||||
Phone: user.Phone,
|
|
||||||
// Email: user.Email,
|
|
||||||
// EmailVerified: user.EmailVerified,
|
|
||||||
RoleName: user.Role.RoleName,
|
|
||||||
CreatedAt: user.CreatedAt.Format(time.RFC3339),
|
|
||||||
UpdatedAt: user.UpdatedAt.Format(time.RFC3339),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *userProfileService) GetUsersByRoleID(roleID string) ([]dto.UserResponseDTO, error) {
|
|
||||||
users, err := s.UserProfileRepo.FindByRoleID(roleID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var response []dto.UserResponseDTO
|
|
||||||
for _, user := range users {
|
|
||||||
response = append(response, dto.UserResponseDTO{
|
|
||||||
ID: user.ID,
|
|
||||||
// Username: user.Username,
|
|
||||||
Avatar: user.Avatar,
|
|
||||||
Name: user.Name,
|
|
||||||
Phone: user.Phone,
|
|
||||||
// Email: user.Email,
|
|
||||||
// EmailVerified: user.EmailVerified,
|
|
||||||
RoleName: user.Role.RoleName,
|
|
||||||
CreatedAt: user.CreatedAt.Format(time.RFC3339),
|
|
||||||
UpdatedAt: user.UpdatedAt.Format(time.RFC3339),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return response, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *userProfileService) UpdateUserProfile(userID string, updateData dto.UpdateUserDTO) (*dto.UserResponseDTO, error) {
|
|
||||||
user, err := s.UserProfileRepo.FindByID(userID)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("user not found")
|
|
||||||
}
|
|
||||||
|
|
||||||
validationErrors, valid := updateData.Validate()
|
|
||||||
if !valid {
|
|
||||||
return nil, fmt.Errorf("validation failed: %v", validationErrors)
|
|
||||||
}
|
|
||||||
|
|
||||||
if updateData.Name != "" {
|
|
||||||
user.Name = updateData.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// if updateData.Phone != "" && updateData.Phone != user.Phone {
|
|
||||||
// if err := s.updatePhoneIfNeeded(user, updateData.Phone); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// user.Phone = updateData.Phone
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if updateData.Email != "" && updateData.Email != user.Email {
|
|
||||||
// if err := s.updateEmailIfNeeded(user, updateData.Email); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// user.Email = updateData.Email
|
|
||||||
// }
|
|
||||||
|
|
||||||
err = s.UserProfileRepo.Update(user)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to update user: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
userResponse := s.prepareUserResponse(user)
|
|
||||||
|
|
||||||
cacheKey := fmt.Sprintf("userProfile:%s", userID)
|
|
||||||
cacheData := map[string]interface{}{
|
|
||||||
"data": userResponse,
|
|
||||||
}
|
|
||||||
err = utils.SetJSONData(cacheKey, cacheData, time.Hour*24)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Error updating cached user profile in Redis: %v\n", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return userResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// func (s *userProfileService) updatePhoneIfNeeded(user *model.User, newPhone string) error {
|
|
||||||
// existingPhone, _ := s.UserRepo.FindByPhoneAndRole(newPhone, user.RoleID)
|
|
||||||
// if existingPhone != nil {
|
|
||||||
// return fmt.Errorf("phone number is already used for this role")
|
|
||||||
// }
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (s *userProfileService) updateEmailIfNeeded(user *model.User, newEmail string) error {
|
|
||||||
// existingEmail, _ := s.UserRepo.FindByEmailAndRole(newEmail, user.RoleID)
|
|
||||||
// if existingEmail != nil {
|
|
||||||
// return fmt.Errorf("email is already used for this role")
|
|
||||||
// }
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (s *userProfileService) UpdateUserPassword(userID string, passwordData dto.UpdatePasswordDTO) (string, error) {
|
|
||||||
|
|
||||||
// validationErrors, valid := passwordData.Validate()
|
|
||||||
// if !valid {
|
|
||||||
// return "", fmt.Errorf("validation failed: %v", validationErrors)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// user, err := s.UserProfileRepo.FindByID(userID)
|
|
||||||
// if err != nil {
|
|
||||||
// return "", errors.New("user not found")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if !CheckPasswordHash(passwordData.OldPassword, user.Password) {
|
|
||||||
// return "", errors.New("old password is incorrect")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// hashedPassword, err := bcrypt.GenerateFromPassword([]byte(passwordData.NewPassword), bcrypt.DefaultCost)
|
|
||||||
// if err != nil {
|
|
||||||
// return "", fmt.Errorf("failed to hash new password: %v", err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// user.Password = string(hashedPassword)
|
|
||||||
// err = s.UserProfileRepo.Update(user)
|
|
||||||
// if err != nil {
|
|
||||||
// return "", fmt.Errorf("failed to update password: %v", err)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return "Password berhasil diupdate", nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (s *userProfileService) UpdateUserAvatar(userID string, file *multipart.FileHeader) (string, error) {
|
|
||||||
baseURL := os.Getenv("BASE_URL")
|
|
||||||
if baseURL == "" {
|
|
||||||
return "", fmt.Errorf("BASE_URL is not set in environment variables")
|
|
||||||
}
|
|
||||||
|
|
||||||
avatarDir := filepath.Join("./public", baseURL, "/uploads/avatars")
|
|
||||||
if err := ensureAvatarDirectoryExists(avatarDir); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := validateAvatarFile(file); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
updatedUser, err := s.UserProfileRepo.FindByID(userID)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to retrieve user data: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if updatedUser.Avatar != nil && *updatedUser.Avatar != "" {
|
|
||||||
oldAvatarPath := filepath.Join("./public", *updatedUser.Avatar)
|
|
||||||
if _, err := os.Stat(oldAvatarPath); err == nil {
|
|
||||||
|
|
||||||
if err := os.Remove(oldAvatarPath); err != nil {
|
|
||||||
return "", fmt.Errorf("failed to remove old avatar: %v", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
log.Printf("Old avatar file not found: %s", oldAvatarPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
avatarURL, err := saveAvatarFile(file, userID, avatarDir)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.UserProfileRepo.UpdateAvatar(userID, avatarURL)
|
|
||||||
if err != nil {
|
|
||||||
return "", fmt.Errorf("failed to update avatar in the database: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return "Foto profil berhasil diupdate", nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ensureAvatarDirectoryExists(avatarDir string) error {
|
|
||||||
if _, err := os.Stat(avatarDir); os.IsNotExist(err) {
|
if _, err := os.Stat(avatarDir); os.IsNotExist(err) {
|
||||||
if err := os.MkdirAll(avatarDir, os.ModePerm); err != nil {
|
if err := os.MkdirAll(avatarDir, os.ModePerm); err != nil {
|
||||||
return fmt.Errorf("failed to create avatar directory: %v", err)
|
return "", fmt.Errorf("failed to create directory for avatar: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateAvatarFile(file *multipart.FileHeader) error {
|
allowedExtensions := map[string]bool{".jpg": true, ".jpeg": true, ".png": true}
|
||||||
extension := filepath.Ext(file.Filename)
|
extension := filepath.Ext(avatar.Filename)
|
||||||
for _, ext := range allowedExtensions {
|
if !allowedExtensions[extension] {
|
||||||
if extension == ext {
|
return "", fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return fmt.Errorf("invalid file type, only .jpg, .jpeg, and .png are allowed")
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveAvatarFile(file *multipart.FileHeader, userID, avatarDir string) (string, error) {
|
|
||||||
extension := filepath.Ext(file.Filename)
|
|
||||||
avatarFileName := fmt.Sprintf("%s_avatar%s", userID, extension)
|
avatarFileName := fmt.Sprintf("%s_avatar%s", userID, extension)
|
||||||
avatarPath := filepath.Join(avatarDir, avatarFileName)
|
avatarPath := filepath.Join(avatarDir, avatarFileName)
|
||||||
|
|
||||||
src, err := file.Open()
|
src, err := avatar.Open()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to open uploaded file: %v", err)
|
return "", fmt.Errorf("failed to open uploaded file: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -312,15 +195,37 @@ func saveAvatarFile(file *multipart.FileHeader, userID, avatarDir string) (strin
|
||||||
|
|
||||||
dst, err := os.Create(avatarPath)
|
dst, err := os.Create(avatarPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to create file: %v", err)
|
return "", fmt.Errorf("failed to create avatar file: %v", err)
|
||||||
}
|
}
|
||||||
defer dst.Close()
|
defer dst.Close()
|
||||||
|
|
||||||
_, err = dst.ReadFrom(src)
|
if _, err := dst.ReadFrom(src); err != nil {
|
||||||
if err != nil {
|
return "", fmt.Errorf("failed to save avatar: %v", err)
|
||||||
return "", fmt.Errorf("failed to save avatar file: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
relativePath := filepath.Join("/uploads/avatars", avatarFileName)
|
avatarURL := fmt.Sprintf("%s%s", pathImage, avatarFileName)
|
||||||
return relativePath, nil
|
|
||||||
|
return avatarURL, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *userService) deleteAvatarImage(avatarPath string) error {
|
||||||
|
|
||||||
|
if avatarPath == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
baseDir := "./public/" + os.Getenv("BASE_URL")
|
||||||
|
absolutePath := baseDir + avatarPath
|
||||||
|
|
||||||
|
if _, err := os.Stat(absolutePath); os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("image file not found: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := os.Remove(absolutePath)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to delete avatar image: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("Avatar image deleted successfully: %s", absolutePath)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,8 @@ package model
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type Role struct {
|
type Role struct {
|
||||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4();unique;not null" json:"id"`
|
||||||
RoleName string `gorm:"unique;not null" json:"roleName"`
|
RoleName string `gorm:"unique;not null" json:"roleName"`
|
||||||
// Users []User `gorm:"foreignKey:RoleID" json:"users"`
|
|
||||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import "time"
|
||||||
type TrashCategory struct {
|
type TrashCategory struct {
|
||||||
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
ID string `gorm:"primaryKey;type:uuid;default:uuid_generate_v4()" json:"id"`
|
||||||
Name string `gorm:"not null" json:"name"`
|
Name string `gorm:"not null" json:"name"`
|
||||||
|
Icon string `json:"icon,omitempty"`
|
||||||
Details []TrashDetail `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE;" json:"details"`
|
Details []TrashDetail `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE;" json:"details"`
|
||||||
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
CreatedAt time.Time `gorm:"default:current_timestamp" json:"createdAt"`
|
||||||
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
UpdatedAt time.Time `gorm:"default:current_timestamp" json:"updatedAt"`
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
|
|
||||||
func IdentityCardRouter(api fiber.Router) {
|
func IdentityCardRouter(api fiber.Router) {
|
||||||
identityCardRepo := repositories.NewIdentityCardRepository(config.DB)
|
identityCardRepo := repositories.NewIdentityCardRepository(config.DB)
|
||||||
userRepo := repositories.NewUserProfileRepository(config.DB)
|
userRepo := repositories.NewUserProfilRepository(config.DB)
|
||||||
identityCardService := services.NewIdentityCardService(identityCardRepo, userRepo)
|
identityCardService := services.NewIdentityCardService(identityCardRepo, userRepo)
|
||||||
identityCardHandler := handler.NewIdentityCardHandler(identityCardService)
|
identityCardHandler := handler.NewIdentityCardHandler(identityCardService)
|
||||||
|
|
||||||
|
|
|
@ -11,19 +11,19 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func UserProfileRouter(api fiber.Router) {
|
func UserProfileRouter(api fiber.Router) {
|
||||||
userProfileRepo := repositories.NewUserProfileRepository(config.DB)
|
userProfileRepo := repositories.NewUserProfilRepository(config.DB)
|
||||||
userProfileService := services.NewUserProfileService(userProfileRepo)
|
userProfileService := services.NewUserService(userProfileRepo)
|
||||||
userProfileHandler := handler.NewUserProfileHandler(userProfileService)
|
userProfileHandler := handler.NewUserHandler(userProfileService)
|
||||||
|
|
||||||
userProfilRoute := api.Group("/user")
|
userProfilRoute := api.Group("/user")
|
||||||
|
|
||||||
userProfilRoute.Get("/info", middleware.AuthMiddleware, userProfileHandler.GetUserProfile)
|
userProfilRoute.Get("/info", middleware.AuthMiddleware, userProfileHandler.GetUserByIDHandler)
|
||||||
|
|
||||||
userProfilRoute.Get("/show-all", middleware.AuthMiddleware, userProfileHandler.GetAllUsers)
|
userProfilRoute.Get("/show-all", middleware.AuthMiddleware, userProfileHandler.GetAllUsersHandler)
|
||||||
userProfilRoute.Get("/:userid", middleware.AuthMiddleware, userProfileHandler.GetUserProfileById)
|
// userProfilRoute.Get("/:userid", middleware.AuthMiddleware, userProfileHandler.GetUserProfileById)
|
||||||
userProfilRoute.Get("/:roleid", middleware.AuthMiddleware, userProfileHandler.GetUsersByRoleID)
|
// userProfilRoute.Get("/:roleid", middleware.AuthMiddleware, userProfileHandler.GetUsersByRoleID)
|
||||||
|
|
||||||
userProfilRoute.Put("/update-user", middleware.AuthMiddleware, userProfileHandler.UpdateUserProfile)
|
userProfilRoute.Put("/update-user", middleware.AuthMiddleware, userProfileHandler.UpdateUserHandler)
|
||||||
// userProfilRoute.Patch("/update-user-password", middleware.AuthMiddleware, userProfileHandler.UpdateUserPassword)
|
userProfilRoute.Patch("/update-user-password", middleware.AuthMiddleware, userProfileHandler.UpdateUserPasswordHandler)
|
||||||
userProfilRoute.Patch("/upload-photoprofile", middleware.AuthMiddleware, userProfileHandler.UpdateUserAvatar)
|
userProfilRoute.Patch("/upload-photoprofile", middleware.AuthMiddleware, userProfileHandler.UpdateUserAvatarHandler)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue