diff --git a/.env.example b/.env.example index 936c7f6..a6dbb08 100644 --- a/.env.example +++ b/.env.example @@ -2,6 +2,7 @@ APP_ENV=local APP_GRPC_PORT=3000 APP_HTTP_PORT=3001 APP_DEBUG=true +APP_STORAGE_PUBLIC_URL= DB_HOST=localhost DB_PORT=3306 diff --git a/config/config.go b/config/config.go index 00cff4a..fd8968e 100644 --- a/config/config.go +++ b/config/config.go @@ -17,6 +17,7 @@ func NewConfig() (defConfig *Config, err error) { appGRPCPort, _ := strconv.Atoi(os.Getenv(`APP_GRPC_PORT`)) appHTTPPort, _ := strconv.Atoi(os.Getenv(`APP_HTTP_PORT`)) debugString := os.Getenv(`APP_DEBUG`) + appStoragePublicURL := os.Getenv(`APP_STORAGE_PUBLIC_URL`) debug := false if debugString == "true" { @@ -39,6 +40,7 @@ func NewConfig() (defConfig *Config, err error) { defConfig.AppGRPCPort = appGRPCPort defConfig.AppHTTPPort = appHTTPPort defConfig.Debug = debug + defConfig.AppStoragePublicURL = appStoragePublicURL if dbHost == "" || dbPort == 0 || dbUser == "" || dbName == "" || driverName == "" { err = fmt.Errorf("[CONFIG][Critical] Please check section DB on %s", envFileName) diff --git a/config/model.go b/config/model.go index 4966b79..68018e2 100644 --- a/config/model.go +++ b/config/model.go @@ -10,9 +10,10 @@ type DB struct { } type Config struct { - AppGRPCPort int `env:"APP_GRPC_PORT,required"` - AppHTTPPort int `env:"APP_HTTP_PORT,required"` - AppEnv string `env:"APP_ENV,required"` - Debug bool `env:"APP_DEBUG,required"` - DB *DB + AppGRPCPort int `env:"APP_GRPC_PORT,required"` + AppHTTPPort int `env:"APP_HTTP_PORT,required"` + AppEnv string `env:"APP_ENV,required"` + Debug bool `env:"APP_DEBUG,required"` + AppStoragePublicURL string `env:"APP_STORAGE_PUBLIC_URL,required"` + DB *DB } diff --git a/endpoint/endpoint.go b/endpoint/endpoint.go index 4b6890b..436c2d6 100644 --- a/endpoint/endpoint.go +++ b/endpoint/endpoint.go @@ -3,7 +3,6 @@ package endpoint import ( "context" "encoding/json" - "strings" "errors" @@ -16,10 +15,9 @@ import ( func MakeGetListUserPost(ctx context.Context, usecase usecase.UsecaseI) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (response interface{}, err error) { req := request.(*GetListUserPostRequest) - cASC := strings.Compare(helper.GetStringFromPointer(req.SortBy), "ASC") - cDESC := strings.Compare(helper.GetStringFromPointer(req.SortBy), "DESC") - if req.SortBy != nil && (cASC*cDESC == 1) { - return nil, errors.New("must_between_ASC_DESC") + orderBy := helper.GetStringFromPointer(req.OrderBy) + if req.OrderBy != nil && !isOrderValid(orderBy) { + return nil, errors.New("order_must_between_ASC_DESC") } // TODO: for get metadata from headers grpc needs to update when using authorization resp, err := usecase.GetListPost(ctx, &model.GetListRequest{ diff --git a/endpoint/request.go b/endpoint/request.go index 92aa23f..6174845 100644 --- a/endpoint/request.go +++ b/endpoint/request.go @@ -1,6 +1,8 @@ package endpoint import ( + "strings" + "github.com/go-ozzo/ozzo-validation/is" validation "github.com/go-ozzo/ozzo-validation/v4" "github.com/sapawarga/userpost-service/helper" @@ -69,3 +71,7 @@ func validationImages(in []*Image) validation.RuleFunc { return err } } + +func isOrderValid(val string) bool { + return strings.EqualFold(val, "ASC") || strings.EqualFold(val, "DESC") +} diff --git a/mocks/testcases/get-detail-user-post.go b/mocks/testcases/get-detail-user-post.go index 122dcdc..833bf4a 100644 --- a/mocks/testcases/get-detail-user-post.go +++ b/mocks/testcases/get-detail-user-post.go @@ -19,12 +19,15 @@ type ResponseGetDetailUsecase struct { } var ( + images = []map[string]interface{}{ + {"path": "general"}, + } userpostResponse = &model.UserPostResponse{ ID: 1, Title: "title", Tag: helper.SetPointerString("tag"), ImagePath: "test", - Images: "test", + Images: images, LastUserPostCommentID: helper.SetPointerInt64(1), LastComment: comment, LikesCount: 0, diff --git a/mocks/testcases/get-list-user-post.go b/mocks/testcases/get-list-user-post.go index cec9434..19f8e15 100644 --- a/mocks/testcases/get-list-user-post.go +++ b/mocks/testcases/get-list-user-post.go @@ -128,15 +128,16 @@ var ( Status: 10, } actor = &model.Actor{ - ID: 1, - Name: "John Doe", - PhotoURL: "www.instagram.com/htm-medium=?p9878y2y3", - Role: 99, - Regency: "regency", - District: "district", - Village: "village", - RW: "rw", - Status: 10, + ID: 1, + Name: "John Doe", + PhotoURL: "www.instagram.com/htm-medium=?p9878y2y3", + Role: 99, + RoleLabel: model.RoleLabel[int64(99)], + Regency: "regency", + District: "district", + Village: "village", + RW: "rw", + Status: 10, } metadataResponse = helper.SetPointerInt64(2) commentResponse = &model.CommentResponse{ @@ -164,7 +165,7 @@ var ( Title: "title", Tag: helper.SetPointerString("tag"), ImagePath: "test", - Images: "test", + Images: images, LastUserPostCommentID: helper.SetPointerInt64(1), LastComment: comment, LikesCount: 0, @@ -179,7 +180,7 @@ var ( Title: "test title", Tag: helper.SetPointerString("tag"), ImagePath: "test", - Images: "test", + Images: images, LastUserPostCommentID: helper.SetPointerInt64(1), LastComment: comment, LikesCount: 0, diff --git a/model/usecase_response.go b/model/usecase_response.go index b3d1333..e35f6da 100644 --- a/model/usecase_response.go +++ b/model/usecase_response.go @@ -5,20 +5,20 @@ import ( ) type UserPostResponse struct { - ID int64 `json:"id"` - Title string `json:"title"` - Tag *string `json:"tags,omitempty"` - ImagePath string `json:"image_path,omitempty"` - Images string `json:"images"` - LastUserPostCommentID *int64 `json:"last_user_post_comment_id,omitempty"` - LastComment *Comment `json:"last_comment,omitempty"` - LikesCount int64 `json:"likes_count"` - IsLiked bool `json:"is_liked"` - CommentCounts int64 `json:"comment_counts"` - Status int64 `json:"status"` - Actor *Actor `json:"actor"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + ID int64 `json:"id"` + Title string `json:"title"` + Tag *string `json:"tags,omitempty"` + ImagePath string `json:"image_path,omitempty"` + Images []map[string]interface{} `json:"images"` + LastUserPostCommentID *int64 `json:"last_user_post_comment_id,omitempty"` + LastComment *Comment `json:"last_comment,omitempty"` + LikesCount int64 `json:"likes_count"` + IsLiked bool `json:"is_liked"` + CommentCounts int64 `json:"comment_counts"` + Status int64 `json:"status"` + Actor *Actor `json:"actor"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` } type UserPostWithMetadata struct { @@ -43,13 +43,29 @@ type Comment struct { } type Actor struct { - ID int64 `json:"id"` - Name string `json:"name"` - PhotoURL string `json:"photo_url,omitempty"` - Role int64 `json:"role,omitempty"` - Regency string `json:"regency,omitempty"` - District string `json:"district,omitempty"` - Village string `json:"village,omitempty"` - RW string `json:"rw,omitempty"` - Status int64 `json:"status,omitempty"` + ID int64 `json:"id"` + Name string `json:"name"` + PhotoURL string `json:"photo_url,omitempty"` + Role int64 `json:"role,omitempty"` + RoleLabel string `json:"role_label,omitempty"` + Regency string `json:"regency,omitempty"` + District string `json:"district,omitempty"` + Village string `json:"village,omitempty"` + RW string `json:"rw,omitempty"` + Status int64 `json:"status,omitempty"` +} + +var RoleLabel = map[int64]string{ + 10: "user", + 49: "trainer", + 50: "staffRW", + 60: "staffKel", + 70: "staffKec", + 80: "staffKabKota", + 88: "staffOPD", + 89: "staffSaberhoax", + 90: "staffProv", + 91: "pimpinan", + 99: "admin", + 100: "service_account", } diff --git a/repository/mysql/userpost.go b/repository/mysql/userpost.go index dcbce26..785efca 100644 --- a/repository/mysql/userpost.go +++ b/repository/mysql/userpost.go @@ -33,7 +33,7 @@ func (r *UserPost) GetListPost(ctx context.Context, request *model.UserPostReque params = append(params, request.Offset, request.Limit) } if request.OrderBy != nil && request.SortBy != nil { - query.WriteString(fmt.Sprintf(" ORDER BY %s %s", *request.OrderBy, *request.SortBy)) + query.WriteString(fmt.Sprintf(" ORDER BY %s %s", *request.SortBy, *request.OrderBy)) } if ctx != nil { err = r.conn.SelectContext(ctx, &result, query.String(), params...) diff --git a/transport/grpc/transport.go b/transport/grpc/transport.go index b3a27ac..2887ebd 100644 --- a/transport/grpc/transport.go +++ b/transport/grpc/transport.go @@ -2,6 +2,7 @@ package grpc import ( "context" + "encoding/json" "github.com/sapawarga/userpost-service/endpoint" "github.com/sapawarga/userpost-service/helper" @@ -96,12 +97,13 @@ func encodeGetListUserPost(ctx context.Context, r interface{}) (interface{}, err resultData := make([]*transportUserPost.UserPost, 0) for _, v := range data { + images, _ := json.Marshal(v.Images) result := &transportUserPost.UserPost{ Id: v.ID, Title: v.Title, Tag: helper.GetStringFromPointer(v.Tag), ImagePath: v.ImagePath, - Images: v.Images, + Images: string(images), LastUserPostCommentId: helper.GetInt64FromPointer(v.LastUserPostCommentID), LikesCount: v.LikesCount, CommentCounts: v.CommentCounts, @@ -175,12 +177,13 @@ func encodedUserPostDetail(ctx context.Context, r interface{}) (interface{}, err actorUserPost := encodeActor(ctx, resp.Actor) + images, _ := json.Marshal(resp.Images) userDetail := &transportUserPost.UserPost{ Id: resp.ID, Title: resp.Title, Tag: helper.GetStringFromPointer(resp.Tag), ImagePath: resp.ImagePath, - Images: resp.Images, + Images: string(images), LastUserPostCommentId: helper.GetInt64FromPointer(resp.LastUserPostCommentID), LastComment: lastComment, LikesCount: resp.LikesCount, diff --git a/usecase/parser.go b/usecase/parser.go index 9722306..e34dc84 100644 --- a/usecase/parser.go +++ b/usecase/parser.go @@ -2,21 +2,32 @@ package usecase import ( "context" + "encoding/json" + "fmt" kitlog "github.com/go-kit/kit/log" "github.com/go-kit/kit/log/level" + "github.com/sapawarga/userpost-service/config" "github.com/sapawarga/userpost-service/helper" "github.com/sapawarga/userpost-service/model" ) func (p *Post) getDetailOfUserPost(ctx context.Context, post *model.PostResponse) (*model.UserPostResponse, error) { logger := kitlog.With(p.logger, "method", "getDetailOfUserPost") + cfg, _ := config.NewConfig() + images := make([]map[string]interface{}, 0) + if err := json.Unmarshal([]byte(post.Images.String), &images); err != nil { + images = nil + } + for _, v := range images { + v["path"] = fmt.Sprintf("%s/%s", cfg.AppStoragePublicURL, v["path"]) + } userPost := &model.UserPostResponse{ ID: post.ID, Title: post.Title, Tag: helper.SetPointerString(post.Tag.String), - ImagePath: post.ImagePath.String, - Images: post.Images.String, + ImagePath: fmt.Sprintf("%s/%s", cfg.AppStoragePublicURL, post.ImagePath.String), + Images: images, LikesCount: post.LikesCount, CommentCounts: post.CommentCounts, Status: post.Status, @@ -51,15 +62,16 @@ func (p *Post) getDetailOfUserPost(ctx context.Context, post *model.PostResponse func (p *Post) parsingUserResponse(ctx context.Context, user *model.UserResponse) *model.Actor { return &model.Actor{ - ID: user.ID, - Name: user.Name.String, - PhotoURL: user.PhotoURL.String, - Role: user.Role.Int64, - Regency: user.Regency.String, - District: user.District.String, - Village: user.Village.String, - RW: user.RW.String, - Status: user.Status, + ID: user.ID, + Name: user.Name.String, + PhotoURL: user.PhotoURL.String, + Role: user.Role.Int64, + RoleLabel: model.RoleLabel[user.Role.Int64], + Regency: user.Regency.String, + District: user.District.String, + Village: user.Village.String, + RW: user.RW.String, + Status: user.Status, } }