Skip to content

Commit

Permalink
feat&fix #time 30m #comment implement like & comment controller, fixi…
Browse files Browse the repository at this point in the history
…ng query sql, route, blog|comment|like interfaces, blog services
  • Loading branch information
PickHD committed May 1, 2022
1 parent 5efdce0 commit 70f09e6
Show file tree
Hide file tree
Showing 6 changed files with 369 additions and 40 deletions.
268 changes: 261 additions & 7 deletions controller/blog.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ func (bc *BlogController) UpdateBlog(ctx *fiber.Ctx) error {

err = bc.BlogSvc.UpdateBlogSvc(id,blogReq,extData.FullName)
if err != nil {
if errors.Is(err,model.ErrForbiddenUpdate) {
return helper.ResponseFormatter[any](ctx,fiber.StatusForbidden,err,err.Error(),nil,nil)
}

if errors.Is(err,model.ErrBlogNotFound) {
return helper.ResponseFormatter[any](ctx,fiber.StatusNotFound,err,err.Error(),nil,nil)
}
Expand All @@ -196,8 +200,18 @@ func (bc *BlogController) DeleteBlog(ctx *fiber.Ctx) error {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,nil,model.ErrBlogNotFound.Error(),nil,nil)
}

err = bc.BlogSvc.DeleteBlogSvc(id)
data := ctx.Locals(model.KeyJWTValidAccess)
extData,err := util.ExtractPayloadJWT(data)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

err = bc.BlogSvc.DeleteBlogSvc(id,extData.UserID)
if err != nil {
if errors.Is(err,model.ErrForbiddenDelete) {
return helper.ResponseFormatter[any](ctx,fiber.StatusForbidden,err,err.Error(),nil,nil)
}

if errors.Is(err,model.ErrBlogNotFound) {
return helper.ResponseFormatter[any](ctx,fiber.StatusNotFound,err,err.Error(),nil,nil)
}
Expand All @@ -209,19 +223,259 @@ func (bc *BlogController) DeleteBlog(ctx *fiber.Ctx) error {
}

// CreateComment responsible to creating a comment from controller layer
func (bc *BlogController) CreateComment(ctx *fiber.Ctx) error {return nil}
func (bc *BlogController) CreateComment(ctx *fiber.Ctx) error {
var commentReq model.CommentRequest

id,err := ctx.ParamsInt("id",0)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

if id == 0 {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,nil,model.ErrBlogNotFound.Error(),nil,nil)
}

data := ctx.Locals(model.KeyJWTValidAccess)
extData,err := util.ExtractPayloadJWT(data)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

if err := ctx.BodyParser(&commentReq); err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

commentReq.UserID = extData.UserID

err = bc.BlogSvc.CreateCommentSvc(id,commentReq,extData.FullName)
if err != nil {

if errors.Is(err,model.ErrUserNotFound) || errors.Is(err,model.ErrBlogNotFound) {
return helper.ResponseFormatter[any](ctx,fiber.StatusNotFound,err,err.Error(),nil,nil)
}

if errors.Is(err,model.ErrInvalidRequest) {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusCreated,nil,"Success Create Comment",nil,nil)
}

// UpdateComment responsible to updating a comment by id from controller layer
func (bc *BlogController) UpdateComment(ctx *fiber.Ctx) error {return nil}
func (bc *BlogController) UpdateComment(ctx *fiber.Ctx) error {
var commentReq model.CommentRequest

commentId,err := ctx.ParamsInt("comment_id",0)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

if commentId == 0 {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,nil,model.ErrCommentNotFound.Error(),nil,nil)
}

data := ctx.Locals(model.KeyJWTValidAccess)
extData,err := util.ExtractPayloadJWT(data)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

if err := ctx.BodyParser(&commentReq); err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

commentReq.UserID = extData.UserID

err = bc.BlogSvc.UpdateCommentSvc(commentId,commentReq,extData.FullName)
if err != nil {
if errors.Is(err,model.ErrForbiddenUpdate) {
return helper.ResponseFormatter[any](ctx,fiber.StatusForbidden,err,err.Error(),nil,nil)
}

if errors.Is(err,model.ErrUserNotFound) || errors.Is(err,model.ErrCommentNotFound) {
return helper.ResponseFormatter[any](ctx,fiber.StatusNotFound,err,err.Error(),nil,nil)
}

if errors.Is(err,model.ErrInvalidRequest) {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusOK,nil,"Success Update Comment",nil,nil)
}

// ListComment responsible to getting comments by blog id from controller layer
func (bc *BlogController) ListComment(ctx *fiber.Ctx) error {return nil}
func (bc *BlogController) ListComment(ctx *fiber.Ctx) error {
var (
page = 1
size = 10
order = "ASC"
field = "id"
)

id,err := ctx.ParamsInt("id",0)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

if id == 0 {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,nil,model.ErrBlogNotFound.Error(),nil,nil)
}

if p := ctx.Query("page",""); p != "" {
pNum,err := strconv.Atoi(p)
if err == nil && pNum > 0 {
page = pNum
}
}

if s := ctx.Query("size",""); s != "" {
sNum, err := strconv.Atoi(s)
if err == nil && sNum > 0 {
size = sNum
}
}

if o := ctx.Query("order",""); o != "" {
if len(o) > 0 {
order = o
}
}

if f := ctx.Query("field",""); f != "" {
if len(f) > 0 {
field = f
}
}

data,meta,err := bc.BlogSvc.GetCommentsByBlogSvc(id,page,size,order,field)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusOK,nil,"Success Getting all Comments",data,meta)
}

