Skip to content

Commit

Permalink
Merge pull request #14 from PickHD/feat/crud-blog
Browse files Browse the repository at this point in the history
Implement CRUD blog
  • Loading branch information
PickHD committed Apr 10, 2022
2 parents a316f8c + dda2eb8 commit 8948130
Show file tree
Hide file tree
Showing 12 changed files with 915 additions and 16 deletions.
28 changes: 28 additions & 0 deletions application/dependency.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Dependency struct {
AuthController controller.IAuthController
TagController controller.ITagController
UserController controller.IUserController
BlogController controller.IBlogController
}

// SetupDependencyInjection is a function to set up dependencies
Expand All @@ -22,6 +23,7 @@ func SetupDependencyInjection(app *App) *Dependency {
AuthController: setupAuthDependency(app),
TagController: setupTagDependency(app),
UserController: setupUserDependency(app),
BlogController: setupBlogDependency(app),
}
}

Expand Down Expand Up @@ -140,4 +142,30 @@ func setupUserDependency(app *App) *controller.UserController {
}

return userCtrl
}

// setupBlogDependency is a function to set up dependencies to be used inside blog controller layer
func setupBlogDependency(app *App) *controller.BlogController {
blogRepo := &repository.BlogRepository{
Context: app.Context,
Config: app.Config,
Logger: app.Logger,
DB: app.DB,
}

blogSvc := &service.BlogService{
Context: app.Context,
Config: app.Config,
Logger: app.Logger,
BlogRepo: blogRepo,
}

blogCtrl := &controller.BlogController{
Context: app.Context,
Config: app.Config,
Logger: app.Logger,
BlogSvc: blogSvc,
}

return blogCtrl
}
201 changes: 201 additions & 0 deletions controller/blog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
package controller

import (
"context"
"errors"
"strconv"
"strings"

"github.com/PickHD/pickablog/config"
"github.com/PickHD/pickablog/helper"
"github.com/PickHD/pickablog/model"
"github.com/PickHD/pickablog/service"
"github.com/PickHD/pickablog/util"
"github.com/gofiber/fiber/v2"
"github.com/sirupsen/logrus"
)

type (
// IBlogController is an interface that has all the function to be implemented inside blog controller
IBlogController interface {
CreateBlog(ctx *fiber.Ctx) error
ListBlog(ctx *fiber.Ctx) error
DetailBlog(ctx *fiber.Ctx) error
UpdateBlog(ctx *fiber.Ctx) error
DeleteBlog(ctx *fiber.Ctx) error
}

// BlogController is an app blog struct that consists of all the dependencies needed for blog controller
BlogController struct {
Context context.Context
Config *config.Configuration
Logger *logrus.Logger
BlogSvc service.IBlogService
}
)
// CreateBlog responsible to creating a blog from controller layer
func (bc *BlogController) CreateBlog(ctx *fiber.Ctx) error {
var blogReq model.CreateBlogRequest

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(&blogReq); err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

blogReq.UserID = extData.UserID

err = bc.BlogSvc.CreateBlogSvc(blogReq,extData.FullName)
if err != 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 Blog",nil,nil)
}

// ListBlog responsible to listing/filter/search a blogs from controller layer
func (bc *BlogController) ListBlog(ctx *fiber.Ctx) error {
var (
page = 1
size = 10
order = "ASC"
field = "id"
search = ""
filter model.FilterBlogRequest
)

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
}
}

if sr := ctx.Query("s",""); sr != "" {
if len(sr) > 0 {
search = strings.Trim(sr," ")
}
}

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

data,meta,err := bc.BlogSvc.GetAllBlogSvc(page,size,order,field,search,filter)
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 Blogs",data,meta)
}

// DetailBlog responsible to getting detail a blog by slug from controller layer
func (bc *BlogController) DetailBlog(ctx *fiber.Ctx) error {
slug := ctx.Params("slug","")

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

data,err := bc.BlogSvc.GetBlogBySlugSvc(slug)
if err != nil {
if errors.Is(err,model.ErrBlogNotFound) {
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 Get Blog",data,nil)
}

// UpdateBlog responsible to updating a blog by id from controller layer
func (bc *BlogController) UpdateBlog(ctx *fiber.Ctx) error {
var blogReq model.UpdateBlogRequest

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(&blogReq); err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
}

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)
}

blogReq.UserID = extData.UserID

err = bc.BlogSvc.UpdateBlogSvc(id,blogReq,extData.FullName)
if err != nil {
if 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.ErrEmailExisted) {
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 Blog",nil,nil)
}

// DeleteBlog responsible to deleting a blog by ud from controller layer
func (bc *BlogController) DeleteBlog(ctx *fiber.Ctx) error {
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)
}

