Skip to content

Commit 4282e86

Browse files
Merge pull request #14 from DoWithLogic/fix/fix-endpoint-and-unit-test
fix: fix endpoint and unit test
2 parents 0a3a63b + 616b28b commit 4282e86

File tree

15 files changed

+227
-72
lines changed

15 files changed

+227
-72
lines changed

config/config-local.yaml.example

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ database:
1717

1818
authentication:
1919
key: DoWithLogic!@#
20-
secret_key: s3cr#tK3y!@#
20+
secret_key: s3cr#tK3y!@#v001
21+
salt_key: s4ltK3y!@#ddv001

internal/users/delivery/http/v1/handler.go

+12-34
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,10 @@ package v1
22

33
import (
44
"context"
5-
"errors"
65
"net/http"
7-
"strconv"
86
"time"
97

108
"github.com/DoWithLogic/golang-clean-architecture/internal/users/dtos"
11-
"github.com/DoWithLogic/golang-clean-architecture/internal/users/entities"
129
usecases "github.com/DoWithLogic/golang-clean-architecture/internal/users/usecase"
1310
"github.com/DoWithLogic/golang-clean-architecture/pkg/middleware"
1411
"github.com/DoWithLogic/golang-clean-architecture/pkg/otel/zerolog"
@@ -36,10 +33,6 @@ const (
3633
BooleanTextFalse = "false"
3734
)
3835

39-
var (
40-
ErrInvalidIsActive = errors.New("invalid is_active")
41-
)
42-
4336
func NewHandlers(uc usecases.Usecase, log *zerolog.Logger) Handlers {
4437
return &handlers{uc, log}
4538
}
@@ -121,18 +114,20 @@ func (h *handlers) UserDetail(c echo.Context) error {
121114
func (h *handlers) UpdateUser(c echo.Context) error {
122115
var (
123116
ctx, cancel = context.WithTimeout(c.Request().Context(), time.Duration(30*time.Second))
117+
identity = c.Get("identity").(*middleware.CustomClaims)
124118
request dtos.UpdateUserRequest
125119
)
126120
defer cancel()
127121

128-
request.UserID = c.Get("identity").(entities.Identity).UserID
129-
130122
if err := c.Bind(&request); err != nil {
131123
h.log.Z().Err(err).Msg("[handlers]UpdateUser.Bind")
132124

133125
return c.JSON(http.StatusBadRequest, response.NewResponseError(http.StatusBadRequest, response.MsgFailed, err.Error()))
134126
}
135127

128+
request.UserID = identity.UserID
129+
request.UpdateBy = identity.Email
130+
136131
if err := request.Validate(); err != nil {
137132
h.log.Z().Err(err).Msg("[handlers]UpdateUser.Validate")
138133

@@ -149,38 +144,21 @@ func (h *handlers) UpdateUser(c echo.Context) error {
149144
func (h *handlers) UpdateUserStatus(c echo.Context) error {
150145
var (
151146
ctx, cancel = context.WithTimeout(c.Request().Context(), time.Duration(30*time.Second))
152-
payload dtos.UpdateUserStatusPayload
147+
identity = c.Get("identity").(*middleware.CustomClaims)
148+
request = dtos.UpdateUserStatusRequest{UserID: identity.UserID, UpdateBy: identity.Email}
153149
)
154150
defer cancel()
155151

156-
userID, err := strconv.ParseInt(c.Param("id"), 10, 64)
157-
if err != nil {
158-
h.log.Z().Err(err).Msg("[handlers]UpdateUser.ParseParam")
159-
160-
return c.JSON(http.StatusBadRequest, response.NewResponseError(
161-
http.StatusBadRequest,
162-
response.MsgFailed,
163-
err.Error()),
164-
)
165-
}
166-
167-
switch c.QueryParam("is_active") {
168-
case BooleanTextFalse:
169-
payload.IsActive = false
170-
case BooleanTextTrue:
171-
payload.IsActive = true
172-
default:
173-
return c.JSON(http.StatusBadRequest, response.NewResponseError(http.StatusBadRequest, response.MsgFailed, ErrInvalidIsActive.Error()))
152+
if err := c.Bind(&request); err != nil {
153+
return c.JSON(http.StatusBadRequest, response.NewResponseError(http.StatusBadRequest, response.MsgFailed, err.Error()))
174154
}
175155

176-
argsUpdateUserStatus := entities.UpdateUserStatus{
177-
UserID: userID,
178-
IsActive: payload.IsActive,
156+
if err := request.Validate(); err != nil {
157+
return c.JSON(http.StatusBadRequest, response.NewResponseError(http.StatusBadRequest, response.MsgFailed, err.Error()))
179158
}
180159

181-
err = h.uc.UpdateStatus(ctx, argsUpdateUserStatus)
182-
if err != nil {
183-
return c.JSON(http.StatusBadRequest, response.NewResponseError(http.StatusInternalServerError, response.MsgFailed, err.Error()))
160+
if err := h.uc.UpdateStatus(ctx, request); err != nil {
161+
return c.JSON(http.StatusInternalServerError, response.NewResponseError(http.StatusInternalServerError, response.MsgFailed, err.Error()))
184162
}
185163

186164
return c.JSON(http.StatusOK, response.NewResponse(http.StatusOK, response.MsgSuccess, nil))

internal/users/delivery/http/v1/route.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ func UserPrivateRoute(version *echo.Group, h Handlers, cfg config.Config) {
1111
users.POST("", h.CreateUser)
1212
users.POST("/login", h.Login)
1313
users.GET("/detail", h.UserDetail, middleware.AuthorizeJWT(cfg))
14-
users.PATCH("/:id", h.UpdateUser, middleware.AuthorizeJWT(cfg))
15-
users.PUT("/:id", h.UpdateUserStatus, middleware.AuthorizeJWT(cfg))
14+
users.PATCH("/update", h.UpdateUser, middleware.AuthorizeJWT(cfg))
15+
users.PUT("/update/status", h.UpdateUserStatus, middleware.AuthorizeJWT(cfg))
1616
}

internal/users/dtos/user_update.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dtos
33
import (
44
"github.com/DoWithLogic/golang-clean-architecture/pkg/apperror"
55
"github.com/DoWithLogic/golang-clean-architecture/pkg/constant"
6+
"github.com/invopop/validation"
67
)
78

89
type UpdateUserRequest struct {
@@ -12,6 +13,7 @@ type UpdateUserRequest struct {
1213
UserType string `json:"user_type"`
1314
Email string `json:"email"`
1415
Password string `json:"password"`
16+
UpdateBy string `json:"-"`
1517
}
1618

1719
var ()
@@ -21,5 +23,8 @@ func (cup UpdateUserRequest) Validate() error {
2123
return apperror.ErrInvalidUserType
2224
}
2325

24-
return nil
26+
return validation.ValidateStruct(&cup,
27+
validation.Field(&cup.UserID, validation.NotNil),
28+
validation.Field(&cup.UpdateBy, validation.NotNil),
29+
)
2530
}
+14-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
package dtos
22

3-
type UpdateUserStatusPayload struct {
4-
UserID int64
5-
IsActive bool
3+
import "github.com/invopop/validation"
4+
5+
type UpdateUserStatusRequest struct {
6+
UserID int64 `json:"-"`
7+
Status int `json:"status"`
8+
UpdateBy string `json:"-"`
9+
}
10+
11+
func (ussp UpdateUserStatusRequest) Validate() error {
12+
return validation.ValidateStruct(&ussp,
13+
validation.Field(&ussp.UserID, validation.NotNil),
14+
validation.Field(&ussp.UpdateBy, validation.NotNil),
15+
validation.Field(&ussp.Status, validation.Required),
16+
)
617
}

internal/users/entities/user_update.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88

99
type UpdateUsers struct {
1010
UserID int64
11-
Fullname string
1211
Email string
12+
Fullname string
1313
Password string
1414
PhoneNumber string
1515
UserType string
@@ -24,6 +24,6 @@ func NewUpdateUsers(data dtos.UpdateUserRequest) UpdateUsers {
2424
PhoneNumber: data.PhoneNumber,
2525
UserType: data.UserType,
2626
UpdatedAt: time.Now(),
27-
UpdatedBy: "martin",
27+
UpdatedBy: data.UpdateBy,
2828
}
2929
}
+10-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
package entities
22

3-
import "time"
3+
import (
4+
"time"
5+
6+
"github.com/DoWithLogic/golang-clean-architecture/internal/users/dtos"
7+
"github.com/DoWithLogic/golang-clean-architecture/pkg/constant"
8+
)
49

510
type UpdateUserStatus struct {
611
UserID int64
@@ -9,11 +14,11 @@ type UpdateUserStatus struct {
914
UpdatedBy string
1015
}
1116

12-
func NewUpdateUserStatus(payload UpdateUserStatus) UpdateUserStatus {
17+
func NewUpdateUserStatus(req dtos.UpdateUserStatusRequest) UpdateUserStatus {
1318
return UpdateUserStatus{
14-
UserID: payload.UserID,
15-
IsActive: payload.IsActive,
19+
UserID: req.UserID,
20+
IsActive: constant.MapStatus[req.Status],
1621
UpdatedAt: time.Now(),
17-
UpdatedBy: "martin",
22+
UpdatedBy: req.UpdateBy,
1823
}
1924
}

internal/users/entities/users.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@ func NewCreateUser(data dtos.CreateUserRequest, cfg config.Config) Users {
3838
UserType: constant.UserTypeRegular,
3939
IsActive: true,
4040
CreatedAt: time.Now(),
41-
CreatedBy: constant.UserSystem,
41+
CreatedBy: "SYSTEM",
4242
}
4343
}

internal/users/repository/repository.go

+1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ func (repo *repository) SaveNewUser(ctx context.Context, user entities.Users) (u
7979

8080
func (repo *repository) UpdateUserByID(ctx context.Context, user entities.UpdateUsers) error {
8181
args := utils.Array{
82+
user.Email, user.Email,
8283
user.Fullname, user.Fullname,
8384
user.PhoneNumber, user.PhoneNumber,
8485
user.UserType, user.UserType,

internal/users/repository/repository_query/users/update.sql

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
UPDATE users SET
2+
email = CASE WHEN ? != '' THEN ? ELSE email END,
23
fullname = CASE WHEN ? != '' THEN ? ELSE fullname END,
34
phone_number = CASE WHEN ? != '' THEN ? ELSE phone_number END,
45
user_type = CASE WHEN ? != '' THEN ? ELSE user_type END,

internal/users/usecase/usecase.go

+4-8
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type (
2323
Login(ctx context.Context, request dtos.UserLoginRequest) (response dtos.UserLoginResponse, httpCode int, err error)
2424
Create(ctx context.Context, payload dtos.CreateUserRequest) (userID int64, httpCode int, err error)
2525
PartialUpdate(ctx context.Context, data dtos.UpdateUserRequest) error
26-
UpdateStatus(ctx context.Context, req entities.UpdateUserStatus) error
26+
UpdateStatus(ctx context.Context, req dtos.UpdateUserStatusRequest) error
2727
Detail(ctx context.Context, id int64) (detail dtos.UserDetailResponse, httpCode int, err error)
2828
}
2929

@@ -44,19 +44,15 @@ func (uc *usecase) Login(ctx context.Context, request dtos.UserLoginRequest) (re
4444
return response, http.StatusInternalServerError, err
4545
}
4646

47-
uc.log.Z().Err(nil).Str("decrypted_password", dataLogin.Password).Str("password", request.Password).Msg("[Login]")
48-
4947
if !strings.EqualFold(utils.Decrypt(dataLogin.Password, uc.cfg), request.Password) {
5048
return response, http.StatusUnauthorized, apperror.ErrInvalidPassword
5149
}
5250

53-
expiredAt := time.Now().Add(time.Minute * 15).Unix()
54-
5551
identityData := middleware.CustomClaims{
5652
UserID: dataLogin.UserID,
5753
Email: dataLogin.Email,
5854
StandardClaims: jwt.StandardClaims{
59-
ExpiresAt: expiredAt,
55+
ExpiresAt: time.Now().Add(time.Minute * 15).Unix(),
6056
},
6157
}
6258

@@ -67,7 +63,7 @@ func (uc *usecase) Login(ctx context.Context, request dtos.UserLoginRequest) (re
6763

6864
response = dtos.UserLoginResponse{
6965
AccessToken: token,
70-
ExpiredAt: expiredAt,
66+
ExpiredAt: utils.UnixToDuration(identityData.ExpiresAt),
7167
}
7268

7369
return response, http.StatusOK, nil
@@ -111,7 +107,7 @@ func (uc *usecase) PartialUpdate(ctx context.Context, data dtos.UpdateUserReques
111107
})
112108
}
113109

114-
func (uc *usecase) UpdateStatus(ctx context.Context, req entities.UpdateUserStatus) error {
110+
func (uc *usecase) UpdateStatus(ctx context.Context, req dtos.UpdateUserStatusRequest) error {
115111
_, err := uc.repo.GetUserByID(ctx, req.UserID, entities.LockingOpt{})
116112
if err != nil {
117113
uc.log.Z().Err(err).Msg("[usecase]UpdateUserStatus.GetUserByID")

0 commit comments

Comments
 (0)