// DeleteComment responsible to deleting a comment by id from controller layer
func (bc *BlogController) DeleteComment(ctx *fiber.Ctx) error {return nil}
func (bc *BlogController) DeleteComment(ctx *fiber.Ctx) error {
blogID,err := ctx.ParamsInt("id",0)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

if blogID == 0 {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,nil,model.ErrBlogNotFound.Error(),nil,nil)
}

commentID,err := ctx.ParamsInt("comment_id",0)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

if commentID == 0 {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,nil,model.ErrCommentNotFound.Error(),nil,nil)
}

data := ctx.Locals(model.KeyJWTValidAccess)
extData,err := util.ExtractPayloadJWT(data)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

err = bc.BlogSvc.DeleteCommentSvc(blogID,commentID,extData.UserID)
if err != nil {
if errors.Is(err,model.ErrForbiddenDelete) {
return helper.ResponseFormatter[any](ctx,fiber.StatusForbidden,err,err.Error(),nil,nil)
}

if errors.Is(err,model.ErrBlogNotFound) || errors.Is(err,model.ErrCommentNotFound) {
return helper.ResponseFormatter[any](ctx,fiber.StatusNotFound,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusOK,nil,"Success Delete Comment",nil,nil)
}

// Like responsible to creating a like / liking a blog
func (bc *BlogController) Like(ctx *fiber.Ctx) error {return nil}
func (bc *BlogController) Like(ctx *fiber.Ctx) error {
var likeReq model.LikeRequest

id,err := ctx.ParamsInt("id",0)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

if id == 0 {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,nil,model.ErrBlogNotFound.Error(),nil,nil)
}

data := ctx.Locals(model.KeyJWTValidAccess)
extData,err := util.ExtractPayloadJWT(data)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

likeReq.Like = 1
likeReq.UserID = extData.UserID

err = bc.BlogSvc.CreateLikeSvc(id,likeReq,extData.FullName)
if err != nil {

if errors.Is(err,model.ErrUserNotFound) || errors.Is(err,model.ErrBlogNotFound) {
return helper.ResponseFormatter[any](ctx,fiber.StatusNotFound,err,err.Error(),nil,nil)
}

if errors.Is(err,model.ErrInvalidRequest) || errors.Is(err,model.ErrAlreadyLikeBlog) {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusCreated,nil,"Success Like",nil,nil)
}

// UnLike responsible to deleting a like by id / unliking a blog
func (bc *BlogController) UnLike(ctx *fiber.Ctx) error {return nil}
func (bc *BlogController) UnLike(ctx *fiber.Ctx) error {
blogID,err := ctx.ParamsInt("id",0)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

if blogID == 0 {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,nil,model.ErrBlogNotFound.Error(),nil,nil)
}

likeID,err := ctx.ParamsInt("like_id",0)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

if likeID == 0 {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,nil,model.ErrLikeNotFound.Error(),nil,nil)
}

data := ctx.Locals(model.KeyJWTValidAccess)
extData,err := util.ExtractPayloadJWT(data)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

err = bc.BlogSvc.DeleteLikeSvc(blogID,likeID,extData.UserID)
if err != nil {
if errors.Is(err,model.ErrBlogNotFound) || errors.Is(err,model.ErrLikeNotFound) {
return helper.ResponseFormatter[any](ctx,fiber.StatusNotFound,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusInternalServerError,err,err.Error(),nil,nil)
}

return helper.ResponseFormatter[any](ctx,fiber.StatusOK,nil,"Success UnLike",nil,nil)
}
19 changes: 14 additions & 5 deletions infrastructure/http.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package infrastructure