err = bc.BlogSvc.DeleteBlogSvc(id)
if err != nil {
if errors.Is(err,model.ErrBlogNotFound) {
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 Blog",nil,nil)
}
12 changes: 6 additions & 6 deletions controller/tag.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type (
// ITagController is an interface that has all the function to be implemented inside tag controller
ITagController interface {
CreateTag(ctx *fiber.Ctx) error
GetAllTag(ctx *fiber.Ctx) error
ListTag(ctx *fiber.Ctx) error
UpdateTag(ctx *fiber.Ctx) error
DeleteTag(ctx *fiber.Ctx) error
}
Expand All @@ -34,7 +34,7 @@ type (

)

// CreateTag responsible to creating a tag of article from controller layer
// CreateTag responsible to creating a tag of blog from controller layer
func (tc *TagController) CreateTag(ctx *fiber.Ctx) error {
var tagReq model.CreateTagRequest

Expand All @@ -60,8 +60,8 @@ func (tc *TagController) CreateTag(ctx *fiber.Ctx) error {
return helper.ResponseFormatter[any](ctx,fiber.StatusCreated,nil,"Success Create Tag",nil,nil)
}

// GetAllTag responsible to getting all tag of article from controller layer
func (tc *TagController) GetAllTag(ctx *fiber.Ctx) error {
// ListTag responsible to getting all tag of blog from controller layer
func (tc *TagController) ListTag(ctx *fiber.Ctx) error {
var (
page = 1
size = 10
Expand Down Expand Up @@ -110,7 +110,7 @@ func (tc *TagController) GetAllTag(ctx *fiber.Ctx) error {
return helper.ResponseFormatter[any](ctx,fiber.StatusOK,nil,"Success Getting all Tags",data,meta)
}

// UpdateTag responsible to updating a tag of article by id from controller layer
// UpdateTag responsible to updating a tag of blog by id from controller layer
func (tc *TagController) UpdateTag(ctx *fiber.Ctx) error {
var tagReq model.UpdateTagRequest

Expand Down Expand Up @@ -149,7 +149,7 @@ func (tc *TagController) UpdateTag(ctx *fiber.Ctx) error {
return helper.ResponseFormatter[any](ctx,fiber.StatusOK,nil,"Success Update Tags",nil,nil)
}

// DeleteTag responsible to deleting a tag of article by id from controller layer
// DeleteTag responsible to deleting a tag of blog by id from controller layer
func (tc *TagController) DeleteTag(ctx *fiber.Ctx) error {
id,err := ctx.ParamsInt("id",0)
if err != nil {
Expand Down
12 changes: 6 additions & 6 deletions controller/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import (
type (
// IUserController is an interface that has all the function to be implemented inside user controller
IUserController interface {
GetAllUser(ctx *fiber.Ctx) error
GetUser(ctx *fiber.Ctx) error
ListUser(ctx *fiber.Ctx) error
DetailUser(ctx *fiber.Ctx) error
UpdateUser(ctx *fiber.Ctx) error
DeleteUser(ctx *fiber.Ctx) error
}
Expand All @@ -33,8 +33,8 @@ type (
}
)

// GetAllUser responsible to getting all user from controller layer
func (uc *UserController) GetAllUser(ctx *fiber.Ctx) error {
// ListUser responsible to getting all user from controller layer
func (uc *UserController) ListUser(ctx *fiber.Ctx) error {
var (
page = 1
size = 10
Expand Down Expand Up @@ -83,8 +83,8 @@ func (uc *UserController) GetAllUser(ctx *fiber.Ctx) error {
return helper.ResponseFormatter[any](ctx,fiber.StatusOK,nil,"Success Getting all Users",data,meta)
}

// GetUser responsible to get a user by id from controller layer
func (uc *UserController) GetUser(ctx *fiber.Ctx) error {
// DetailUser responsible to get a user by id from controller layer
func (uc *UserController) DetailUser(ctx *fiber.Ctx) error {
id,err := ctx.ParamsInt("id",0)
if err != nil {
return helper.ResponseFormatter[any](ctx,fiber.StatusBadRequest,err,err.Error(),nil,nil)
Expand Down
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ require (
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/gosimple/slug v1.12.0 // indirect
github.com/gosimple/unidecode v1.0.1 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.11.0 // indirect
github.com/jackc/pgio v1.0.0 // indirect
Expand All @@ -27,6 +29,7 @@ require (
github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
github.com/jackc/pgtype v1.10.0 // indirect
github.com/klauspost/compress v1.15.1 // indirect
github.com/lib/pq v1.10.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.34.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gosimple/slug v1.12.0 h1:xzuhj7G7cGtd34NXnW/yF0l+AGNfWqwgh/IXgFy7dnc=
github.com/gosimple/slug v1.12.0/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ=
github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o=
github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
Expand Down Expand Up @@ -192,6 +196,8 @@ github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
Expand Down
5 changes: 5 additions & 0 deletions helper/time.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package helper

const (
StandardLayout = "2006-01-02"
)
Loading

0 comments on commit 8948130

Please sign in to comment.