Skip to content

Commit f591f93

Browse files
committed
feat: implement user profile update functionality
1 parent 186286a commit f591f93

6 files changed

Lines changed: 110 additions & 1 deletion

File tree

controller/user_controller.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type (
1515
Login(ctx *gin.Context)
1616
Me(ctx *gin.Context)
1717
GetUserByUsername(ctx *gin.Context)
18+
UpdateUser(ctx *gin.Context)
1819
}
1920

2021
userController struct {
@@ -98,3 +99,23 @@ func (c *userController) GetUserByUsername(ctx *gin.Context) {
9899
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_USER, result)
99100
ctx.JSON(http.StatusOK, res)
100101
}
102+
103+
func (c *userController) UpdateUser(ctx *gin.Context) {
104+
userId := ctx.MustGet("user_id").(string)
105+
var user dto.UserProfileUpdateRequest
106+
if err := ctx.ShouldBind(&user); err != nil {
107+
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_USER_DATA_FROM_BODY, err.Error(), nil)
108+
ctx.AbortWithStatusJSON(http.StatusBadRequest, res)
109+
return
110+
}
111+
112+
result, err := c.userService.UpdateUser(ctx.Request.Context(), userId, user)
113+
if err != nil {
114+
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_UPDATE_USER, err.Error(), nil)
115+
ctx.JSON(http.StatusBadRequest, res)
116+
return
117+
}
118+
119+
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_UPDATE_USER, result)
120+
ctx.JSON(http.StatusOK, res)
121+
}

dto/user_dto.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ const (
1515
MESSAGE_FAILED_LOGIN = "failed login"
1616
MESSAGE_FAILED_PROSES_REQUEST = "failed proses request"
1717
MESSAGE_FAILED_DENIED_ACCESS = "denied access"
18+
MESSAGE_FAILED_UPDATE_USER = "failed update user"
1819

1920
// Success
2021
MESSAGE_SUCCESS_REGISTER_USER = "success create user"
2122
MESSAGE_SUCCESS_GET_USER = "success get user"
2223
MESSAGE_SUCCESS_LOGIN = "success login"
24+
MESSAGE_SUCCESS_UPDATE_USER = "success update user"
2325
)
2426

2527
var (
@@ -40,6 +42,12 @@ type (
4042
Password string `json:"password" form:"password" binding:"required"`
4143
}
4244

45+
UserProfileUpdateRequest struct {
46+
Name string `json:"name" form:"name"`
47+
Bio string `json:"bio" form:"bio"`
48+
Image *multipart.FileHeader `json:"image" form:"image"`
49+
}
50+
4351
UserResponse struct {
4452
ID string `json:"id"`
4553
Name string `json:"name"`

repository/user_repository.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type (
1212
RegisterUser(ctx context.Context, tx *gorm.DB, user entity.User) (entity.User, error)
1313
GetUserById(ctx context.Context, tx *gorm.DB, userId string) (entity.User, error)
1414
CheckUsername(ctx context.Context, tx *gorm.DB, email string) (entity.User, bool, error)
15+
UpdateUser(ctx context.Context, tx *gorm.DB, userId string, user entity.User) (entity.User, error)
1516
}
1617

1718
userRepository struct {
@@ -62,3 +63,20 @@ func (r *userRepository) CheckUsername(ctx context.Context, tx *gorm.DB, usernam
6263

6364
return user, true, nil
6465
}
66+
67+
func (r *userRepository) UpdateUser(ctx context.Context, tx *gorm.DB, userId string, user entity.User) (entity.User, error) {
68+
if tx == nil {
69+
tx = r.db
70+
}
71+
72+
if err := tx.WithContext(ctx).Model(&user).Where("id = ?", userId).Updates(user).Error; err != nil {
73+
return entity.User{}, err
74+
}
75+
76+
var updatedUser entity.User
77+
if err := tx.WithContext(ctx).Where("id = ?", userId).Take(&updatedUser).Error; err != nil {
78+
return entity.User{}, err
79+
}
80+
81+
return updatedUser, nil
82+
}

routes/user_route.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,6 @@ func User(route *gin.Engine, injector *do.Injector) {
2020
routes.POST("/login", userController.Login)
2121
routes.GET("/me", middleware.Authenticate(jwtService), userController.Me)
2222
routes.GET("/:username", userController.GetUserByUsername)
23+
routes.PATCH("/update", middleware.Authenticate(jwtService), userController.UpdateUser)
2324
}
2425
}

service/user_service.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type (
1818
GetUserById(ctx context.Context, userId string) (dto.UserResponse, error)
1919
Verify(ctx context.Context, req dto.UserLoginRequest) (dto.UserLoginResponse, error)
2020
GetUserByUsername(ctx context.Context, username string) (dto.UserResponse, error)
21+
UpdateUser(ctx context.Context, userId string, req dto.UserProfileUpdateRequest) (dto.UserResponse, error)
2122
}
2223

2324
userService struct {
@@ -127,3 +128,55 @@ func (s *userService) GetUserByUsername(ctx context.Context, username string) (d
127128
ImageUrl: user.ImageUrl,
128129
}, nil
129130
}
131+
132+
func (s *userService) UpdateUser(ctx context.Context, userId string, req dto.UserProfileUpdateRequest) (dto.UserResponse, error) {
133+
user, err := s.userRepo.GetUserById(ctx, nil, userId)
134+
if err != nil {
135+
return dto.UserResponse{}, dto.ErrGetUserById
136+
}
137+
138+
if req.Name != "" {
139+
user.Name = req.Name
140+
}
141+
142+
previousImage := user.ImageUrl
143+
144+
if req.Image != nil {
145+
var filenamePtr *string
146+
imageId := uuid.New()
147+
ext := utils.GetExtensions(req.Image.Filename)
148+
149+
filename := fmt.Sprintf("profile/%s.%s", imageId, ext)
150+
if err := utils.UploadFile(req.Image, filename); err != nil {
151+
return dto.UserResponse{}, err
152+
}
153+
filenamePtr = &filename
154+
user.ImageUrl = filenamePtr
155+
}
156+
157+
if req.Bio != "" {
158+
var bioPtr *string
159+
bio := req.Bio
160+
bioPtr = &bio
161+
user.Bio = bioPtr
162+
}
163+
164+
userUpdate, err := s.userRepo.UpdateUser(ctx, nil, userId, user)
165+
if err != nil {
166+
return dto.UserResponse{}, dto.ErrCreateUser
167+
}
168+
169+
if previousImage != nil {
170+
if err := utils.DeleteFile(*previousImage); err != nil {
171+
return dto.UserResponse{}, err
172+
}
173+
}
174+
175+
return dto.UserResponse{
176+
ID: userUpdate.ID.String(),
177+
Name: userUpdate.Name,
178+
UserName: userUpdate.Username,
179+
Bio: userUpdate.Bio,
180+
ImageUrl: userUpdate.ImageUrl,
181+
}, nil
182+
}

utils/file.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,12 @@ func UploadFile(file *multipart.FileHeader, path string) error {
4747

4848
func GetExtensions(filename string) string {
4949
return strings.Split(filename, ".")[len(strings.Split(filename, "."))-1]
50-
}
50+
}
51+
52+
func DeleteFile(path string) error {
53+
filePath := fmt.Sprintf("%s/%s", PATH, path)
54+
if err := os.Remove(filePath); err != nil {
55+
return err
56+
}
57+
return nil
58+
}

0 commit comments

Comments
 (0)