import (
"time"

"github.com/PickHD/pickablog/application"
"github.com/PickHD/pickablog/helper"
m "github.com/PickHD/pickablog/middleware"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/limiter"
)

// ServeHTTP is wrapper function to start the apps infra in HTTP mode
Expand Down Expand Up @@ -34,7 +37,13 @@ func setupRouter(app *application.App) {
v1.Post("/auth/register",dep.AuthController.RegisterAuthor)
v1.Get("/auth/google/login",dep.AuthController.GoogleLogin)
v1.Get("/auth/google/callback",dep.AuthController.GoogleLoginCallback)
v1.Post("/auth/login",dep.AuthController.Login)
v1.Post("/auth/login",limiter.New(limiter.Config{
Expiration: 15 * time.Minute,
Max: 5,
LimitReached: func (ctx *fiber.Ctx) error {
return helper.ResponseFormatter[any](ctx,fiber.StatusTooManyRequests,nil,"Login Attempts already reached the limit, tell our super admin about resetting a password, Thank you",nil,nil)
},
}),dep.AuthController.Login)
}

// TAG SECTION
Expand Down Expand Up @@ -64,12 +73,12 @@ func setupRouter(app *application.App) {
// BLOG COMMENT SECTION
v1.Post("/blog/:id/comment",m.ValidateJWTMiddleware,dep.BlogController.CreateComment)
v1.Put("/blog/:id/comment/:comment_id",m.ValidateJWTMiddleware,dep.BlogController.UpdateComment)
v1.Get("/blog/:id/comment",m.ValidateJWTMiddleware,dep.BlogController.ListBlog)
v1.Delete("/blog/:id/:comment_id",m.ValidateJWTMiddleware,dep.BlogController.DeleteComment)
v1.Get("/blog/:id/comment",m.ValidateJWTMiddleware,dep.BlogController.ListComment)
v1.Delete("/blog/:id/comment/:comment_id",m.ValidateJWTMiddleware,dep.BlogController.DeleteComment)

// BLOG LIKE SECTION
v1.Post("/blog/:id/like",m.ValidateJWTMiddleware,dep.BlogController.Like)
v1.Delete("/blog/:id/unlike",m.ValidateJWTMiddleware,dep.BlogController.UnLike)
v1.Get("/blog/:id/like",m.ValidateJWTMiddleware,dep.BlogController.Like)
v1.Delete("/blog/:id/like/:like_id",m.ValidateJWTMiddleware,dep.BlogController.UnLike)
}
}

Expand Down
6 changes: 6 additions & 0 deletions model/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ var (
ErrInvalidPassword = errors.New("invalid password")
// ErrMismatchLogin occurs when user trying mismatch login method
ErrMismatchLogin = errors.New("mismatch login, please use endpoint /api/v1/auth/google/login")
// ErrAlreadyLikeBlog occurs when user trying to liking a blog more than 1 times
ErrAlreadyLikeBlog = errors.New("already liking this blog")

// ErrRedisKeyNotExisted occurs when key provided is not existed
ErrRedisKeyNotExisted = errors.New("keys not existed")
Expand All @@ -54,4 +56,8 @@ var (

// ErrForbiddenDeleteSelf occurs when user trying deleting their account by self
ErrForbiddenDeleteSelf = errors.New("forbidden delete account self, make sure the id is corrent")
// ErrForbiddenUpdate occurs when user trying updating forbidden resource
ErrForbiddenUpdate = errors.New("forbidden updating data")
// ErrForbiddenDelete occurs when user trying deleting forbidden resource
ErrForbiddenDelete = errors.New("forbidden deleteing data")
)
2 changes: 1 addition & 1 deletion repository/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func (cr *CommentRepository) Create(blogID int, req model.CommentRequest,created
return err
}

qInsert := `INSERT INTO comments (comment,article_id,user_id,created_by) VALUES ($1,$2,$3,$4) RETURNING id`
qInsert := `INSERT INTO comments (id,comment,article_id,user_id,created_by) VALUES (nextval('comment_seq'),$1,$2,$3,$4) RETURNING id`

var commentID int
err = tx.QueryRow(cr.Context,qInsert,req.Comment,blogID,req.UserID,createdBy).Scan(&commentID)
Expand Down
Loading

0 comments on commit 70f09e6

Please sign in to comment.