From eb9d61422688965e804c9e8012105f8ccce305ba Mon Sep 17 00:00:00 2001 From: hanif salafi Date: Sun, 5 May 2024 16:24:49 +0700 Subject: [PATCH] feat: update article categories, user roles, ppid data & ppid data files --- .../entity/article_categories.entity.go | 8 +- app/database/entity/articles.entity.go | 5 +- .../entity/user_role_level_details.entity.go | 12 + app/database/index.database.go | 1 + .../article_categories.module.go | 2 + .../article_categories.controller.go | 48 +- .../mapper/article_categories.mapper.go | 2 - .../article_categories.repository.go | 13 +- .../request/article_categories.request.go | 38 +- .../response/article_categories.response.go | 22 +- .../service/article_categories.service.go | 169 ++++- app/module/articles/articles.module.go | 2 + .../controller/articles.controller.go | 48 +- app/module/articles/mapper/articles.mapper.go | 45 +- .../repository/articles.repository.go | 20 +- .../articles/request/articles.request.go | 12 + .../articles/response/articles.response.go | 31 +- .../articles/service/articles.service.go | 179 +++++- .../ppid_data_categories.controller.go | 8 +- .../ppid_data_categories.module.go | 4 +- .../service/ppid_data_categories.service.go | 6 +- .../mapper/ppid_data_files.mapper.go | 6 +- .../controller/controller.go | 13 + .../user_role_level_details.controller.go | 181 ++++++ .../mapper/user_role_level_details.mapper.go | 20 + .../user_role_level_details.repository.go | 69 ++ .../user_role_level_details.request.go | 51 ++ .../user_role_level_details.response.go | 12 + .../user_role_level_details.service.go | 72 +++ .../user_role_level_details.module.go | 53 ++ .../repository/user_roles.repository.go | 7 +- .../user_roles/request/user_roles.request.go | 22 +- .../user_roles/service/user_roles.service.go | 43 +- config/toml/config.toml | 2 +- docs/swagger/docs.go | 588 ++++++++++++++++-- docs/swagger/swagger.json | 588 ++++++++++++++++-- docs/swagger/swagger.yaml | 353 ++++++++++- main.go | 2 + 38 files changed, 2484 insertions(+), 273 deletions(-) create mode 100644 app/database/entity/user_role_level_details.entity.go create mode 100644 app/module/user_role_level_details/controller/controller.go create mode 100644 app/module/user_role_level_details/controller/user_role_level_details.controller.go create mode 100644 app/module/user_role_level_details/mapper/user_role_level_details.mapper.go create mode 100644 app/module/user_role_level_details/repository/user_role_level_details.repository.go create mode 100644 app/module/user_role_level_details/request/user_role_level_details.request.go create mode 100644 app/module/user_role_level_details/response/user_role_level_details.response.go create mode 100644 app/module/user_role_level_details/service/user_role_level_details.service.go create mode 100644 app/module/user_role_level_details/user_role_level_details.module.go diff --git a/app/database/entity/article_categories.entity.go b/app/database/entity/article_categories.entity.go index c8f7e12..6b287a8 100644 --- a/app/database/entity/article_categories.entity.go +++ b/app/database/entity/article_categories.entity.go @@ -7,13 +7,11 @@ type ArticleCategories struct { Title string `json:"title" gorm:"type:varchar"` Description string `json:"description" gorm:"type:varchar"` ThumbnailPath *string `json:"thumbnail_path" gorm:"type:varchar"` - ThumbnailUrl *string `json:"thumbnail_url" gorm:"type:varchar"` - ParentId int `json:"parent_id" gorm:"type:int4"` - CreatedById *int `json:"created_by_id" gorm:"type:int4"` - StatusId *int `json:"status_id" gorm:"type:int4;default:1"` + ParentId *int `json:"parent_id" gorm:"type:int4"` + CreatedById *uint `json:"created_by_id" gorm:"type:int4"` + StatusId int `json:"status_id" gorm:"type:int4;default:1"` IsPublish *bool `json:"is_publish" gorm:"type:bool;default:false"` PublishedAt *time.Time `json:"published_at" gorm:"type:timestamp"` - IsEnabled *bool `json:"is_enabled" gorm:"type:bool;default:false"` IsActive *bool `json:"is_active" gorm:"type:bool;default:true"` CreatedAt time.Time `json:"created_at" gorm:"default:now()"` UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"` diff --git a/app/database/entity/articles.entity.go b/app/database/entity/articles.entity.go index 44b36da..f7df296 100644 --- a/app/database/entity/articles.entity.go +++ b/app/database/entity/articles.entity.go @@ -7,13 +7,14 @@ type Articles struct { Title string `json:"title" gorm:"type:varchar"` Slug string `json:"slug" gorm:"type:varchar"` Description string `json:"description" gorm:"type:varchar"` + CategoryId int `json:"category_id" gorm:"type:int4"` HtmlDescription string `json:"html_description" gorm:"type:varchar"` TypeId int `json:"type_id" gorm:"type:int4"` Tags string `json:"tags" gorm:"type:varchar"` + ThumbnailName *string `json:"thumbnail_name" gorm:"type:varchar"` ThumbnailPath *string `json:"thumbnail_path" gorm:"type:varchar"` - ThumbnailUrl *string `json:"thumbnail_url" gorm:"type:varchar"` PageUrl *string `json:"page_url" gorm:"type:varchar"` - CreatedById *int `json:"created_by_id" gorm:"type:int4"` + CreatedById *uint `json:"created_by_id" gorm:"type:int4"` ShareCount *int `json:"share_count" gorm:"type:int4"` ViewCount *int `json:"view_count" gorm:"type:int4"` DownloadCount *int `json:"download_count" gorm:"type:int4"` diff --git a/app/database/entity/user_role_level_details.entity.go b/app/database/entity/user_role_level_details.entity.go new file mode 100644 index 0000000..b37d71f --- /dev/null +++ b/app/database/entity/user_role_level_details.entity.go @@ -0,0 +1,12 @@ +package entity + +import "time" + +type UserRoleLevelDetails struct { + ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"` + UserRoleId uint `json:"user_role_id" gorm:"type:int4"` + UserLevelId uint `json:"user_level_id" gorm:"type:int4"` + IsActive *bool `json:"is_active" gorm:"type:bool;default:true"` + CreatedAt time.Time `json:"created_at" gorm:"default:now()"` + UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"` +} diff --git a/app/database/index.database.go b/app/database/index.database.go index 403fd76..33a38f2 100644 --- a/app/database/index.database.go +++ b/app/database/index.database.go @@ -86,6 +86,7 @@ func Models() []interface{} { entity.UserRoles{}, entity.UserRoleAccesses{}, entity.Users{}, + entity.UserRoleLevelDetails{}, } } diff --git a/app/module/article_categories/article_categories.module.go b/app/module/article_categories/article_categories.module.go index 5cd2cfd..c0978e1 100644 --- a/app/module/article_categories/article_categories.module.go +++ b/app/module/article_categories/article_categories.module.go @@ -48,6 +48,8 @@ func (_i *ArticleCategoriesRouter) RegisterArticleCategoriesRoutes() { router.Get("/:id", articleCategoriesController.Show) router.Post("/", articleCategoriesController.Save) router.Put("/:id", articleCategoriesController.Update) + router.Post("/thumbnail/:id", articleCategoriesController.SaveThumbnail) + router.Get("/thumbnail/viewer/:id", articleCategoriesController.Viewer) router.Delete("/:id", articleCategoriesController.Delete) }) } diff --git a/app/module/article_categories/controller/article_categories.controller.go b/app/module/article_categories/controller/article_categories.controller.go index e2c8c8d..dac1ca5 100644 --- a/app/module/article_categories/controller/article_categories.controller.go +++ b/app/module/article_categories/controller/article_categories.controller.go @@ -19,8 +19,10 @@ type ArticleCategoriesController interface { All(c *fiber.Ctx) error Show(c *fiber.Ctx) error Save(c *fiber.Ctx) error + SaveThumbnail(c *fiber.Ctx) error Update(c *fiber.Ctx) error Delete(c *fiber.Ctx) error + Viewer(c *fiber.Ctx) error } func NewArticleCategoriesController(articleCategoriesService service.ArticleCategoriesService) ArticleCategoriesController { @@ -51,7 +53,6 @@ func (_i *articleCategoriesController) All(c *fiber.Ctx) error { Title: c.Query("title"), Description: c.Query("description"), ParentId: c.Query("parentId"), - IsEnabled: c.Query("isEnabled"), IsPublish: c.Query("isPublish"), StatusId: c.Query("statusId"), } @@ -105,6 +106,7 @@ func (_i *articleCategoriesController) Show(c *fiber.Ctx) error { // @Description API for create ArticleCategories // @Tags Article Categories // @Security Bearer +// @Param Authorization header string true "Insert your access token" default(Bearer ) // @Param payload body request.ArticleCategoriesCreateRequest true "Required payload" // @Success 200 {object} response.Response // @Failure 400 {object} response.BadRequestError @@ -117,7 +119,8 @@ func (_i *articleCategoriesController) Save(c *fiber.Ctx) error { return err } - err := _i.articleCategoriesService.Save(*req) + authToken := c.Get("Authorization") + dataResult, err := _i.articleCategoriesService.Save(*req, authToken) if err != nil { return err } @@ -125,6 +128,32 @@ func (_i *articleCategoriesController) Save(c *fiber.Ctx) error { return utilRes.Resp(c, utilRes.Response{ Success: true, Messages: utilRes.Messages{"ArticleCategories successfully created"}, + Data: dataResult, + }) +} + +// SaveThumbnail PpidDataCategories +// @Summary Upload ArticleCategories Thumbnail +// @Description API for Upload ArticleCategories Thumbnail +// @Tags Article Categories +// @Security Bearer +// @Produce json +// @Param files formData file true "Upload thumbnail" +// @Param id path int true "ArticleCategories ID" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /article-categories/thumbnail/{id} [post] +func (_i *articleCategoriesController) SaveThumbnail(c *fiber.Ctx) error { + err := _i.articleCategoriesService.SaveThumbnail(c) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Thumbnail of ArticleCategories successfully created"}, }) } @@ -189,3 +218,18 @@ func (_i *articleCategoriesController) Delete(c *fiber.Ctx) error { Messages: utilRes.Messages{"ArticleCategories successfully deleted"}, }) } + +// Viewer ArticleCategories +// @Summary Viewer ArticleCategories +// @Description API for View Thumbnail of ArticleCategories +// @Tags Article Categories +// @Security Bearer +// @Param id path string true "ArticleCategories ID" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /article-categories/thumbnail/viewer/{id} [get] +func (_i *articleCategoriesController) Viewer(c *fiber.Ctx) error { + return _i.articleCategoriesService.Viewer(c) +} diff --git a/app/module/article_categories/mapper/article_categories.mapper.go b/app/module/article_categories/mapper/article_categories.mapper.go index e3ccdad..97177a2 100644 --- a/app/module/article_categories/mapper/article_categories.mapper.go +++ b/app/module/article_categories/mapper/article_categories.mapper.go @@ -12,13 +12,11 @@ func ArticleCategoriesResponseMapper(articleCategoriesReq *entity.ArticleCategor Title: articleCategoriesReq.Title, Description: articleCategoriesReq.Description, ThumbnailPath: articleCategoriesReq.ThumbnailPath, - ThumbnailUrl: articleCategoriesReq.ThumbnailUrl, ParentId: articleCategoriesReq.ParentId, CreatedById: articleCategoriesReq.CreatedById, StatusId: articleCategoriesReq.StatusId, IsPublish: articleCategoriesReq.IsPublish, PublishedAt: articleCategoriesReq.PublishedAt, - IsEnabled: articleCategoriesReq.IsEnabled, IsActive: articleCategoriesReq.IsActive, CreatedAt: articleCategoriesReq.CreatedAt, UpdatedAt: articleCategoriesReq.UpdatedAt, diff --git a/app/module/article_categories/repository/article_categories.repository.go b/app/module/article_categories/repository/article_categories.repository.go index cea50bd..6153bff 100644 --- a/app/module/article_categories/repository/article_categories.repository.go +++ b/app/module/article_categories/repository/article_categories.repository.go @@ -17,7 +17,7 @@ type articleCategoriesRepository struct { type ArticleCategoriesRepository interface { GetAll(req request.ArticleCategoriesQueryRequest) (articleCategoriess []*entity.ArticleCategories, paging paginator.Pagination, err error) FindOne(id uint) (articleCategories *entity.ArticleCategories, err error) - Create(articleCategories *entity.ArticleCategories) (err error) + Create(articleCategories *entity.ArticleCategories) (articleCategoriesReturn *entity.ArticleCategories, err error) Update(id uint, articleCategories *entity.ArticleCategories) (err error) Delete(id uint) (err error) } @@ -46,12 +46,6 @@ func (_i *articleCategoriesRepository) GetAll(req request.ArticleCategoriesQuery if req.ParentId != nil { query = query.Where("parent_id = ?", req.ParentId) } - if req.CreatedById != nil { - query = query.Where("created_by_id = ?", req.CreatedById) - } - if req.IsEnabled != nil { - query = query.Where("is_enabled = ?", req.IsEnabled) - } if req.IsPublish != nil { query = query.Where("is_publish = ?", req.IsPublish) } @@ -89,8 +83,9 @@ func (_i *articleCategoriesRepository) FindOne(id uint) (articleCategories *enti return articleCategories, nil } -func (_i *articleCategoriesRepository) Create(articleCategories *entity.ArticleCategories) (err error) { - return _i.DB.DB.Create(articleCategories).Error +func (_i *articleCategoriesRepository) Create(articleCategories *entity.ArticleCategories) (articleCategoriesReturn *entity.ArticleCategories, err error) { + result := _i.DB.DB.Create(articleCategories) + return articleCategories, result.Error } func (_i *articleCategoriesRepository) Update(id uint, articleCategories *entity.ArticleCategories) (err error) { diff --git a/app/module/article_categories/request/article_categories.request.go b/app/module/article_categories/request/article_categories.request.go index a0a8898..3a90951 100644 --- a/app/module/article_categories/request/article_categories.request.go +++ b/app/module/article_categories/request/article_categories.request.go @@ -17,17 +17,14 @@ type ArticleCategoriesQueryRequest struct { ParentId *int `json:"parentId"` StatusId *int `json:"statusId"` IsPublish *bool `json:"isPublish"` - CreatedById *int `json:"createdById"` - IsEnabled *bool `json:"isEnabled"` Pagination *paginator.Pagination `json:"pagination"` } type ArticleCategoriesCreateRequest struct { Title string `json:"title" validate:"required"` Description string `json:"description" validate:"required"` - ParentId int `json:"parentId" validate:"required"` StatusId int `json:"statusId" validate:"required"` - IsEnabled bool `json:"isEnabled" validate:"required"` + ParentId *int `json:"parentId"` } func (req ArticleCategoriesCreateRequest) ToEntity() *entity.ArticleCategories { @@ -35,20 +32,18 @@ func (req ArticleCategoriesCreateRequest) ToEntity() *entity.ArticleCategories { Title: req.Title, Description: req.Description, ParentId: req.ParentId, + StatusId: req.StatusId, } } type ArticleCategoriesUpdateRequest struct { - ID uint `json:"id" validate:"required"` - Title string `json:"title" validate:"required"` - Description string `json:"description" validate:"required"` - ThumbnailPath string `json:"thumbnailPath" validate:"required"` - ThumbnailUrl string `json:"thumbnailUrl" validate:"required"` - ParentId int `json:"parentId" validate:"required"` - StatusId *int `json:"statusId"` - IsPublish *bool `json:"isPublish"` - PublishedAt *time.Time `json:"publishedAt"` - IsEnabled *bool `json:"isEnabled"` + ID uint `json:"id" validate:"required"` + Title string `json:"title" validate:"required"` + Description string `json:"description" validate:"required"` + StatusId int `json:"statusId" validate:"required"` + ParentId *int `json:"parentId"` + IsPublish *bool `json:"isPublish"` + PublishedAt *time.Time `json:"publishedAt"` } func (req ArticleCategoriesUpdateRequest) ToEntity() *entity.ArticleCategories { @@ -60,7 +55,6 @@ func (req ArticleCategoriesUpdateRequest) ToEntity() *entity.ArticleCategories { StatusId: req.StatusId, IsPublish: req.IsPublish, PublishedAt: req.PublishedAt, - IsEnabled: req.IsEnabled, UpdatedAt: time.Now(), } } @@ -70,9 +64,7 @@ type ArticleCategoriesQueryRequestContext struct { Description string `json:"description"` ParentId string `json:"parentId"` StatusId string `json:"statusId"` - CreatedById string `json:"created_by_id"` IsPublish string `json:"isPublish"` - IsEnabled string `json:"isEnabled"` } func (req ArticleCategoriesQueryRequestContext) ToParamRequest() ArticleCategoriesQueryRequest { @@ -90,24 +82,12 @@ func (req ArticleCategoriesQueryRequestContext) ToParamRequest() ArticleCategori request.ParentId = &parentId } } - if isEnabledStr := req.IsEnabled; isEnabledStr != "" { - isEnabled, err := strconv.ParseBool(isEnabledStr) - if err == nil { - request.IsEnabled = &isEnabled - } - } if isPublishStr := req.IsPublish; isPublishStr != "" { isPublish, err := strconv.ParseBool(isPublishStr) if err == nil { request.IsPublish = &isPublish } } - if createdByIdStr := req.CreatedById; createdByIdStr != "" { - createdById, err := strconv.Atoi(createdByIdStr) - if err == nil { - request.CreatedById = &createdById - } - } if statusIdStr := req.StatusId; statusIdStr != "" { statusId, err := strconv.Atoi(statusIdStr) if err == nil { diff --git a/app/module/article_categories/response/article_categories.response.go b/app/module/article_categories/response/article_categories.response.go index bedb138..5d24467 100644 --- a/app/module/article_categories/response/article_categories.response.go +++ b/app/module/article_categories/response/article_categories.response.go @@ -6,15 +6,15 @@ type ArticleCategoriesResponse struct { ID uint `json:"id"` Title string `json:"title"` Description string `json:"description"` - ThumbnailPath *string `json:"thumbnail_path"` - ThumbnailUrl *string `json:"thumbnail_url"` - ParentId int `json:"parent_id"` - CreatedById *int `json:"created_by_id"` - StatusId *int `json:"status_id"` - IsPublish *bool `json:"is_publish"` - PublishedAt *time.Time `json:"published_at"` - IsEnabled *bool `json:"is_enabled"` - IsActive *bool `json:"is_active"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + ThumbnailPath *string `json:"thumbnailPath"` + ThumbnailUrl *string `json:"thumbnailUrl"` + ParentId *int `json:"parentId"` + CreatedById *uint `json:"createdById"` + StatusId int `json:"statusId"` + IsPublish *bool `json:"isPublish"` + PublishedAt *time.Time `json:"publishedAt"` + IsEnabled *bool `json:"isEnabled"` + IsActive *bool `json:"isActive"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } diff --git a/app/module/article_categories/service/article_categories.service.go b/app/module/article_categories/service/article_categories.service.go index 0477463..bd3c4cc 100644 --- a/app/module/article_categories/service/article_categories.service.go +++ b/app/module/article_categories/service/article_categories.service.go @@ -1,35 +1,56 @@ package service import ( + "context" + "github.com/gofiber/fiber/v2" + "github.com/minio/minio-go/v7" "github.com/rs/zerolog" + "go-humas-be/app/database/entity" "go-humas-be/app/module/article_categories/mapper" "go-humas-be/app/module/article_categories/repository" "go-humas-be/app/module/article_categories/request" "go-humas-be/app/module/article_categories/response" + usersRepository "go-humas-be/app/module/users/repository" + minioStorage "go-humas-be/config/config" "go-humas-be/utils/paginator" + utilSvc "go-humas-be/utils/service" + "io" + "log" + "math/rand" + "mime" + "path/filepath" + "strconv" + "strings" + "time" ) // ArticleCategoriesService type articleCategoriesService struct { - Repo repository.ArticleCategoriesRepository - Log zerolog.Logger + Repo repository.ArticleCategoriesRepository + UsersRepo usersRepository.UsersRepository + MinioStorage *minioStorage.MinioStorage + Log zerolog.Logger } // ArticleCategoriesService define interface of IArticleCategoriesService type ArticleCategoriesService interface { All(req request.ArticleCategoriesQueryRequest) (articleCategories []*response.ArticleCategoriesResponse, paging paginator.Pagination, err error) Show(id uint) (articleCategories *response.ArticleCategoriesResponse, err error) - Save(req request.ArticleCategoriesCreateRequest) (err error) + Save(req request.ArticleCategoriesCreateRequest, authToken string) (articleCategories *entity.ArticleCategories, err error) + SaveThumbnail(c *fiber.Ctx) (err error) Update(id uint, req request.ArticleCategoriesUpdateRequest) (err error) Delete(id uint) error + Viewer(c *fiber.Ctx) error } // NewArticleCategoriesService init ArticleCategoriesService -func NewArticleCategoriesService(repo repository.ArticleCategoriesRepository, log zerolog.Logger) ArticleCategoriesService { +func NewArticleCategoriesService(repo repository.ArticleCategoriesRepository, usersRepo usersRepository.UsersRepository, minioStorage *minioStorage.MinioStorage, log zerolog.Logger) ArticleCategoriesService { return &articleCategoriesService{ - Repo: repo, - Log: log, + Repo: repo, + UsersRepo: usersRepo, + MinioStorage: minioStorage, + Log: log, } } @@ -56,10 +77,80 @@ func (_i *articleCategoriesService) Show(id uint) (articleCategories *response.A return mapper.ArticleCategoriesResponseMapper(result), nil } -func (_i *articleCategoriesService) Save(req request.ArticleCategoriesCreateRequest) (err error) { +func (_i *articleCategoriesService) Save(req request.ArticleCategoriesCreateRequest, authToken string) (articleCategories *entity.ArticleCategories, err error) { _i.Log.Info().Interface("data", req).Msg("") + newReq := req.ToEntity() - return _i.Repo.Create(req.ToEntity()) + createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) + newReq.CreatedById = &createdBy.ID + + return _i.Repo.Create(newReq) +} + +func (_i *articleCategoriesService) SaveThumbnail(c *fiber.Ctx) (err error) { + + id, err := strconv.ParseUint(c.Params("id"), 10, 0) + if err != nil { + return err + } + + bucketName := _i.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName + + form, err := c.MultipartForm() + if err != nil { + return err + } + files := form.File["files"] + + // Create minio connection. + minioClient, err := _i.MinioStorage.ConnectMinio() + if err != nil { + // Return status 500 and minio connection error. + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": true, + "msg": err.Error(), + }) + } + + // Iterasi semua file yang diunggah + for _, file := range files { + + _i.Log.Info().Str("timestamp", time.Now(). + Format(time.RFC3339)).Str("Service:Resource", "Uploader:: loop1"). + Interface("data", file).Msg("") + + src, err := file.Open() + if err != nil { + return err + } + defer src.Close() + + filename := filepath.Base(file.Filename) + filenameWithoutExt := filepath.Clean(filename[:len(filename)-len(filepath.Ext(filename))]) + extension := filepath.Ext(file.Filename)[1:] + + rand.New(rand.NewSource(time.Now().UnixNano())) + randUniqueId := rand.Intn(1000000) + + newFilenameWithoutExt := filenameWithoutExt + "_" + strconv.Itoa(randUniqueId) + newFilename := newFilenameWithoutExt + "." + extension + objectName := "articles/category/thumbnail/" + newFilename + + findCategory, err := _i.Repo.FindOne(uint(id)) + findCategory.ThumbnailPath = &objectName + err = _i.Repo.Update(uint(id), findCategory) + if err != nil { + return err + } + + // Upload file ke MinIO + _, err = minioClient.PutObject(context.Background(), bucketName, objectName, src, file.Size, minio.PutObjectOptions{}) + if err != nil { + return err + } + } + + return } func (_i *articleCategoriesService) Update(id uint, req request.ArticleCategoriesUpdateRequest) (err error) { @@ -77,3 +168,65 @@ func (_i *articleCategoriesService) Delete(id uint) error { result.IsActive = &isActive return _i.Repo.Update(id, result) } + +func (_i *articleCategoriesService) Viewer(c *fiber.Ctx) (err error) { + id, err := strconv.ParseUint(c.Params("id"), 10, 0) + result, err := _i.Repo.FindOne(uint(id)) + if err != nil { + return err + } + + if result.ThumbnailPath == nil { + return nil + } + + ctx := context.Background() + bucketName := _i.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName + objectName := result.ThumbnailPath + + _i.Log.Info().Str("timestamp", time.Now(). + Format(time.RFC3339)).Str("Service:Resource", "Article:Uploads"). + Interface("data", objectName).Msg("") + + // Create minio connection. + minioClient, err := _i.MinioStorage.ConnectMinio() + if err != nil { + // Return status 500 and minio connection error. + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": true, + "msg": err.Error(), + }) + } + + fileContent, err := minioClient.GetObject(ctx, bucketName, *objectName, minio.GetObjectOptions{}) + if err != nil { + log.Fatalln(err) + } + defer fileContent.Close() + + contentType := mime.TypeByExtension("." + getFileExtension(*objectName)) + if contentType == "" { + contentType = "application/octet-stream" + } + + c.Set("Content-Type", contentType) + + if _, err := io.Copy(c.Response().BodyWriter(), fileContent); err != nil { + return err + } + + return +} + +func getFileExtension(filename string) string { + // split file name + parts := strings.Split(filename, ".") + + // jika tidak ada ekstensi, kembalikan string kosong + if len(parts) == 1 || (len(parts) == 2 && parts[0] == "") { + return "" + } + + // ambil ekstensi terakhir + return parts[len(parts)-1] +} diff --git a/app/module/articles/articles.module.go b/app/module/articles/articles.module.go index a8af82d..cef17a7 100644 --- a/app/module/articles/articles.module.go +++ b/app/module/articles/articles.module.go @@ -48,6 +48,8 @@ func (_i *ArticlesRouter) RegisterArticlesRoutes() { router.Get("/:id", articlesController.Show) router.Post("/", articlesController.Save) router.Put("/:id", articlesController.Update) + router.Post("/thumbnail/:id", articlesController.SaveThumbnail) + router.Get("/thumbnail/viewer/:thumbnailName", articlesController.Viewer) router.Delete("/:id", articlesController.Delete) }) } diff --git a/app/module/articles/controller/articles.controller.go b/app/module/articles/controller/articles.controller.go index e48ff0e..f630562 100644 --- a/app/module/articles/controller/articles.controller.go +++ b/app/module/articles/controller/articles.controller.go @@ -19,8 +19,10 @@ type ArticlesController interface { All(c *fiber.Ctx) error Show(c *fiber.Ctx) error Save(c *fiber.Ctx) error + SaveThumbnail(c *fiber.Ctx) error Update(c *fiber.Ctx) error Delete(c *fiber.Ctx) error + Viewer(c *fiber.Ctx) error } func NewArticlesController(articlesService service.ArticlesService) ArticlesController { @@ -51,6 +53,7 @@ func (_i *articlesController) All(c *fiber.Ctx) error { Title: c.Query("title"), Description: c.Query("description"), Tags: c.Query("tags"), + CategoryId: c.Query("categoryId"), TypeId: c.Query("typeId"), StatusId: c.Query("statusId"), IsPublish: c.Query("isPublish"), @@ -105,6 +108,7 @@ func (_i *articlesController) Show(c *fiber.Ctx) error { // @Description API for create Articles // @Tags Articles // @Security Bearer +// @Param Authorization header string true "Insert your access token" default(Bearer ) // @Param payload body request.ArticlesCreateRequest true "Required payload" // @Success 200 {object} response.Response // @Failure 400 {object} response.BadRequestError @@ -117,7 +121,8 @@ func (_i *articlesController) Save(c *fiber.Ctx) error { return err } - err := _i.articlesService.Save(*req) + authToken := c.Get("Authorization") + dataResult, err := _i.articlesService.Save(*req, authToken) if err != nil { return err } @@ -125,6 +130,32 @@ func (_i *articlesController) Save(c *fiber.Ctx) error { return utilRes.Resp(c, utilRes.Response{ Success: true, Messages: utilRes.Messages{"Articles successfully created"}, + Data: dataResult, + }) +} + +// SaveThumbnail Articles +// @Summary Save Thumbnail Articles +// @Description API for Save Thumbnail of Articles +// @Tags Articles +// @Security Bearer +// @Produce json +// @Param files formData file true "Upload thumbnail" +// @Param id path int true "Articles ID" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /articles/thumbnail/{id} [post] +func (_i *articlesController) SaveThumbnail(c *fiber.Ctx) error { + err := _i.articlesService.SaveThumbnail(c) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Success: true, + Messages: utilRes.Messages{"Thumbnail of Articles successfully created"}, }) } @@ -189,3 +220,18 @@ func (_i *articlesController) Delete(c *fiber.Ctx) error { Messages: utilRes.Messages{"Articles successfully deleted"}, }) } + +// Viewer Articles +// @Summary Viewer Articles Thumbnail +// @Description API for View Thumbnail of Article +// @Tags Articles +// @Security Bearer +// @Param thumbnailName path string true "Articles Thumbnail Name" +// @Success 200 {object} response.Response +// @Failure 400 {object} response.BadRequestError +// @Failure 401 {object} response.UnauthorizedError +// @Failure 500 {object} response.InternalServerError +// @Router /articles/thumbnail/viewer/{thumbnailName} [get] +func (_i *articlesController) Viewer(c *fiber.Ctx) error { + return _i.articlesService.Viewer(c) +} diff --git a/app/module/articles/mapper/articles.mapper.go b/app/module/articles/mapper/articles.mapper.go index 59bbb61..ae829a0 100644 --- a/app/module/articles/mapper/articles.mapper.go +++ b/app/module/articles/mapper/articles.mapper.go @@ -6,29 +6,32 @@ import ( ) func ArticlesResponseMapper(articlesReq *entity.Articles) (articlesRes *res.ArticlesResponse) { + thumbnailUrl := "/articles/thumbnail/viewer/" + if articlesReq.ThumbnailName != nil { + thumbnailUrl += *articlesReq.ThumbnailName + } if articlesReq != nil { articlesRes = &res.ArticlesResponse{ - ID: articlesReq.ID, - Title: articlesReq.Title, - Slug: articlesReq.Slug, - Description: articlesReq.Description, - HtmlDescription: articlesReq.HtmlDescription, - TypeId: articlesReq.TypeId, - Tags: articlesReq.Tags, - ThumbnailPath: articlesReq.ThumbnailPath, - ThumbnailUrl: articlesReq.ThumbnailUrl, - PageUrl: articlesReq.PageUrl, - CreatedById: articlesReq.CreatedById, - ShareCount: articlesReq.ShareCount, - ViewCount: articlesReq.ViewCount, - DownloadCount: articlesReq.DownloadCount, - StatusId: articlesReq.StatusId, - IsPublish: articlesReq.IsPublish, - PublishedAt: articlesReq.PublishedAt, - IsActive: articlesReq.IsActive, - CreatedAt: articlesReq.CreatedAt, - UpdatedAt: articlesReq.UpdatedAt, + ID: articlesReq.ID, + Title: articlesReq.Title, + Slug: articlesReq.Slug, + Description: articlesReq.Description, + HtmlDescription: articlesReq.HtmlDescription, + TypeId: articlesReq.TypeId, + Tags: articlesReq.Tags, + ThumbnailUrl: thumbnailUrl, + PageUrl: articlesReq.PageUrl, + CreatedById: articlesReq.CreatedById, + ShareCount: articlesReq.ShareCount, + ViewCount: articlesReq.ViewCount, + DownloadCount: articlesReq.DownloadCount, + StatusId: articlesReq.StatusId, + IsPublish: articlesReq.IsPublish, + PublishedAt: articlesReq.PublishedAt, + IsActive: articlesReq.IsActive, + CreatedAt: articlesReq.CreatedAt, + UpdatedAt: articlesReq.UpdatedAt, } } return articlesRes -} \ No newline at end of file +} diff --git a/app/module/articles/repository/articles.repository.go b/app/module/articles/repository/articles.repository.go index 4b72397..b491608 100644 --- a/app/module/articles/repository/articles.repository.go +++ b/app/module/articles/repository/articles.repository.go @@ -19,7 +19,8 @@ type articlesRepository struct { type ArticlesRepository interface { GetAll(req request.ArticlesQueryRequest) (articless []*entity.Articles, paging paginator.Pagination, err error) FindOne(id uint) (articles *entity.Articles, err error) - Create(articles *entity.Articles) (err error) + FindByFilename(thumbnailName string) (articleReturn *entity.Articles, err error) + Create(articles *entity.Articles) (articleReturn *entity.Articles, err error) Update(id uint, articles *entity.Articles) (err error) Delete(id uint) (err error) } @@ -50,6 +51,9 @@ func (_i *articlesRepository) GetAll(req request.ArticlesQueryRequest) (articles tags := strings.ToLower(*req.Tags) query = query.Where("LOWER(tags) LIKE ?", "%"+strings.ToLower(tags)+"%") } + if req.CategoryId != nil { + query = query.Where("category_id = ?", req.CategoryId) + } if req.TypeId != nil { query = query.Where("type_id = ?", req.TypeId) } @@ -93,8 +97,18 @@ func (_i *articlesRepository) FindOne(id uint) (articles *entity.Articles, err e return articles, nil } -func (_i *articlesRepository) Create(articles *entity.Articles) (err error) { - return _i.DB.DB.Create(articles).Error +func (_i *articlesRepository) FindByFilename(thumbnailName string) (articles *entity.Articles, err error) { + + if err := _i.DB.DB.Where("thumbnail_name = ?", thumbnailName).First(&articles).Error; err != nil { + return nil, err + } + + return articles, nil +} + +func (_i *articlesRepository) Create(articles *entity.Articles) (articleReturn *entity.Articles, err error) { + result := _i.DB.DB.Create(articles) + return articles, result.Error } func (_i *articlesRepository) Update(id uint, articles *entity.Articles) (err error) { diff --git a/app/module/articles/request/articles.request.go b/app/module/articles/request/articles.request.go index 0c49e84..ff78b0a 100644 --- a/app/module/articles/request/articles.request.go +++ b/app/module/articles/request/articles.request.go @@ -14,6 +14,7 @@ type ArticlesGeneric interface { type ArticlesQueryRequest struct { Title *string `json:"title"` Description *string `json:"description"` + CategoryId *int `json:"categoryId"` TypeId *int `json:"typeId"` Tags *string `json:"tags"` CreatedById *int `json:"createdById"` @@ -27,6 +28,7 @@ type ArticlesCreateRequest struct { Slug string `json:"slug" validate:"required"` Description string `json:"description" validate:"required"` HtmlDescription string `json:"htmlDescription" validate:"required"` + CategoryId int `json:"categoryId" validate:"required"` TypeId int `json:"typeId" validate:"required"` Tags string `json:"tags" validate:"required"` } @@ -39,6 +41,7 @@ func (req ArticlesCreateRequest) ToEntity() *entity.Articles { HtmlDescription: req.HtmlDescription, TypeId: req.TypeId, Tags: req.Tags, + CategoryId: req.CategoryId, } } @@ -47,6 +50,7 @@ type ArticlesUpdateRequest struct { Slug string `json:"slug" validate:"required"` Description string `json:"description" validate:"required"` HtmlDescription string `json:"htmlDescription" validate:"required"` + CategoryId int `json:"categoryId" validate:"required"` TypeId int `json:"typeId" validate:"required"` Tags string `json:"tags" validate:"required"` StatusId *int `json:"statusId"` @@ -58,6 +62,7 @@ func (req ArticlesUpdateRequest) ToEntity() *entity.Articles { Slug: req.Slug, Description: req.Description, HtmlDescription: req.HtmlDescription, + CategoryId: req.CategoryId, TypeId: req.TypeId, Tags: req.Tags, StatusId: req.StatusId, @@ -68,6 +73,7 @@ func (req ArticlesUpdateRequest) ToEntity() *entity.Articles { type ArticlesQueryRequestContext struct { Title string `json:"title"` Description string `json:"description"` + CategoryId string `json:"categoryId"` TypeId string `json:"typeId"` Tags string `json:"tags"` CreatedById string `json:"createdById"` @@ -84,6 +90,12 @@ func (req ArticlesQueryRequestContext) ToParamRequest() ArticlesQueryRequest { if description := req.Description; description != "" { request.Description = &description } + if categoryIdStr := req.CategoryId; categoryIdStr != "" { + categoryId, err := strconv.Atoi(categoryIdStr) + if err == nil { + request.CategoryId = &categoryId + } + } if typeIdStr := req.TypeId; typeIdStr != "" { typeId, err := strconv.Atoi(typeIdStr) if err == nil { diff --git a/app/module/articles/response/articles.response.go b/app/module/articles/response/articles.response.go index addcc4d..6bcdbc9 100644 --- a/app/module/articles/response/articles.response.go +++ b/app/module/articles/response/articles.response.go @@ -7,20 +7,21 @@ type ArticlesResponse struct { Title string `json:"title"` Slug string `json:"slug"` Description string `json:"description"` - HtmlDescription string `json:"html_description"` - TypeId int `json:"type_id"` + HtmlDescription string `json:"htmlDescription"` + CategoryId int `json:"categoryId"` + CategoryName string `json:"categoryName"` + TypeId int `json:"typeId"` Tags string `json:"tags"` - ThumbnailPath *string `json:"thumbnail_path"` - ThumbnailUrl *string `json:"thumbnail_url"` - PageUrl *string `json:"page_url"` - CreatedById *int `json:"created_by_id"` - ShareCount *int `json:"share_count"` - ViewCount *int `json:"view_count"` - DownloadCount *int `json:"download_count"` - StatusId *int `json:"status_id"` - IsPublish *bool `json:"is_publish"` - PublishedAt *time.Time `json:"published_at"` - IsActive *bool `json:"is_active"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + ThumbnailUrl string `json:"thumbnailUrl"` + PageUrl *string `json:"pageUrl"` + CreatedById *uint `json:"createdById"` + ShareCount *int `json:"shareSount"` + ViewCount *int `json:"viewCount"` + DownloadCount *int `json:"downloadCount"` + StatusId *int `json:"statusId"` + IsPublish *bool `json:"isPublish"` + PublishedAt *time.Time `json:"publishedAt"` + IsActive *bool `json:"isActive"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` } diff --git a/app/module/articles/service/articles.service.go b/app/module/articles/service/articles.service.go index 0d683f2..55f2aeb 100644 --- a/app/module/articles/service/articles.service.go +++ b/app/module/articles/service/articles.service.go @@ -1,35 +1,61 @@ package service import ( + "context" + "github.com/gofiber/fiber/v2" + "github.com/minio/minio-go/v7" "github.com/rs/zerolog" + "go-humas-be/app/database/entity" "go-humas-be/app/module/articles/mapper" "go-humas-be/app/module/articles/repository" "go-humas-be/app/module/articles/request" "go-humas-be/app/module/articles/response" + usersRepository "go-humas-be/app/module/users/repository" + minioStorage "go-humas-be/config/config" "go-humas-be/utils/paginator" + utilSvc "go-humas-be/utils/service" + "io" + "log" + "math/rand" + "mime" + "path/filepath" + "strconv" + "strings" + "time" ) // ArticlesService type articlesService struct { - Repo repository.ArticlesRepository - Log zerolog.Logger + Repo repository.ArticlesRepository + Log zerolog.Logger + UsersRepo usersRepository.UsersRepository + MinioStorage *minioStorage.MinioStorage } // ArticlesService define interface of IArticlesService type ArticlesService interface { All(req request.ArticlesQueryRequest) (articles []*response.ArticlesResponse, paging paginator.Pagination, err error) Show(id uint) (articles *response.ArticlesResponse, err error) - Save(req request.ArticlesCreateRequest) (err error) + Save(req request.ArticlesCreateRequest, authToken string) (articles *entity.Articles, err error) + SaveThumbnail(c *fiber.Ctx) (err error) Update(id uint, req request.ArticlesUpdateRequest) (err error) Delete(id uint) error + Viewer(c *fiber.Ctx) error } // NewArticlesService init ArticlesService -func NewArticlesService(repo repository.ArticlesRepository, log zerolog.Logger) ArticlesService { +func NewArticlesService( + repo repository.ArticlesRepository, + log zerolog.Logger, + usersRepo usersRepository.UsersRepository, + minioStorage *minioStorage.MinioStorage, +) ArticlesService { return &articlesService{ - Repo: repo, - Log: log, + Repo: repo, + Log: log, + UsersRepo: usersRepo, + MinioStorage: minioStorage, } } @@ -40,6 +66,10 @@ func (_i *articlesService) All(req request.ArticlesQueryRequest) (articless []*r return } + _i.Log.Info().Str("timestamp", time.Now(). + Format(time.RFC3339)).Str("Service:articlesService", "Methods:All"). + Interface("results", results).Msg("") + for _, result := range results { articless = append(articless, mapper.ArticlesResponseMapper(result)) } @@ -56,10 +86,85 @@ func (_i *articlesService) Show(id uint) (articles *response.ArticlesResponse, e return mapper.ArticlesResponseMapper(result), nil } -func (_i *articlesService) Save(req request.ArticlesCreateRequest) (err error) { +func (_i *articlesService) Save(req request.ArticlesCreateRequest, authToken string) (articles *entity.Articles, err error) { _i.Log.Info().Interface("data", req).Msg("") + newReq := req.ToEntity() - return _i.Repo.Create(req.ToEntity()) + createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) + newReq.CreatedById = &createdBy.ID + + return _i.Repo.Create(newReq) +} + +func (_i *articlesService) SaveThumbnail(c *fiber.Ctx) (err error) { + + id, err := strconv.ParseUint(c.Params("id"), 10, 0) + if err != nil { + return err + } + + _i.Log.Info().Str("timestamp", time.Now(). + Format(time.RFC3339)).Str("Service:articlesService", "Methods:SaveThumbnail"). + Interface("id", id).Msg("") + + bucketName := _i.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName + + form, err := c.MultipartForm() + if err != nil { + return err + } + files := form.File["files"] + + // Create minio connection. + minioClient, err := _i.MinioStorage.ConnectMinio() + if err != nil { + // Return status 500 and minio connection error. + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": true, + "msg": err.Error(), + }) + } + + // Iterasi semua file yang diunggah + for _, file := range files { + + _i.Log.Info().Str("timestamp", time.Now(). + Format(time.RFC3339)).Str("Service:Resource", "Uploader:: loop1"). + Interface("data", file).Msg("") + + src, err := file.Open() + if err != nil { + return err + } + defer src.Close() + + filename := filepath.Base(file.Filename) + filenameWithoutExt := filepath.Clean(filename[:len(filename)-len(filepath.Ext(filename))]) + extension := filepath.Ext(file.Filename)[1:] + + rand.New(rand.NewSource(time.Now().UnixNano())) + randUniqueId := rand.Intn(1000000) + + newFilenameWithoutExt := filenameWithoutExt + "_" + strconv.Itoa(randUniqueId) + newFilename := newFilenameWithoutExt + "." + extension + objectName := "articles/thumbnail/" + newFilename + + findCategory, err := _i.Repo.FindOne(uint(id)) + findCategory.ThumbnailName = &newFilename + findCategory.ThumbnailPath = &objectName + err = _i.Repo.Update(uint(id), findCategory) + if err != nil { + return err + } + + // Upload file ke MinIO + _, err = minioClient.PutObject(context.Background(), bucketName, objectName, src, file.Size, minio.PutObjectOptions{}) + if err != nil { + return err + } + } + + return } func (_i *articlesService) Update(id uint, req request.ArticlesUpdateRequest) (err error) { @@ -77,3 +182,61 @@ func (_i *articlesService) Delete(id uint) error { result.IsActive = &isActive return _i.Repo.Update(id, result) } + +func (_i *articlesService) Viewer(c *fiber.Ctx) (err error) { + thumbnailName := c.Params("thumbnailName") + result, err := _i.Repo.FindByFilename(thumbnailName) + if err != nil { + return err + } + + if result.ThumbnailPath == nil { + return nil + } + + ctx := context.Background() + bucketName := _i.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName + objectName := result.ThumbnailPath + + // Create minio connection. + minioClient, err := _i.MinioStorage.ConnectMinio() + if err != nil { + // Return status 500 and minio connection error. + return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{ + "error": true, + "msg": err.Error(), + }) + } + + fileContent, err := minioClient.GetObject(ctx, bucketName, *objectName, minio.GetObjectOptions{}) + if err != nil { + log.Fatalln(err) + } + defer fileContent.Close() + + contentType := mime.TypeByExtension("." + getFileExtension(*objectName)) + if contentType == "" { + contentType = "application/octet-stream" + } + + c.Set("Content-Type", contentType) + + if _, err := io.Copy(c.Response().BodyWriter(), fileContent); err != nil { + return err + } + + return +} + +func getFileExtension(filename string) string { + // split file name + parts := strings.Split(filename, ".") + + // jika tidak ada ekstensi, kembalikan string kosong + if len(parts) == 1 || (len(parts) == 2 && parts[0] == "") { + return "" + } + + // ambil ekstensi terakhir + return parts[len(parts)-1] +} diff --git a/app/module/ppid_data_categories/controller/ppid_data_categories.controller.go b/app/module/ppid_data_categories/controller/ppid_data_categories.controller.go index c51751c..fe71b8f 100644 --- a/app/module/ppid_data_categories/controller/ppid_data_categories.controller.go +++ b/app/module/ppid_data_categories/controller/ppid_data_categories.controller.go @@ -126,7 +126,7 @@ func (_i *ppidDataCategoriesController) Save(c *fiber.Ctx) error { }) } -// SaveThumbnail PpidDataFiles +// SaveThumbnail PpidDataCategories // @Summary Upload PpidDataCategories Thumbnail // @Description API for Upload PpidDataCategories Thumbnail // @Tags PPID Categories @@ -147,12 +147,12 @@ func (_i *ppidDataCategoriesController) SaveThumbnail(c *fiber.Ctx) error { return utilRes.Resp(c, utilRes.Response{ Success: true, - Messages: utilRes.Messages{"PpidDataFiles successfully created"}, + Messages: utilRes.Messages{"Thumbnail of PpidDataFiles successfully created"}, }) } // Update PpidDataCategories -// @Summary update PpidDataCategories +// @Summary Update PpidDataCategories // @Description API for update PpidDataCategories // @Tags PPID Categories // @Security Bearer @@ -223,7 +223,7 @@ func (_i *ppidDataCategoriesController) Delete(c *fiber.Ctx) error { // @Failure 400 {object} response.BadRequestError // @Failure 401 {object} response.UnauthorizedError // @Failure 500 {object} response.InternalServerError -// @Router /ppid-data-categories/viewer/{id} [get] +// @Router /ppid-data-categories/thumbnail/viewer/{id} [get] func (_i *ppidDataCategoriesController) Viewer(c *fiber.Ctx) error { return _i.ppidDataCategoriesService.Viewer(c) } diff --git a/app/module/ppid_data_categories/ppid_data_categories.module.go b/app/module/ppid_data_categories/ppid_data_categories.module.go index 41ec541..2f94ada 100644 --- a/app/module/ppid_data_categories/ppid_data_categories.module.go +++ b/app/module/ppid_data_categories/ppid_data_categories.module.go @@ -47,9 +47,9 @@ func (_i *PpidDataCategoriesRouter) RegisterPpidDataCategoriesRoutes() { router.Get("/", ppidDataCategoriesController.All) router.Get("/:id", ppidDataCategoriesController.Show) router.Post("/", ppidDataCategoriesController.Save) - router.Get("/viewer/:id", ppidDataCategoriesController.Viewer) - router.Post("/thumbnail/:id", ppidDataCategoriesController.SaveThumbnail) router.Put("/:id", ppidDataCategoriesController.Update) + router.Post("/thumbnail/:id", ppidDataCategoriesController.SaveThumbnail) + router.Get("/thumbnail/viewer/:id", ppidDataCategoriesController.Viewer) router.Delete("/:id", ppidDataCategoriesController.Delete) }) } diff --git a/app/module/ppid_data_categories/service/ppid_data_categories.service.go b/app/module/ppid_data_categories/service/ppid_data_categories.service.go index db8a16a..d98e4b7 100644 --- a/app/module/ppid_data_categories/service/ppid_data_categories.service.go +++ b/app/module/ppid_data_categories/service/ppid_data_categories.service.go @@ -24,8 +24,8 @@ import ( // PpidDataCategoriesService type ppidDataCategoriesService struct { Repo repository.PpidDataCategoriesRepository - Log zerolog.Logger MinioStorage *minioStorage.MinioStorage + Log zerolog.Logger } // PpidDataCategoriesService define interface of IPpidDataCategoriesService @@ -40,12 +40,12 @@ type PpidDataCategoriesService interface { } // NewPpidDataCategoriesService init PpidDataCategoriesService -func NewPpidDataCategoriesService(repo repository.PpidDataCategoriesRepository, log zerolog.Logger, minioStorage *minioStorage.MinioStorage) PpidDataCategoriesService { +func NewPpidDataCategoriesService(repo repository.PpidDataCategoriesRepository, minioStorage *minioStorage.MinioStorage, log zerolog.Logger) PpidDataCategoriesService { return &ppidDataCategoriesService{ Repo: repo, - Log: log, MinioStorage: minioStorage, + Log: log, } } diff --git a/app/module/ppid_data_files/mapper/ppid_data_files.mapper.go b/app/module/ppid_data_files/mapper/ppid_data_files.mapper.go index 3a7446b..2c9bc37 100644 --- a/app/module/ppid_data_files/mapper/ppid_data_files.mapper.go +++ b/app/module/ppid_data_files/mapper/ppid_data_files.mapper.go @@ -6,12 +6,16 @@ import ( ) func PpidDataFilesResponseMapper(ppidDataFilesReq *entity.PpidDataFiles) (ppidDataFilesRes *res.PpidDataFilesResponse) { + fileUrl := "/ppid-data-files/viewer/" + if ppidDataFilesReq.FileName != nil { + fileUrl += *ppidDataFilesReq.FileName + } if ppidDataFilesReq != nil { ppidDataFilesRes = &res.PpidDataFilesResponse{ ID: ppidDataFilesReq.ID, Title: ppidDataFilesReq.Title, PpidDataId: ppidDataFilesReq.PpidDataId, - FileUrl: "/ppid-data-files/viewer/" + *ppidDataFilesReq.FileName, + FileUrl: fileUrl, FileType: ppidDataFilesReq.FileType, DownloadCount: ppidDataFilesReq.DownloadCount, CreatedById: ppidDataFilesReq.CreatedById, diff --git a/app/module/user_role_level_details/controller/controller.go b/app/module/user_role_level_details/controller/controller.go new file mode 100644 index 0000000..b9ad9c2 --- /dev/null +++ b/app/module/user_role_level_details/controller/controller.go @@ -0,0 +1,13 @@ +package controller + +import "go-humas-be/app/module/user_role_level_details/service" + +type Controller struct { + UserRoleLevelDetails UserRoleLevelDetailsController +} + +func NewController(UserRoleLevelDetailsService service.UserRoleLevelDetailsService) *Controller { + return &Controller{ + UserRoleLevelDetails: NewUserRoleLevelDetailsController(UserRoleLevelDetailsService), + } +} diff --git a/app/module/user_role_level_details/controller/user_role_level_details.controller.go b/app/module/user_role_level_details/controller/user_role_level_details.controller.go new file mode 100644 index 0000000..96339e9 --- /dev/null +++ b/app/module/user_role_level_details/controller/user_role_level_details.controller.go @@ -0,0 +1,181 @@ +package controller + +import ( + "github.com/gofiber/fiber/v2" + "go-humas-be/app/module/user_role_level_details/request" + "go-humas-be/app/module/user_role_level_details/service" + "go-humas-be/utils/paginator" + "strconv" + + utilRes "go-humas-be/utils/response" + utilVal "go-humas-be/utils/validator" +) + +type userRoleLevelDetailsController struct { + userRoleLevelDetailsService service.UserRoleLevelDetailsService +} + +type UserRoleLevelDetailsController interface { + All(c *fiber.Ctx) error + Show(c *fiber.Ctx) error + Save(c *fiber.Ctx) error + Update(c *fiber.Ctx) error + Delete(c *fiber.Ctx) error +} + +func NewUserRoleLevelDetailsController(userRoleLevelDetailsService service.UserRoleLevelDetailsService) UserRoleLevelDetailsController { + return &userRoleLevelDetailsController{ + userRoleLevelDetailsService: userRoleLevelDetailsService, + } +} + +// All get all UserRoleLevelDetails +// @Summary Get all UserRoleLevelDetails +// @Description API for getting all UserRoleLevelDetails +// @Tags Task +// @Security Bearer +// @Success 200 {object} response.Response +// @Failure 401 {object} response.Response +// @Failure 404 {object} response.Response +// @Failure 422 {object} response.Response +// @Failure 500 {object} response.Response +// @Router /user-role-level-details [get] +func (_i *userRoleLevelDetailsController) All(c *fiber.Ctx) error { + paginate, err := paginator.Paginate(c) + if err != nil { + return err + } + + var req request.UserRoleLevelDetailsQueryRequest + req.Pagination = paginate + + userRoleLevelDetailsData, paging, err := _i.userRoleLevelDetailsService.All(req) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Messages: utilRes.Messages{"UserRoleLevelDetails list successfully retrieved"}, + Data: userRoleLevelDetailsData, + Meta: paging, + }) +} + +// Show get one UserRoleLevelDetails +// @Summary Get one UserRoleLevelDetails +// @Description API for getting one UserRoleLevelDetails +// @Tags Task +// @Security Bearer +// @Param id path int true "UserRoleLevelDetails ID" +// @Success 200 {object} response.Response +// @Failure 401 {object} response.Response +// @Failure 404 {object} response.Response +// @Failure 422 {object} response.Response +// @Failure 500 {object} response.Response +// @Router /user-role-level-details/:id [get] +func (_i *userRoleLevelDetailsController) Show(c *fiber.Ctx) error { + id, err := strconv.ParseUint(c.Params("id"), 10, 0) + if err != nil { + return err + } + + userRoleLevelDetailsData, err := _i.userRoleLevelDetailsService.Show(uint(id)) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Messages: utilRes.Messages{"UserRoleLevelDetails successfully retrieved"}, + Data: userRoleLevelDetailsData, + }) +} + +// Save create UserRoleLevelDetails +// @Summary Create UserRoleLevelDetails +// @Description API for create UserRoleLevelDetails +// @Tags Task +// @Security Bearer +// @Body request.UserRoleLevelDetailsCreateRequest +// @Success 200 {object} response.Response +// @Failure 401 {object} response.Response +// @Failure 404 {object} response.Response +// @Failure 422 {object} response.Response +// @Failure 500 {object} response.Response +// @Router /user-role-level-details [post] +func (_i *userRoleLevelDetailsController) Save(c *fiber.Ctx) error { + req := new(request.UserRoleLevelDetailsCreateRequest) + if err := utilVal.ParseAndValidate(c, req); err != nil { + return err + } + + err := _i.userRoleLevelDetailsService.Save(*req) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Messages: utilRes.Messages{"UserRoleLevelDetails successfully created"}, + }) +} + +// Update update UserRoleLevelDetails +// @Summary update UserRoleLevelDetails +// @Description API for update UserRoleLevelDetails +// @Tags Task +// @Security Bearer +// @Body request.UserRoleLevelDetailsUpdateRequest +// @Param id path int true "UserRoleLevelDetails ID" +// @Success 200 {object} response.Response +// @Failure 401 {object} response.Response +// @Failure 404 {object} response.Response +// @Failure 422 {object} response.Response +// @Failure 500 {object} response.Response +// @Router /user-role-level-details/:id [put] +func (_i *userRoleLevelDetailsController) Update(c *fiber.Ctx) error { + id, err := strconv.ParseUint(c.Params("id"), 10, 0) + if err != nil { + return err + } + + req := new(request.UserRoleLevelDetailsUpdateRequest) + if err := utilVal.ParseAndValidate(c, req); err != nil { + return err + } + + err = _i.userRoleLevelDetailsService.Update(uint(id), *req) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Messages: utilRes.Messages{"UserRoleLevelDetails successfully updated"}, + }) +} + +// Delete delete UserRoleLevelDetails +// @Summary delete UserRoleLevelDetails +// @Description API for delete UserRoleLevelDetails +// @Tags Task +// @Security Bearer +// @Param id path int true "UserRoleLevelDetails ID" +// @Success 200 {object} response.Response +// @Failure 401 {object} response.Response +// @Failure 404 {object} response.Response +// @Failure 422 {object} response.Response +// @Failure 500 {object} response.Response +// @Router /user-role-level-details/:id [delete] +func (_i *userRoleLevelDetailsController) Delete(c *fiber.Ctx) error { + id, err := strconv.ParseUint(c.Params("id"), 10, 0) + if err != nil { + return err + } + + err = _i.userRoleLevelDetailsService.Delete(uint(id)) + if err != nil { + return err + } + + return utilRes.Resp(c, utilRes.Response{ + Messages: utilRes.Messages{"UserRoleLevelDetails successfully deleted"}, + }) +} diff --git a/app/module/user_role_level_details/mapper/user_role_level_details.mapper.go b/app/module/user_role_level_details/mapper/user_role_level_details.mapper.go new file mode 100644 index 0000000..c5b3bef --- /dev/null +++ b/app/module/user_role_level_details/mapper/user_role_level_details.mapper.go @@ -0,0 +1,20 @@ +package mapper + +import ( + "go-humas-be/app/database/entity" + res "go-humas-be/app/module/user_role_level_details/response" +) + +func UserRoleLevelDetailsResponseMapper(userRoleLevelDetailsReq *entity.UserRoleLevelDetails) (userRoleLevelDetailsRes *res.UserRoleLevelDetailsResponse) { + if userRoleLevelDetailsReq != nil { + userRoleLevelDetailsRes = &res.UserRoleLevelDetailsResponse{ + ID: userRoleLevelDetailsReq.ID, + UserRoleId: userRoleLevelDetailsReq.UserRoleId, + UserLevelId: userRoleLevelDetailsReq.UserLevelId, + IsActive: userRoleLevelDetailsReq.IsActive, + CreatedAt: userRoleLevelDetailsReq.CreatedAt, + UpdatedAt: userRoleLevelDetailsReq.UpdatedAt, + } + } + return userRoleLevelDetailsRes +} diff --git a/app/module/user_role_level_details/repository/user_role_level_details.repository.go b/app/module/user_role_level_details/repository/user_role_level_details.repository.go new file mode 100644 index 0000000..7113642 --- /dev/null +++ b/app/module/user_role_level_details/repository/user_role_level_details.repository.go @@ -0,0 +1,69 @@ +package repository + +import ( + "go-humas-be/app/database" + "go-humas-be/app/database/entity" + "go-humas-be/app/module/user_role_level_details/request" + "go-humas-be/utils/paginator" +) + +type userRoleLevelDetailsRepository struct { + DB *database.Database +} + +// UserRoleLevelDetailsRepository define interface of IUserRoleLevelDetailsRepository +type UserRoleLevelDetailsRepository interface { + GetAll(req request.UserRoleLevelDetailsQueryRequest) (userRoleLevelDetailss []*entity.UserRoleLevelDetails, paging paginator.Pagination, err error) + FindOne(id uint) (userRoleLevelDetails *entity.UserRoleLevelDetails, err error) + Create(userRoleLevelDetails *entity.UserRoleLevelDetails) (err error) + Update(id uint, userRoleLevelDetails *entity.UserRoleLevelDetails) (err error) + Delete(id uint) (err error) +} + +func NewUserRoleLevelDetailsRepository(db *database.Database) UserRoleLevelDetailsRepository { + return &userRoleLevelDetailsRepository{ + DB: db, + } +} + +// implement interface of IUserRoleLevelDetailsRepository +func (_i *userRoleLevelDetailsRepository) GetAll(req request.UserRoleLevelDetailsQueryRequest) (userRoleLevelDetailss []*entity.UserRoleLevelDetails, paging paginator.Pagination, err error) { + var count int64 + + query := _i.DB.DB.Model(&entity.UserRoleLevelDetails{}) + query.Count(&count) + + req.Pagination.Count = count + req.Pagination = paginator.Paging(req.Pagination) + + err = query.Offset(req.Pagination.Offset).Limit(req.Pagination.Limit).Find(&userRoleLevelDetailss).Error + if err != nil { + return + } + + paging = *req.Pagination + + return +} + +func (_i *userRoleLevelDetailsRepository) FindOne(id uint) (userRoleLevelDetails *entity.UserRoleLevelDetails, err error) { + if err := _i.DB.DB.First(&userRoleLevelDetails, id).Error; err != nil { + return nil, err + } + + return userRoleLevelDetails, nil +} + +func (_i *userRoleLevelDetailsRepository) Create(userRoleLevelDetails *entity.UserRoleLevelDetails) (err error) { + return _i.DB.DB.Create(userRoleLevelDetails).Error +} + +func (_i *userRoleLevelDetailsRepository) Update(id uint, userRoleLevelDetails *entity.UserRoleLevelDetails) (err error) { + return _i.DB.DB.Model(&entity.UserRoleLevelDetails{}). + Where(&entity.UserRoleLevelDetails{ID: id}). + Updates(userRoleLevelDetails).Error +} + +func (_i *userRoleLevelDetailsRepository) Delete(id uint) error { + return _i.DB.DB.Delete(&entity.UserRoleLevelDetails{}, id).Error +} diff --git a/app/module/user_role_level_details/request/user_role_level_details.request.go b/app/module/user_role_level_details/request/user_role_level_details.request.go new file mode 100644 index 0000000..6345742 --- /dev/null +++ b/app/module/user_role_level_details/request/user_role_level_details.request.go @@ -0,0 +1,51 @@ +package request + +import ( + "go-humas-be/app/database/entity" + "go-humas-be/utils/paginator" + "time" +) + +type UserRoleLevelDetailsGeneric interface { + ToEntity() +} + +type UserRoleLevelDetailsQueryRequest struct { + UserRoleId uint `json:"user_role_id" validate:"required"` + UserLevelId uint `json:"user_level_id" validate:"required"` + Pagination *paginator.Pagination `json:"pagination"` +} + +type UserRoleLevelDetailsCreateRequest struct { + UserRoleId uint `json:"user_role_id" validate:"required"` + UserLevelId uint `json:"user_level_id" validate:"required"` + IsActive *bool `json:"is_active" validate:"required"` +} + +func (req UserRoleLevelDetailsCreateRequest) ToEntity() *entity.UserRoleLevelDetails { + return &entity.UserRoleLevelDetails{ + UserRoleId: req.UserRoleId, + UserLevelId: req.UserLevelId, + IsActive: req.IsActive, + } +} + +type UserRoleLevelDetailsUpdateRequest struct { + ID uint `json:"id" validate:"required"` + UserRoleId uint `json:"user_role_id" validate:"required"` + UserLevelId uint `json:"user_level_id" validate:"required"` + IsActive *bool `json:"is_active" validate:"required"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} + +func (req UserRoleLevelDetailsUpdateRequest) ToEntity() *entity.UserRoleLevelDetails { + return &entity.UserRoleLevelDetails{ + ID: req.ID, + UserRoleId: req.UserRoleId, + UserLevelId: req.UserLevelId, + IsActive: req.IsActive, + CreatedAt: req.CreatedAt, + UpdatedAt: req.UpdatedAt, + } +} diff --git a/app/module/user_role_level_details/response/user_role_level_details.response.go b/app/module/user_role_level_details/response/user_role_level_details.response.go new file mode 100644 index 0000000..58ed186 --- /dev/null +++ b/app/module/user_role_level_details/response/user_role_level_details.response.go @@ -0,0 +1,12 @@ +package response + +import "time" + +type UserRoleLevelDetailsResponse struct { + ID uint `json:"id"` + UserRoleId uint `json:"user_role_id"` + UserLevelId uint `json:"user_level_id"` + IsActive *bool `json:"is_active"` + CreatedAt time.Time `json:"created_at"` + UpdatedAt time.Time `json:"updated_at"` +} diff --git a/app/module/user_role_level_details/service/user_role_level_details.service.go b/app/module/user_role_level_details/service/user_role_level_details.service.go new file mode 100644 index 0000000..786cb8c --- /dev/null +++ b/app/module/user_role_level_details/service/user_role_level_details.service.go @@ -0,0 +1,72 @@ +package service + +import ( + "github.com/rs/zerolog" + "go-humas-be/app/module/user_role_level_details/mapper" + "go-humas-be/app/module/user_role_level_details/repository" + "go-humas-be/app/module/user_role_level_details/request" + "go-humas-be/app/module/user_role_level_details/response" + "go-humas-be/utils/paginator" +) + +// UserRoleLevelDetailsService +type userRoleLevelDetailsService struct { + Repo repository.UserRoleLevelDetailsRepository + Log zerolog.Logger +} + +// UserRoleLevelDetailsService define interface of IUserRoleLevelDetailsService +type UserRoleLevelDetailsService interface { + All(req request.UserRoleLevelDetailsQueryRequest) (userRoleLevelDetails []*response.UserRoleLevelDetailsResponse, paging paginator.Pagination, err error) + Show(id uint) (userRoleLevelDetails *response.UserRoleLevelDetailsResponse, err error) + Save(req request.UserRoleLevelDetailsCreateRequest) (err error) + Update(id uint, req request.UserRoleLevelDetailsUpdateRequest) (err error) + Delete(id uint) error +} + +// NewUserRoleLevelDetailsService init UserRoleLevelDetailsService +func NewUserRoleLevelDetailsService(repo repository.UserRoleLevelDetailsRepository, log zerolog.Logger) UserRoleLevelDetailsService { + + return &userRoleLevelDetailsService{ + Repo: repo, + Log: log, + } +} + +// All implement interface of UserRoleLevelDetailsService +func (_i *userRoleLevelDetailsService) All(req request.UserRoleLevelDetailsQueryRequest) (userRoleLevelDetailss []*response.UserRoleLevelDetailsResponse, paging paginator.Pagination, err error) { + results, paging, err := _i.Repo.GetAll(req) + if err != nil { + return + } + + for _, result := range results { + userRoleLevelDetailss = append(userRoleLevelDetailss, mapper.UserRoleLevelDetailsResponseMapper(result)) + } + + return +} + +func (_i *userRoleLevelDetailsService) Show(id uint) (userRoleLevelDetails *response.UserRoleLevelDetailsResponse, err error) { + result, err := _i.Repo.FindOne(id) + if err != nil { + return nil, err + } + + return mapper.UserRoleLevelDetailsResponseMapper(result), nil +} + +func (_i *userRoleLevelDetailsService) Save(req request.UserRoleLevelDetailsCreateRequest) (err error) { + _i.Log.Info().Interface("data", req).Msg("") + + return _i.Repo.Create(req.ToEntity()) +} + +func (_i *userRoleLevelDetailsService) Update(id uint, req request.UserRoleLevelDetailsUpdateRequest) (err error) { + _i.Log.Info().Interface("data", req).Msg("") + return _i.Repo.Update(id, req.ToEntity()) +} + +func (_i *userRoleLevelDetailsService) Delete(id uint) error { + return _i.Repo.Delete(id) +} diff --git a/app/module/user_role_level_details/user_role_level_details.module.go b/app/module/user_role_level_details/user_role_level_details.module.go new file mode 100644 index 0000000..9e0c2db --- /dev/null +++ b/app/module/user_role_level_details/user_role_level_details.module.go @@ -0,0 +1,53 @@ +package user_role_level_details + +import ( + "github.com/gofiber/fiber/v2" + "go-humas-be/app/module/user_role_level_details/controller" + "go-humas-be/app/module/user_role_level_details/repository" + "go-humas-be/app/module/user_role_level_details/service" + "go.uber.org/fx" +) + +// struct of UserRoleLevelDetailsRouter +type UserRoleLevelDetailsRouter struct { + App fiber.Router + Controller *controller.Controller +} + +// register bulky of UserRoleLevelDetails module +var NewUserRoleLevelDetailsModule = fx.Options( + // register repository of UserRoleLevelDetails module + fx.Provide(repository.NewUserRoleLevelDetailsRepository), + + // register service of UserRoleLevelDetails module + fx.Provide(service.NewUserRoleLevelDetailsService), + + // register controller of UserRoleLevelDetails module + fx.Provide(controller.NewController), + + // register router of UserRoleLevelDetails module + fx.Provide(NewUserRoleLevelDetailsRouter), +) + +// init UserRoleLevelDetailsRouter +func NewUserRoleLevelDetailsRouter(fiber *fiber.App, controller *controller.Controller) *UserRoleLevelDetailsRouter { + return &UserRoleLevelDetailsRouter{ + App: fiber, + Controller: controller, + } +} + +// register routes of UserRoleLevelDetails module +func (_i *UserRoleLevelDetailsRouter) RegisterUserRoleLevelDetailsRoutes() { + // define controllers + userRoleLevelDetailsController := _i.Controller.UserRoleLevelDetails + + // define routes + _i.App.Route("/user-role-level-details", func(router fiber.Router) { + router.Get("/", userRoleLevelDetailsController.All) + router.Get("/:id", userRoleLevelDetailsController.Show) + router.Post("/", userRoleLevelDetailsController.Save) + router.Put("/:id", userRoleLevelDetailsController.Update) + router.Delete("/:id", userRoleLevelDetailsController.Delete) + }) +} diff --git a/app/module/user_roles/repository/user_roles.repository.go b/app/module/user_roles/repository/user_roles.repository.go index 742374e..751af15 100644 --- a/app/module/user_roles/repository/user_roles.repository.go +++ b/app/module/user_roles/repository/user_roles.repository.go @@ -19,7 +19,7 @@ type userRolesRepository struct { type UserRolesRepository interface { GetAll(req request.UserRolesQueryRequest) (userRoless []*entity.UserRoles, paging paginator.Pagination, err error) FindOne(id uint) (userRoles *entity.UserRoles, err error) - Create(userRoles *entity.UserRoles) (err error) + Create(userRoles *entity.UserRoles) (userRolesReturn *entity.UserRoles, err error) Update(id uint, userRoles *entity.UserRoles) (err error) Delete(id uint) (err error) } @@ -84,8 +84,9 @@ func (_i *userRolesRepository) FindOne(id uint) (userRoles *entity.UserRoles, er return userRoles, nil } -func (_i *userRolesRepository) Create(userRoles *entity.UserRoles) (err error) { - return _i.DB.DB.Create(userRoles).Error +func (_i *userRolesRepository) Create(userRoles *entity.UserRoles) (userRolesReturn *entity.UserRoles, err error) { + result := _i.DB.DB.Create(userRoles) + return userRoles, result.Error } func (_i *userRolesRepository) Update(id uint, userRoles *entity.UserRoles) (err error) { diff --git a/app/module/user_roles/request/user_roles.request.go b/app/module/user_roles/request/user_roles.request.go index fdac691..ee89c7e 100644 --- a/app/module/user_roles/request/user_roles.request.go +++ b/app/module/user_roles/request/user_roles.request.go @@ -21,11 +21,12 @@ type UserRolesQueryRequest struct { } type UserRolesCreateRequest struct { - Name string `json:"name" validate:"required"` - Description string `json:"description" validate:"required"` - Code string `json:"code" validate:"required"` - LevelNumber int `json:"levelNumber" validate:"required"` - StatusId int `json:"statusId" validate:"required"` + Name string `json:"name" validate:"required"` + Description string `json:"description" validate:"required"` + Code string `json:"code" validate:"required"` + LevelNumber int `json:"levelNumber" validate:"required"` + StatusId int `json:"statusId" validate:"required"` + UserLevelIds []int `json:"userLevelIds" validate:"required"` } func (req UserRolesCreateRequest) ToEntity() *entity.UserRoles { @@ -39,11 +40,12 @@ func (req UserRolesCreateRequest) ToEntity() *entity.UserRoles { } type UserRolesUpdateRequest struct { - Name string `json:"name" validate:"required"` - Description string `json:"description" validate:"required"` - Code string `json:"code" validate:"required"` - LevelNumber int `json:"level_number" validate:"required"` - StatusId int `json:"status_id" validate:"required"` + Name string `json:"name" validate:"required"` + Description string `json:"description" validate:"required"` + Code string `json:"code" validate:"required"` + LevelNumber int `json:"level_number" validate:"required"` + StatusId int `json:"status_id" validate:"required"` + UserLevelIds []int `json:"userLevelIds" validate:"required"` } func (req UserRolesUpdateRequest) ToEntity() *entity.UserRoles { diff --git a/app/module/user_roles/service/user_roles.service.go b/app/module/user_roles/service/user_roles.service.go index 56d833f..4c9d113 100644 --- a/app/module/user_roles/service/user_roles.service.go +++ b/app/module/user_roles/service/user_roles.service.go @@ -2,6 +2,9 @@ package service import ( "github.com/rs/zerolog" + "go-humas-be/app/database/entity" + userLevelsRepository "go-humas-be/app/module/user_levels/repository" + userRoleLevelDetailsRepository "go-humas-be/app/module/user_role_level_details/repository" "go-humas-be/app/module/user_roles/mapper" "go-humas-be/app/module/user_roles/repository" "go-humas-be/app/module/user_roles/request" @@ -13,9 +16,11 @@ import ( // UserRolesService type userRolesService struct { - Repo repository.UserRolesRepository - UsersRepo usersRepository.UsersRepository - Log zerolog.Logger + Repo repository.UserRolesRepository + UsersRepo usersRepository.UsersRepository + UserLevelsRepo userLevelsRepository.UserLevelsRepository + UserRoleLevelDetailsRepo userRoleLevelDetailsRepository.UserRoleLevelDetailsRepository + Log zerolog.Logger } // UserRolesService define interface of IUserRolesService @@ -28,12 +33,20 @@ type UserRolesService interface { } // NewUserRolesService init UserRolesService -func NewUserRolesService(repo repository.UserRolesRepository, usersRepo usersRepository.UsersRepository, log zerolog.Logger) UserRolesService { +func NewUserRolesService( + repo repository.UserRolesRepository, + usersRepo usersRepository.UsersRepository, + userLevelsRepo userLevelsRepository.UserLevelsRepository, + userRoleLevelDetailsRepo userRoleLevelDetailsRepository.UserRoleLevelDetailsRepository, + log zerolog.Logger, +) UserRolesService { return &userRolesService{ - Repo: repo, - UsersRepo: usersRepo, - Log: log, + Repo: repo, + UsersRepo: usersRepo, + UserLevelsRepo: userLevelsRepo, + UserRoleLevelDetailsRepo: userRoleLevelDetailsRepo, + Log: log, } } @@ -68,7 +81,21 @@ func (_i *userRolesService) Save(req request.UserRolesCreateRequest, authToken s createdBy := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken) newReq.CreatedById = &createdBy.ID - return _i.Repo.Create(newReq) + dataResult, err := _i.Repo.Create(newReq) + + for _, levelId := range req.UserLevelIds { + var userRoleLevelDetails *entity.UserRoleLevelDetails + userRoleLevelDetails = &entity.UserRoleLevelDetails{ + UserRoleId: dataResult.ID, + UserLevelId: uint(levelId), + } + err := _i.UserRoleLevelDetailsRepo.Create(userRoleLevelDetails) + if err != nil { + return err + } + } + + return err } func (_i *userRolesService) Update(id uint, req request.UserRolesUpdateRequest) (err error) { diff --git a/config/toml/config.toml b/config/toml/config.toml index 44d16d6..5c1ea67 100644 --- a/config/toml/config.toml +++ b/config/toml/config.toml @@ -9,7 +9,7 @@ production = false [db.postgres] dsn = "postgresql://humas_polri:P@ssw0rd.1@103.82.242.92:5432/humas_polri" # ://:@:/ -migrate = false +migrate = true seed = false [logger] diff --git a/docs/swagger/docs.go b/docs/swagger/docs.go index 795aef8..bef8f09 100644 --- a/docs/swagger/docs.go +++ b/docs/swagger/docs.go @@ -28,21 +28,11 @@ const docTemplate = `{ ], "summary": "Get all ArticleCategories", "parameters": [ - { - "type": "integer", - "name": "createdById", - "in": "query" - }, { "type": "string", "name": "description", "in": "query" }, - { - "type": "boolean", - "name": "isEnabled", - "in": "query" - }, { "type": "boolean", "name": "isPublish", @@ -143,6 +133,14 @@ const docTemplate = `{ ], "summary": "Create ArticleCategories", "parameters": [ + { + "type": "string", + "default": "Bearer \u003cAdd access token here\u003e", + "description": "Insert your access token", + "name": "Authorization", + "in": "header", + "required": true + }, { "description": "Required payload", "name": "payload", @@ -181,6 +179,114 @@ const docTemplate = `{ } } }, + "/article-categories/thumbnail/viewer/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for View Thumbnail of ArticleCategories", + "tags": [ + "Article Categories" + ], + "summary": "Viewer ArticleCategories", + "parameters": [ + { + "type": "string", + "description": "ArticleCategories ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/article-categories/thumbnail/{id}": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for Upload ArticleCategories Thumbnail", + "produces": [ + "application/json" + ], + "tags": [ + "Article Categories" + ], + "summary": "Upload ArticleCategories Thumbnail", + "parameters": [ + { + "type": "file", + "description": "Upload thumbnail", + "name": "files", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "ArticleCategories ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/article-categories/{id}": { "get": { "security": [ @@ -959,6 +1065,11 @@ const docTemplate = `{ ], "summary": "Get all Articles", "parameters": [ + { + "type": "integer", + "name": "categoryId", + "in": "query" + }, { "type": "integer", "name": "createdById", @@ -1074,6 +1185,14 @@ const docTemplate = `{ ], "summary": "Create Articles", "parameters": [ + { + "type": "string", + "default": "Bearer \u003cAdd access token here\u003e", + "description": "Insert your access token", + "name": "Authorization", + "in": "header", + "required": true + }, { "description": "Required payload", "name": "payload", @@ -1112,6 +1231,114 @@ const docTemplate = `{ } } }, + "/articles/thumbnail/viewer/{thumbnailName}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for View Thumbnail of Article", + "tags": [ + "Articles" + ], + "summary": "Viewer Articles Thumbnail", + "parameters": [ + { + "type": "string", + "description": "Articles Thumbnail Name", + "name": "thumbnailName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/articles/thumbnail/{id}": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for Save Thumbnail of Articles", + "produces": [ + "application/json" + ], + "tags": [ + "Articles" + ], + "summary": "Save Thumbnail Articles", + "parameters": [ + { + "type": "file", + "description": "Upload thumbnail", + "name": "files", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "Articles ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/articles/{id}": { "get": { "security": [ @@ -3289,32 +3516,22 @@ const docTemplate = `{ } } }, - "/ppid-data-categories/thumbnail/{id}": { - "post": { + "/ppid-data-categories/thumbnail/viewer/{id}": { + "get": { "security": [ { "Bearer": [] } ], - "description": "API for Upload PpidDataCategories Thumbnail", - "produces": [ - "application/json" - ], + "description": "API for View Thumbnail of PpidDataCategories", "tags": [ "PPID Categories" ], - "summary": "Upload PpidDataCategories Thumbnail", + "summary": "Viewer PpidDataCategories", "parameters": [ { - "type": "file", - "description": "Upload thumbnail", - "name": "files", - "in": "formData", - "required": true - }, - { - "type": "integer", - "description": "Ppid Data Category ID", + "type": "string", + "description": "PPID Categories ID", "name": "id", "in": "path", "required": true @@ -3348,22 +3565,32 @@ const docTemplate = `{ } } }, - "/ppid-data-categories/viewer/{id}": { - "get": { + "/ppid-data-categories/thumbnail/{id}": { + "post": { "security": [ { "Bearer": [] } ], - "description": "API for View Thumbnail of PpidDataCategories", + "description": "API for Upload PpidDataCategories Thumbnail", + "produces": [ + "application/json" + ], "tags": [ "PPID Categories" ], - "summary": "Viewer PpidDataCategories", + "summary": "Upload PpidDataCategories Thumbnail", "parameters": [ { - "type": "string", - "description": "PPID Categories ID", + "type": "file", + "description": "Upload thumbnail", + "name": "files", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "Ppid Data Category ID", "name": "id", "in": "path", "required": true @@ -3455,7 +3682,7 @@ const docTemplate = `{ "tags": [ "PPID Categories" ], - "summary": "update PpidDataCategories", + "summary": "Update PpidDataCategories", "parameters": [ { "description": "Required payload", @@ -5078,6 +5305,257 @@ const docTemplate = `{ } } }, + "/user-role-level-details": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "Get all UserRoleLevelDetails", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for create UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "Create UserRoleLevelDetails", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/user-role-level-details/:id": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting one UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "Get one UserRoleLevelDetails", + "parameters": [ + { + "type": "integer", + "description": "UserRoleLevelDetails ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for update UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "update UserRoleLevelDetails", + "parameters": [ + { + "type": "integer", + "description": "UserRoleLevelDetails ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for delete UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "delete UserRoleLevelDetails", + "parameters": [ + { + "type": "integer", + "description": "UserRoleLevelDetails ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/user-roles": { "get": { "security": [ @@ -5806,8 +6284,6 @@ const docTemplate = `{ "type": "object", "required": [ "description", - "isEnabled", - "parentId", "statusId", "title" ], @@ -5815,9 +6291,6 @@ const docTemplate = `{ "description": { "type": "string" }, - "isEnabled": { - "type": "boolean" - }, "parentId": { "type": "integer" }, @@ -5834,9 +6307,7 @@ const docTemplate = `{ "required": [ "description", "id", - "parentId", - "thumbnailPath", - "thumbnailUrl", + "statusId", "title" ], "properties": { @@ -5846,9 +6317,6 @@ const docTemplate = `{ "id": { "type": "integer" }, - "isEnabled": { - "type": "boolean" - }, "isPublish": { "type": "boolean" }, @@ -5861,12 +6329,6 @@ const docTemplate = `{ "statusId": { "type": "integer" }, - "thumbnailPath": { - "type": "string" - }, - "thumbnailUrl": { - "type": "string" - }, "title": { "type": "string" } @@ -5942,6 +6404,7 @@ const docTemplate = `{ "request.ArticlesCreateRequest": { "type": "object", "required": [ + "categoryId", "description", "htmlDescription", "slug", @@ -5950,6 +6413,9 @@ const docTemplate = `{ "typeId" ], "properties": { + "categoryId": { + "type": "integer" + }, "description": { "type": "string" }, @@ -5973,6 +6439,7 @@ const docTemplate = `{ "request.ArticlesUpdateRequest": { "type": "object", "required": [ + "categoryId", "description", "htmlDescription", "slug", @@ -5981,6 +6448,9 @@ const docTemplate = `{ "typeId" ], "properties": { + "categoryId": { + "type": "integer" + }, "description": { "type": "string" }, @@ -6403,7 +6873,8 @@ const docTemplate = `{ "description", "levelNumber", "name", - "statusId" + "statusId", + "userLevelIds" ], "properties": { "code": { @@ -6420,6 +6891,12 @@ const docTemplate = `{ }, "statusId": { "type": "integer" + }, + "userLevelIds": { + "type": "array", + "items": { + "type": "integer" + } } } }, @@ -6430,7 +6907,8 @@ const docTemplate = `{ "description", "level_number", "name", - "status_id" + "status_id", + "userLevelIds" ], "properties": { "code": { @@ -6447,6 +6925,12 @@ const docTemplate = `{ }, "status_id": { "type": "integer" + }, + "userLevelIds": { + "type": "array", + "items": { + "type": "integer" + } } } }, diff --git a/docs/swagger/swagger.json b/docs/swagger/swagger.json index 07bda8c..f2b7da2 100644 --- a/docs/swagger/swagger.json +++ b/docs/swagger/swagger.json @@ -17,21 +17,11 @@ ], "summary": "Get all ArticleCategories", "parameters": [ - { - "type": "integer", - "name": "createdById", - "in": "query" - }, { "type": "string", "name": "description", "in": "query" }, - { - "type": "boolean", - "name": "isEnabled", - "in": "query" - }, { "type": "boolean", "name": "isPublish", @@ -132,6 +122,14 @@ ], "summary": "Create ArticleCategories", "parameters": [ + { + "type": "string", + "default": "Bearer \u003cAdd access token here\u003e", + "description": "Insert your access token", + "name": "Authorization", + "in": "header", + "required": true + }, { "description": "Required payload", "name": "payload", @@ -170,6 +168,114 @@ } } }, + "/article-categories/thumbnail/viewer/{id}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for View Thumbnail of ArticleCategories", + "tags": [ + "Article Categories" + ], + "summary": "Viewer ArticleCategories", + "parameters": [ + { + "type": "string", + "description": "ArticleCategories ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/article-categories/thumbnail/{id}": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for Upload ArticleCategories Thumbnail", + "produces": [ + "application/json" + ], + "tags": [ + "Article Categories" + ], + "summary": "Upload ArticleCategories Thumbnail", + "parameters": [ + { + "type": "file", + "description": "Upload thumbnail", + "name": "files", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "ArticleCategories ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/article-categories/{id}": { "get": { "security": [ @@ -948,6 +1054,11 @@ ], "summary": "Get all Articles", "parameters": [ + { + "type": "integer", + "name": "categoryId", + "in": "query" + }, { "type": "integer", "name": "createdById", @@ -1063,6 +1174,14 @@ ], "summary": "Create Articles", "parameters": [ + { + "type": "string", + "default": "Bearer \u003cAdd access token here\u003e", + "description": "Insert your access token", + "name": "Authorization", + "in": "header", + "required": true + }, { "description": "Required payload", "name": "payload", @@ -1101,6 +1220,114 @@ } } }, + "/articles/thumbnail/viewer/{thumbnailName}": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for View Thumbnail of Article", + "tags": [ + "Articles" + ], + "summary": "Viewer Articles Thumbnail", + "parameters": [ + { + "type": "string", + "description": "Articles Thumbnail Name", + "name": "thumbnailName", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, + "/articles/thumbnail/{id}": { + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for Save Thumbnail of Articles", + "produces": [ + "application/json" + ], + "tags": [ + "Articles" + ], + "summary": "Save Thumbnail Articles", + "parameters": [ + { + "type": "file", + "description": "Upload thumbnail", + "name": "files", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "Articles ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "400": { + "description": "Bad Request", + "schema": { + "$ref": "#/definitions/response.BadRequestError" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.UnauthorizedError" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.InternalServerError" + } + } + } + } + }, "/articles/{id}": { "get": { "security": [ @@ -3278,32 +3505,22 @@ } } }, - "/ppid-data-categories/thumbnail/{id}": { - "post": { + "/ppid-data-categories/thumbnail/viewer/{id}": { + "get": { "security": [ { "Bearer": [] } ], - "description": "API for Upload PpidDataCategories Thumbnail", - "produces": [ - "application/json" - ], + "description": "API for View Thumbnail of PpidDataCategories", "tags": [ "PPID Categories" ], - "summary": "Upload PpidDataCategories Thumbnail", + "summary": "Viewer PpidDataCategories", "parameters": [ { - "type": "file", - "description": "Upload thumbnail", - "name": "files", - "in": "formData", - "required": true - }, - { - "type": "integer", - "description": "Ppid Data Category ID", + "type": "string", + "description": "PPID Categories ID", "name": "id", "in": "path", "required": true @@ -3337,22 +3554,32 @@ } } }, - "/ppid-data-categories/viewer/{id}": { - "get": { + "/ppid-data-categories/thumbnail/{id}": { + "post": { "security": [ { "Bearer": [] } ], - "description": "API for View Thumbnail of PpidDataCategories", + "description": "API for Upload PpidDataCategories Thumbnail", + "produces": [ + "application/json" + ], "tags": [ "PPID Categories" ], - "summary": "Viewer PpidDataCategories", + "summary": "Upload PpidDataCategories Thumbnail", "parameters": [ { - "type": "string", - "description": "PPID Categories ID", + "type": "file", + "description": "Upload thumbnail", + "name": "files", + "in": "formData", + "required": true + }, + { + "type": "integer", + "description": "Ppid Data Category ID", "name": "id", "in": "path", "required": true @@ -3444,7 +3671,7 @@ "tags": [ "PPID Categories" ], - "summary": "update PpidDataCategories", + "summary": "Update PpidDataCategories", "parameters": [ { "description": "Required payload", @@ -5067,6 +5294,257 @@ } } }, + "/user-role-level-details": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting all UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "Get all UserRoleLevelDetails", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "post": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for create UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "Create UserRoleLevelDetails", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, + "/user-role-level-details/:id": { + "get": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for getting one UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "Get one UserRoleLevelDetails", + "parameters": [ + { + "type": "integer", + "description": "UserRoleLevelDetails ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "put": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for update UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "update UserRoleLevelDetails", + "parameters": [ + { + "type": "integer", + "description": "UserRoleLevelDetails ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + }, + "delete": { + "security": [ + { + "Bearer": [] + } + ], + "description": "API for delete UserRoleLevelDetails", + "tags": [ + "Task" + ], + "summary": "delete UserRoleLevelDetails", + "parameters": [ + { + "type": "integer", + "description": "UserRoleLevelDetails ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "401": { + "description": "Unauthorized", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "404": { + "description": "Not Found", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "422": { + "description": "Unprocessable Entity", + "schema": { + "$ref": "#/definitions/response.Response" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/response.Response" + } + } + } + } + }, "/user-roles": { "get": { "security": [ @@ -5795,8 +6273,6 @@ "type": "object", "required": [ "description", - "isEnabled", - "parentId", "statusId", "title" ], @@ -5804,9 +6280,6 @@ "description": { "type": "string" }, - "isEnabled": { - "type": "boolean" - }, "parentId": { "type": "integer" }, @@ -5823,9 +6296,7 @@ "required": [ "description", "id", - "parentId", - "thumbnailPath", - "thumbnailUrl", + "statusId", "title" ], "properties": { @@ -5835,9 +6306,6 @@ "id": { "type": "integer" }, - "isEnabled": { - "type": "boolean" - }, "isPublish": { "type": "boolean" }, @@ -5850,12 +6318,6 @@ "statusId": { "type": "integer" }, - "thumbnailPath": { - "type": "string" - }, - "thumbnailUrl": { - "type": "string" - }, "title": { "type": "string" } @@ -5931,6 +6393,7 @@ "request.ArticlesCreateRequest": { "type": "object", "required": [ + "categoryId", "description", "htmlDescription", "slug", @@ -5939,6 +6402,9 @@ "typeId" ], "properties": { + "categoryId": { + "type": "integer" + }, "description": { "type": "string" }, @@ -5962,6 +6428,7 @@ "request.ArticlesUpdateRequest": { "type": "object", "required": [ + "categoryId", "description", "htmlDescription", "slug", @@ -5970,6 +6437,9 @@ "typeId" ], "properties": { + "categoryId": { + "type": "integer" + }, "description": { "type": "string" }, @@ -6392,7 +6862,8 @@ "description", "levelNumber", "name", - "statusId" + "statusId", + "userLevelIds" ], "properties": { "code": { @@ -6409,6 +6880,12 @@ }, "statusId": { "type": "integer" + }, + "userLevelIds": { + "type": "array", + "items": { + "type": "integer" + } } } }, @@ -6419,7 +6896,8 @@ "description", "level_number", "name", - "status_id" + "status_id", + "userLevelIds" ], "properties": { "code": { @@ -6436,6 +6914,12 @@ }, "status_id": { "type": "integer" + }, + "userLevelIds": { + "type": "array", + "items": { + "type": "integer" + } } } }, diff --git a/docs/swagger/swagger.yaml b/docs/swagger/swagger.yaml index fdea809..65dd892 100644 --- a/docs/swagger/swagger.yaml +++ b/docs/swagger/swagger.yaml @@ -22,8 +22,6 @@ definitions: properties: description: type: string - isEnabled: - type: boolean parentId: type: integer statusId: @@ -32,8 +30,6 @@ definitions: type: string required: - description - - isEnabled - - parentId - statusId - title type: object @@ -43,8 +39,6 @@ definitions: type: string id: type: integer - isEnabled: - type: boolean isPublish: type: boolean parentId: @@ -53,18 +47,12 @@ definitions: type: string statusId: type: integer - thumbnailPath: - type: string - thumbnailUrl: - type: string title: type: string required: - description - id - - parentId - - thumbnailPath - - thumbnailUrl + - statusId - title type: object request.ArticleFilesUpdateRequest: @@ -118,6 +106,8 @@ definitions: type: object request.ArticlesCreateRequest: properties: + categoryId: + type: integer description: type: string htmlDescription: @@ -131,6 +121,7 @@ definitions: typeId: type: integer required: + - categoryId - description - htmlDescription - slug @@ -140,6 +131,8 @@ definitions: type: object request.ArticlesUpdateRequest: properties: + categoryId: + type: integer description: type: string htmlDescription: @@ -155,6 +148,7 @@ definitions: typeId: type: integer required: + - categoryId - description - htmlDescription - slug @@ -447,12 +441,17 @@ definitions: type: string statusId: type: integer + userLevelIds: + items: + type: integer + type: array required: - code - description - levelNumber - name - statusId + - userLevelIds type: object request.UserRolesUpdateRequest: properties: @@ -466,12 +465,17 @@ definitions: type: string status_id: type: integer + userLevelIds: + items: + type: integer + type: array required: - code - description - level_number - name - status_id + - userLevelIds type: object request.UsersCreateRequest: properties: @@ -621,15 +625,9 @@ paths: get: description: API for getting all ArticleCategories parameters: - - in: query - name: createdById - type: integer - in: query name: description type: string - - in: query - name: isEnabled - type: boolean - in: query name: isPublish type: boolean @@ -691,6 +689,12 @@ paths: post: description: API for create ArticleCategories parameters: + - default: Bearer + description: Insert your access token + in: header + name: Authorization + required: true + type: string - description: Required payload in: body name: payload @@ -816,6 +820,75 @@ paths: summary: update ArticleCategories tags: - Article Categories + /article-categories/thumbnail/{id}: + post: + description: API for Upload ArticleCategories Thumbnail + parameters: + - description: Upload thumbnail + in: formData + name: files + required: true + type: file + - description: ArticleCategories ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Upload ArticleCategories Thumbnail + tags: + - Article Categories + /article-categories/thumbnail/viewer/{id}: + get: + description: API for View Thumbnail of ArticleCategories + parameters: + - description: ArticleCategories ID + in: path + name: id + required: true + type: string + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Viewer ArticleCategories + tags: + - Article Categories /article-category-details: get: description: API for getting all ArticleCategoryDetails @@ -1208,6 +1281,9 @@ paths: get: description: API for getting all Articles parameters: + - in: query + name: categoryId + type: integer - in: query name: createdById type: integer @@ -1278,6 +1354,12 @@ paths: post: description: API for create Articles parameters: + - default: Bearer + description: Insert your access token + in: header + name: Authorization + required: true + type: string - description: Required payload in: body name: payload @@ -1403,6 +1485,75 @@ paths: summary: Update Articles tags: - Articles + /articles/thumbnail/{id}: + post: + description: API for Save Thumbnail of Articles + parameters: + - description: Upload thumbnail + in: formData + name: files + required: true + type: file + - description: Articles ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Save Thumbnail Articles + tags: + - Articles + /articles/thumbnail/viewer/{thumbnailName}: + get: + description: API for View Thumbnail of Article + parameters: + - description: Articles Thumbnail Name + in: path + name: thumbnailName + required: true + type: string + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "400": + description: Bad Request + schema: + $ref: '#/definitions/response.BadRequestError' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.UnauthorizedError' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.InternalServerError' + security: + - Bearer: [] + summary: Viewer Articles Thumbnail + tags: + - Articles /cities: get: description: API for getting all Cities @@ -2779,7 +2930,7 @@ paths: $ref: '#/definitions/response.InternalServerError' security: - Bearer: [] - summary: update PpidDataCategories + summary: Update PpidDataCategories tags: - PPID Categories /ppid-data-categories/thumbnail/{id}: @@ -2820,7 +2971,7 @@ paths: summary: Upload PpidDataCategories Thumbnail tags: - PPID Categories - /ppid-data-categories/viewer/{id}: + /ppid-data-categories/thumbnail/viewer/{id}: get: description: API for View Thumbnail of PpidDataCategories parameters: @@ -3816,6 +3967,166 @@ paths: summary: update UserRoleAccesses tags: - UserRoleAccesses + /user-role-level-details: + get: + description: API for getting all UserRoleLevelDetails + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.Response' + "404": + description: Not Found + schema: + $ref: '#/definitions/response.Response' + "422": + description: Unprocessable Entity + schema: + $ref: '#/definitions/response.Response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: Get all UserRoleLevelDetails + tags: + - Task + post: + description: API for create UserRoleLevelDetails + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.Response' + "404": + description: Not Found + schema: + $ref: '#/definitions/response.Response' + "422": + description: Unprocessable Entity + schema: + $ref: '#/definitions/response.Response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: Create UserRoleLevelDetails + tags: + - Task + /user-role-level-details/:id: + delete: + description: API for delete UserRoleLevelDetails + parameters: + - description: UserRoleLevelDetails ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.Response' + "404": + description: Not Found + schema: + $ref: '#/definitions/response.Response' + "422": + description: Unprocessable Entity + schema: + $ref: '#/definitions/response.Response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: delete UserRoleLevelDetails + tags: + - Task + get: + description: API for getting one UserRoleLevelDetails + parameters: + - description: UserRoleLevelDetails ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.Response' + "404": + description: Not Found + schema: + $ref: '#/definitions/response.Response' + "422": + description: Unprocessable Entity + schema: + $ref: '#/definitions/response.Response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: Get one UserRoleLevelDetails + tags: + - Task + put: + description: API for update UserRoleLevelDetails + parameters: + - description: UserRoleLevelDetails ID + in: path + name: id + required: true + type: integer + responses: + "200": + description: OK + schema: + $ref: '#/definitions/response.Response' + "401": + description: Unauthorized + schema: + $ref: '#/definitions/response.Response' + "404": + description: Not Found + schema: + $ref: '#/definitions/response.Response' + "422": + description: Unprocessable Entity + schema: + $ref: '#/definitions/response.Response' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/response.Response' + security: + - Bearer: [] + summary: update UserRoleLevelDetails + tags: + - Task /user-roles: get: description: API for getting all UserRoles diff --git a/main.go b/main.go index 8a4a5ff..44c24d2 100644 --- a/main.go +++ b/main.go @@ -20,6 +20,7 @@ import ( "go-humas-be/app/module/provinces" "go-humas-be/app/module/user_levels" "go-humas-be/app/module/user_role_accesses" + "go-humas-be/app/module/user_role_level_details" "go-humas-be/app/module/user_roles" "go-humas-be/app/module/users" "go-humas-be/app/router" @@ -69,6 +70,7 @@ func main() { user_roles.NewUserRolesModule, user_role_accesses.NewUserRoleAccessesModule, users.NewUsersModule, + user_role_level_details.NewUserRoleLevelDetailsModule, // start aplication fx.Invoke(webserver.Start),