feat: update advertisement, users, articles, etc
This commit is contained in:
parent
de618efe3a
commit
74da9d3e90
|
|
@ -11,6 +11,7 @@ type Advertisement struct {
|
||||||
ContentFileName *string `json:"content_file_name" gorm:"type:varchar"`
|
ContentFileName *string `json:"content_file_name" gorm:"type:varchar"`
|
||||||
Placement string `json:"placement" gorm:"type:varchar"`
|
Placement string `json:"placement" gorm:"type:varchar"`
|
||||||
StatusId int `json:"status_id" gorm:"type:int4"`
|
StatusId int `json:"status_id" gorm:"type:int4"`
|
||||||
|
IsPublish bool `json:"is_publish" gorm:"type:bool;default:true"`
|
||||||
IsActive bool `json:"is_active" gorm:"type:bool;default:true"`
|
IsActive bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ type Articles struct {
|
||||||
NeedApprovalFrom *int `json:"need_approval_from" gorm:"type:int4"`
|
NeedApprovalFrom *int `json:"need_approval_from" gorm:"type:int4"`
|
||||||
HasApprovedBy *string `json:"has_approved_by" gorm:"type:varchar"`
|
HasApprovedBy *string `json:"has_approved_by" gorm:"type:varchar"`
|
||||||
IsPublish *bool `json:"is_publish" gorm:"type:bool;default:false"`
|
IsPublish *bool `json:"is_publish" gorm:"type:bool;default:false"`
|
||||||
|
IsBanner *bool `json:"is_banner" gorm:"type:bool;default:false"`
|
||||||
PublishedAt *time.Time `json:"published_at" gorm:"type:timestamp"`
|
PublishedAt *time.Time `json:"published_at" gorm:"type:timestamp"`
|
||||||
IsDraft *bool `json:"is_draft" gorm:"type:bool;default:false"`
|
IsDraft *bool `json:"is_draft" gorm:"type:bool;default:false"`
|
||||||
DraftedAt *time.Time `json:"drafted_at" gorm:"type:timestamp"`
|
DraftedAt *time.Time `json:"drafted_at" gorm:"type:timestamp"`
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package entity
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type AuditTrails struct {
|
||||||
|
ID uint `gorm:"primaryKey"`
|
||||||
|
Method string
|
||||||
|
Path string
|
||||||
|
IP string
|
||||||
|
Status int
|
||||||
|
UserID *string
|
||||||
|
RequestHeaders string
|
||||||
|
RequestBody string
|
||||||
|
ResponseBody string
|
||||||
|
DurationMs int64
|
||||||
|
CreatedAt time.Time
|
||||||
|
}
|
||||||
|
|
@ -2,10 +2,11 @@ package entity
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type RegistrationOtps struct {
|
type OneTimePasswords struct {
|
||||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||||
Email string `json:"email" gorm:"type:varchar"`
|
Email string `json:"email" gorm:"type:varchar"`
|
||||||
Name *string `json:"name" gorm:"type:varchar"`
|
Name *string `json:"name" gorm:"type:varchar"`
|
||||||
|
Identity *string `json:"identity" gorm:"type:varchar"`
|
||||||
OtpCode string `json:"otp_code" gorm:"type:varchar"`
|
OtpCode string `json:"otp_code" gorm:"type:varchar"`
|
||||||
ValidUntil time.Time `json:"valid_until" gorm:"default:(NOW() + INTERVAL '10 minutes')"`
|
ValidUntil time.Time `json:"valid_until" gorm:"default:(NOW() + INTERVAL '10 minutes')"`
|
||||||
IsActive bool `json:"is_active" gorm:"type:bool"`
|
IsActive bool `json:"is_active" gorm:"type:bool"`
|
||||||
|
|
@ -28,6 +28,7 @@ type Users struct {
|
||||||
CreatedById *uint `json:"created_by_id" gorm:"type:int4"`
|
CreatedById *uint `json:"created_by_id" gorm:"type:int4"`
|
||||||
ProfilePicturePath *string `json:"profile_picture_path" gorm:"type:varchar"`
|
ProfilePicturePath *string `json:"profile_picture_path" gorm:"type:varchar"`
|
||||||
TempPassword *string `json:"temp_password" gorm:"type:varchar"`
|
TempPassword *string `json:"temp_password" gorm:"type:varchar"`
|
||||||
|
IsEmailUpdated *bool `json:"is_email_updated" gorm:"type:bool;default:false"`
|
||||||
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
IsActive *bool `json:"is_active" gorm:"type:bool;default:true"`
|
||||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,7 @@ func Models() []interface{} {
|
||||||
entity.ArticleFiles{},
|
entity.ArticleFiles{},
|
||||||
entity.ArticleComments{},
|
entity.ArticleComments{},
|
||||||
entity.ArticleNulisAI{},
|
entity.ArticleNulisAI{},
|
||||||
|
entity.AuditTrails{},
|
||||||
entity.Cities{},
|
entity.Cities{},
|
||||||
entity.CustomStaticPages{},
|
entity.CustomStaticPages{},
|
||||||
entity.Districts{},
|
entity.Districts{},
|
||||||
|
|
@ -105,7 +106,7 @@ func Models() []interface{} {
|
||||||
entity.MasterStatuses{},
|
entity.MasterStatuses{},
|
||||||
entity.MasterApprovalStatuses{},
|
entity.MasterApprovalStatuses{},
|
||||||
entity.Provinces{},
|
entity.Provinces{},
|
||||||
entity.RegistrationOtps{},
|
entity.OneTimePasswords{},
|
||||||
entity.UserLevels{},
|
entity.UserLevels{},
|
||||||
entity.UserRoles{},
|
entity.UserRoles{},
|
||||||
entity.UserRoleAccesses{},
|
entity.UserRoleAccesses{},
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"go-humas-be/app/database"
|
||||||
"go-humas-be/config/config"
|
"go-humas-be/config/config"
|
||||||
"go-humas-be/utils"
|
"go-humas-be/utils"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -12,6 +13,8 @@ import (
|
||||||
"github.com/gofiber/fiber/v2/middleware/monitor"
|
"github.com/gofiber/fiber/v2/middleware/monitor"
|
||||||
"github.com/gofiber/fiber/v2/middleware/pprof"
|
"github.com/gofiber/fiber/v2/middleware/pprof"
|
||||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||||
|
|
||||||
|
auditTrails "go-humas-be/config/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Middleware is a struct that contains all the middleware functions
|
// Middleware is a struct that contains all the middleware functions
|
||||||
|
|
@ -28,7 +31,7 @@ func NewMiddleware(app *fiber.App, cfg *config.Config) *Middleware {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register registers all the middleware functions
|
// Register registers all the middleware functions
|
||||||
func (m *Middleware) Register() {
|
func (m *Middleware) Register(db *database.Database) {
|
||||||
// Add Extra Middlewares
|
// Add Extra Middlewares
|
||||||
|
|
||||||
m.App.Use(limiter.New(limiter.Config{
|
m.App.Use(limiter.New(limiter.Config{
|
||||||
|
|
@ -60,6 +63,8 @@ func (m *Middleware) Register() {
|
||||||
MaxAge: 12,
|
MaxAge: 12,
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
m.App.Use(auditTrails.AuditTrailsMiddleware(db.DB))
|
||||||
|
|
||||||
//m.App.Use(filesystem.New(filesystem.Config{
|
//m.App.Use(filesystem.New(filesystem.Config{
|
||||||
// Next: utils.IsEnabled(m.Cfg.Middleware.FileSystem.Enable),
|
// Next: utils.IsEnabled(m.Cfg.Middleware.FileSystem.Enable),
|
||||||
// Root: http.Dir(m.Cfg.Middleware.FileSystem.Root),
|
// Root: http.Dir(m.Cfg.Middleware.FileSystem.Root),
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,9 @@ func (_i *AdvertisementRouter) RegisterAdvertisementRoutes() {
|
||||||
router.Get("/:id", advertisementController.Show)
|
router.Get("/:id", advertisementController.Show)
|
||||||
router.Post("/", advertisementController.Save)
|
router.Post("/", advertisementController.Save)
|
||||||
router.Post("/upload/:id", advertisementController.Upload)
|
router.Post("/upload/:id", advertisementController.Upload)
|
||||||
|
router.Get("/viewer/:filename", advertisementController.Viewer)
|
||||||
router.Put("/:id", advertisementController.Update)
|
router.Put("/:id", advertisementController.Update)
|
||||||
|
router.Put("/publish/:id", advertisementController.UpdatePublish)
|
||||||
router.Delete("/:id", advertisementController.Delete)
|
router.Delete("/:id", advertisementController.Delete)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,9 @@ type AdvertisementController interface {
|
||||||
Save(c *fiber.Ctx) error
|
Save(c *fiber.Ctx) error
|
||||||
Upload(c *fiber.Ctx) error
|
Upload(c *fiber.Ctx) error
|
||||||
Update(c *fiber.Ctx) error
|
Update(c *fiber.Ctx) error
|
||||||
|
UpdatePublish(c *fiber.Ctx) error
|
||||||
Delete(c *fiber.Ctx) error
|
Delete(c *fiber.Ctx) error
|
||||||
|
Viewer(c *fiber.Ctx) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAdvertisementController(advertisementService service.AdvertisementService, log zerolog.Logger) AdvertisementController {
|
func NewAdvertisementController(advertisementService service.AdvertisementService, log zerolog.Logger) AdvertisementController {
|
||||||
|
|
@ -197,6 +199,40 @@ func (_i *advertisementController) Update(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdatePublish Advertisement
|
||||||
|
// @Summary Update Publish Advertisement
|
||||||
|
// @Description API for Update Publish Advertisement
|
||||||
|
// @Tags Advertisement
|
||||||
|
// @Security Bearer
|
||||||
|
// @Param id path int true "Advertisement ID"
|
||||||
|
// @Param isPublish path bool true "Advertisement Publish Status"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 400 {object} response.BadRequestError
|
||||||
|
// @Failure 401 {object} response.UnauthorizedError
|
||||||
|
// @Failure 500 {object} response.InternalServerError
|
||||||
|
// @Router /advertisement/publish/{id} [put]
|
||||||
|
func (_i *advertisementController) UpdatePublish(c *fiber.Ctx) error {
|
||||||
|
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
isPublish, err := strconv.ParseBool(c.Params("isPublish"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _i.advertisementService.UpdatePublish(uint(id), isPublish)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return utilRes.Resp(c, utilRes.Response{
|
||||||
|
Success: true,
|
||||||
|
Messages: utilRes.Messages{"Advertisement successfully publish updated"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Delete delete Advertisement
|
// Delete delete Advertisement
|
||||||
// @Summary delete Advertisement
|
// @Summary delete Advertisement
|
||||||
// @Description API for delete Advertisement
|
// @Description API for delete Advertisement
|
||||||
|
|
@ -224,3 +260,18 @@ func (_i *advertisementController) Delete(c *fiber.Ctx) error {
|
||||||
Messages: utilRes.Messages{"Advertisement successfully deleted"},
|
Messages: utilRes.Messages{"Advertisement successfully deleted"},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Viewer Advertisement
|
||||||
|
// @Summary Viewer Advertisement
|
||||||
|
// @Description API for Viewer Advertisement
|
||||||
|
// @Tags Advertisement
|
||||||
|
// @Security Bearer
|
||||||
|
// @Param filename path string true "Content File Name"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 400 {object} response.BadRequestError
|
||||||
|
// @Failure 401 {object} response.UnauthorizedError
|
||||||
|
// @Failure 500 {object} response.InternalServerError
|
||||||
|
// @Router /advertisement/viewer/{filename} [get]
|
||||||
|
func (_i *advertisementController) Viewer(c *fiber.Ctx) error {
|
||||||
|
return _i.advertisementService.Viewer(c)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ type advertisementRepository struct {
|
||||||
type AdvertisementRepository interface {
|
type AdvertisementRepository interface {
|
||||||
GetAll(req request.AdvertisementQueryRequest) (advertisements []*entity.Advertisement, paging paginator.Pagination, err error)
|
GetAll(req request.AdvertisementQueryRequest) (advertisements []*entity.Advertisement, paging paginator.Pagination, err error)
|
||||||
FindOne(id uint) (advertisement *entity.Advertisement, err error)
|
FindOne(id uint) (advertisement *entity.Advertisement, err error)
|
||||||
|
FindByFilename(contentFilename string) (advertisement *entity.Advertisement, err error)
|
||||||
Create(advertisement *entity.Advertisement) (advertisementReturn *entity.Advertisement, err error)
|
Create(advertisement *entity.Advertisement) (advertisementReturn *entity.Advertisement, err error)
|
||||||
Update(id uint, advertisement *entity.Advertisement) (err error)
|
Update(id uint, advertisement *entity.Advertisement) (err error)
|
||||||
Delete(id uint) (err error)
|
Delete(id uint) (err error)
|
||||||
|
|
@ -88,6 +89,15 @@ func (_i *advertisementRepository) FindOne(id uint) (advertisement *entity.Adver
|
||||||
return advertisement, nil
|
return advertisement, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_i *advertisementRepository) FindByFilename(contentFilename string) (advertisement *entity.Advertisement, err error) {
|
||||||
|
|
||||||
|
if err := _i.DB.DB.Where("content_file_name = ?", contentFilename).First(&advertisement).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return advertisement, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (_i *advertisementRepository) Create(advertisement *entity.Advertisement) (advertisementReturn *entity.Advertisement, err error) {
|
func (_i *advertisementRepository) Create(advertisement *entity.Advertisement) (advertisementReturn *entity.Advertisement, err error) {
|
||||||
result := _i.DB.DB.Create(advertisement)
|
result := _i.DB.DB.Create(advertisement)
|
||||||
return advertisement, result.Error
|
return advertisement, result.Error
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ type AdvertisementQueryRequest struct {
|
||||||
Description *string `json:"description"`
|
Description *string `json:"description"`
|
||||||
RedirectLink *string `json:"redirectLink"`
|
RedirectLink *string `json:"redirectLink"`
|
||||||
Placement *string `json:"placement"`
|
Placement *string `json:"placement"`
|
||||||
|
IsPublish *bool `json:"isPublish"`
|
||||||
StatusId *int `json:"statusId"`
|
StatusId *int `json:"statusId"`
|
||||||
Pagination *paginator.Pagination `json:"pagination"`
|
Pagination *paginator.Pagination `json:"pagination"`
|
||||||
}
|
}
|
||||||
|
|
@ -34,6 +35,8 @@ func (req AdvertisementCreateRequest) ToEntity() *entity.Advertisement {
|
||||||
RedirectLink: req.RedirectLink,
|
RedirectLink: req.RedirectLink,
|
||||||
Placement: req.Placement,
|
Placement: req.Placement,
|
||||||
StatusId: 1,
|
StatusId: 1,
|
||||||
|
IsPublish: true,
|
||||||
|
IsActive: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,6 +65,7 @@ type AdvertisementQueryRequestContext struct {
|
||||||
RedirectLink string `json:"redirectLink"`
|
RedirectLink string `json:"redirectLink"`
|
||||||
Placement string `json:"placement"`
|
Placement string `json:"placement"`
|
||||||
StatusId string `json:"statusId"`
|
StatusId string `json:"statusId"`
|
||||||
|
IsPublish string `json:"isPublish"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (req AdvertisementQueryRequestContext) ToParamRequest() AdvertisementQueryRequest {
|
func (req AdvertisementQueryRequestContext) ToParamRequest() AdvertisementQueryRequest {
|
||||||
|
|
@ -79,6 +83,12 @@ func (req AdvertisementQueryRequestContext) ToParamRequest() AdvertisementQueryR
|
||||||
if placement := req.Placement; placement != "" {
|
if placement := req.Placement; placement != "" {
|
||||||
request.Placement = &placement
|
request.Placement = &placement
|
||||||
}
|
}
|
||||||
|
if isPublishStr := req.IsPublish; isPublishStr != "" {
|
||||||
|
isPublish, err := strconv.ParseBool(isPublishStr)
|
||||||
|
if err == nil {
|
||||||
|
request.IsPublish = &isPublish
|
||||||
|
}
|
||||||
|
}
|
||||||
if statusIdStr := req.StatusId; statusIdStr != "" {
|
if statusIdStr := req.StatusId; statusIdStr != "" {
|
||||||
statusId, err := strconv.Atoi(statusIdStr)
|
statusId, err := strconv.Atoi(statusIdStr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,10 @@ import (
|
||||||
usersRepository "go-humas-be/app/module/users/repository"
|
usersRepository "go-humas-be/app/module/users/repository"
|
||||||
minioStorage "go-humas-be/config/config"
|
minioStorage "go-humas-be/config/config"
|
||||||
"go-humas-be/utils/paginator"
|
"go-humas-be/utils/paginator"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"mime"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -36,7 +39,9 @@ type AdvertisementService interface {
|
||||||
Save(req request.AdvertisementCreateRequest) (advertisement *entity.Advertisement, err error)
|
Save(req request.AdvertisementCreateRequest) (advertisement *entity.Advertisement, err error)
|
||||||
Upload(c *fiber.Ctx, id uint) (err error)
|
Upload(c *fiber.Ctx, id uint) (err error)
|
||||||
Update(id uint, req request.AdvertisementUpdateRequest) (err error)
|
Update(id uint, req request.AdvertisementUpdateRequest) (err error)
|
||||||
|
UpdatePublish(id uint, isPublish bool) (err error)
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
|
Viewer(c *fiber.Ctx) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAdvertisementService init AdvertisementService
|
// NewAdvertisementService init AdvertisementService
|
||||||
|
|
@ -165,6 +170,17 @@ func (_i *advertisementService) Update(id uint, req request.AdvertisementUpdateR
|
||||||
return _i.Repo.Update(id, req.ToEntity())
|
return _i.Repo.Update(id, req.ToEntity())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_i *advertisementService) UpdatePublish(id uint, isPublish bool) (err error) {
|
||||||
|
result, err := _i.Repo.FindOne(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
result.IsPublish = isPublish
|
||||||
|
|
||||||
|
return _i.Repo.Update(id, result)
|
||||||
|
}
|
||||||
|
|
||||||
func (_i *advertisementService) Delete(id uint) error {
|
func (_i *advertisementService) Delete(id uint) error {
|
||||||
result, err := _i.Repo.FindOne(id)
|
result, err := _i.Repo.FindOne(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -174,3 +190,58 @@ func (_i *advertisementService) Delete(id uint) error {
|
||||||
result.IsActive = false
|
result.IsActive = false
|
||||||
return _i.Repo.Update(id, result)
|
return _i.Repo.Update(id, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_i *advertisementService) Viewer(c *fiber.Ctx) (err error) {
|
||||||
|
filename := c.Params("filename")
|
||||||
|
result, err := _i.Repo.FindByFilename(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
bucketName := _i.MinioStorage.Cfg.ObjectStorage.MinioStorage.BucketName
|
||||||
|
objectName := *result.ContentFilePath
|
||||||
|
|
||||||
|
// 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()
|
||||||
|
|
||||||
|
// Tentukan Content-Type berdasarkan ekstensi file
|
||||||
|
contentType := mime.TypeByExtension("." + getFileExtension(objectName))
|
||||||
|
if contentType == "" {
|
||||||
|
contentType = "application/octet-stream" // fallback jika tidak ada tipe MIME yang cocok
|
||||||
|
}
|
||||||
|
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -193,8 +193,8 @@ func (_i *articleFilesController) Delete(c *fiber.Ctx) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Viewer ArticleFiles
|
// Viewer ArticleFiles
|
||||||
// @Summary Create ArticleFiles
|
// @Summary Viewer ArticleFiles
|
||||||
// @Description API for create ArticleFiles
|
// @Description API for Viewer ArticleFiles
|
||||||
// @Tags Article Files
|
// @Tags Article Files
|
||||||
// @Security Bearer
|
// @Security Bearer
|
||||||
// @Param filename path string true "Article File Name"
|
// @Param filename path string true "Article File Name"
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ func (_i *ArticlesRouter) RegisterArticlesRoutes() {
|
||||||
router.Get("/:id", articlesController.Show)
|
router.Get("/:id", articlesController.Show)
|
||||||
router.Post("/", articlesController.Save)
|
router.Post("/", articlesController.Save)
|
||||||
router.Put("/:id", articlesController.Update)
|
router.Put("/:id", articlesController.Update)
|
||||||
|
router.Put("/banner/:id", articlesController.UpdateBanner)
|
||||||
router.Post("/thumbnail/:id", articlesController.SaveThumbnail)
|
router.Post("/thumbnail/:id", articlesController.SaveThumbnail)
|
||||||
router.Get("/thumbnail/viewer/:thumbnailName", articlesController.Viewer)
|
router.Get("/thumbnail/viewer/:thumbnailName", articlesController.Viewer)
|
||||||
router.Post("/publish-scheduling", articlesController.PublishScheduling)
|
router.Post("/publish-scheduling", articlesController.PublishScheduling)
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ type ArticlesController interface {
|
||||||
Save(c *fiber.Ctx) error
|
Save(c *fiber.Ctx) error
|
||||||
SaveThumbnail(c *fiber.Ctx) error
|
SaveThumbnail(c *fiber.Ctx) error
|
||||||
Update(c *fiber.Ctx) error
|
Update(c *fiber.Ctx) error
|
||||||
|
UpdateBanner(c *fiber.Ctx) error
|
||||||
Delete(c *fiber.Ctx) error
|
Delete(c *fiber.Ctx) error
|
||||||
Viewer(c *fiber.Ctx) error
|
Viewer(c *fiber.Ctx) error
|
||||||
SummaryStats(c *fiber.Ctx) error
|
SummaryStats(c *fiber.Ctx) error
|
||||||
|
|
@ -199,6 +200,40 @@ func (_i *articlesController) Update(c *fiber.Ctx) error {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateBanner Articles
|
||||||
|
// @Summary Update Banner Articles
|
||||||
|
// @Description API for Update Banner Articles
|
||||||
|
// @Tags Articles
|
||||||
|
// @Security Bearer
|
||||||
|
// @Param id path int true "Articles ID"
|
||||||
|
// @Param isBanner path bool true "Articles Banner Status"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 400 {object} response.BadRequestError
|
||||||
|
// @Failure 401 {object} response.UnauthorizedError
|
||||||
|
// @Failure 500 {object} response.InternalServerError
|
||||||
|
// @Router /articles/banner/{id} [put]
|
||||||
|
func (_i *articlesController) UpdateBanner(c *fiber.Ctx) error {
|
||||||
|
id, err := strconv.ParseUint(c.Params("id"), 10, 0)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
isBanner, err := strconv.ParseBool(c.Params("isBanner"))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _i.articlesService.UpdateBanner(uint(id), isBanner)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return utilRes.Resp(c, utilRes.Response{
|
||||||
|
Success: true,
|
||||||
|
Messages: utilRes.Messages{"Articles successfully banner updated"},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Delete Articles
|
// Delete Articles
|
||||||
// @Summary Delete Articles
|
// @Summary Delete Articles
|
||||||
// @Description API for delete Articles
|
// @Description API for delete Articles
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ type ArticlesService interface {
|
||||||
Delete(id uint) error
|
Delete(id uint) error
|
||||||
UpdateActivityCount(id uint, activityTypeId int) (err error)
|
UpdateActivityCount(id uint, activityTypeId int) (err error)
|
||||||
UpdateApproval(id uint, statusId int, userLevelId int, userLevelNumber int, userParentLevelId int) (err error)
|
UpdateApproval(id uint, statusId int, userLevelId int, userLevelNumber int, userParentLevelId int) (err error)
|
||||||
|
UpdateBanner(id uint, isBanner bool) error
|
||||||
Viewer(c *fiber.Ctx) error
|
Viewer(c *fiber.Ctx) error
|
||||||
SummaryStats(authToken string) (summaryStats *response.ArticleSummaryStats, err error)
|
SummaryStats(authToken string) (summaryStats *response.ArticleSummaryStats, err error)
|
||||||
ArticlePerUserLevelStats(authToken string, startDate *string, endDate *string) (articlePerUserLevelStats []*response.ArticlePerUserLevelStats, err error)
|
ArticlePerUserLevelStats(authToken string, startDate *string, endDate *string) (articlePerUserLevelStats []*response.ArticlePerUserLevelStats, err error)
|
||||||
|
|
@ -577,7 +578,15 @@ func (_i *articlesService) PublishScheduling(id uint, publishSchedule string) er
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
result.PublishSchedule = &publishSchedule
|
result.PublishSchedule = &publishSchedule
|
||||||
|
return _i.Repo.Update(id, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_i *articlesService) UpdateBanner(id uint, isBanner bool) error {
|
||||||
|
result, err := _i.Repo.FindOne(id)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
result.IsBanner = &isBanner
|
||||||
return _i.Repo.Update(id, result)
|
return _i.Repo.Update(id, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,8 @@ type UsersController interface {
|
||||||
ForgotPassword(c *fiber.Ctx) error
|
ForgotPassword(c *fiber.Ctx) error
|
||||||
OtpRequest(c *fiber.Ctx) error
|
OtpRequest(c *fiber.Ctx) error
|
||||||
OtpValidation(c *fiber.Ctx) error
|
OtpValidation(c *fiber.Ctx) error
|
||||||
|
EmailValidation(c *fiber.Ctx) error
|
||||||
|
SetupEmail(c *fiber.Ctx) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUsersController(usersService service.UsersService) UsersController {
|
func NewUsersController(usersService service.UsersService) UsersController {
|
||||||
|
|
@ -469,3 +471,59 @@ func (_i *usersController) OtpValidation(c *fiber.Ctx) error {
|
||||||
Messages: utilRes.Messages{"OTP is valid"},
|
Messages: utilRes.Messages{"OTP is valid"},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EmailValidation Users
|
||||||
|
// @Summary EmailValidation Users
|
||||||
|
// @Description API for Email Validation Users
|
||||||
|
// @Tags Users
|
||||||
|
// @Security Bearer
|
||||||
|
// @Param payload body request.UserEmailValidationRequest true "Required payload"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 400 {object} response.BadRequestError
|
||||||
|
// @Failure 401 {object} response.UnauthorizedError
|
||||||
|
// @Failure 500 {object} response.InternalServerError
|
||||||
|
// @Router /users/email-validation [post]
|
||||||
|
func (_i *usersController) EmailValidation(c *fiber.Ctx) error {
|
||||||
|
req := new(request.UserEmailValidationRequest)
|
||||||
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
messageResponse, err := _i.usersService.EmailValidationPreLogin(*req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return utilRes.Resp(c, utilRes.Response{
|
||||||
|
Success: true,
|
||||||
|
Messages: utilRes.Messages{messageResponse},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetupEmail Users
|
||||||
|
// @Summary SetupEmail Users
|
||||||
|
// @Description API for Setup Email Users
|
||||||
|
// @Tags Users
|
||||||
|
// @Security Bearer
|
||||||
|
// @Param payload body request.UserEmailValidationRequest true "Required payload"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 400 {object} response.BadRequestError
|
||||||
|
// @Failure 401 {object} response.UnauthorizedError
|
||||||
|
// @Failure 500 {object} response.InternalServerError
|
||||||
|
// @Router /users/setup-email [post]
|
||||||
|
func (_i *usersController) SetupEmail(c *fiber.Ctx) error {
|
||||||
|
req := new(request.UserEmailValidationRequest)
|
||||||
|
if err := utilVal.ParseAndValidate(c, req); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
messageResponse, err := _i.usersService.SetupEmail(*req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return utilRes.Resp(c, utilRes.Response{
|
||||||
|
Success: true,
|
||||||
|
Messages: utilRes.Messages{messageResponse},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,9 @@ type UsersRepository interface {
|
||||||
CreateForgotPassword(forgotPasswords *entity.ForgotPasswords) (err error)
|
CreateForgotPassword(forgotPasswords *entity.ForgotPasswords) (err error)
|
||||||
UpdateForgotPassword(id uint, forgotPasswords *entity.ForgotPasswords) (err error)
|
UpdateForgotPassword(id uint, forgotPasswords *entity.ForgotPasswords) (err error)
|
||||||
FindForgotPassword(keycloakId string, code string) (forgotPasswords *entity.ForgotPasswords, err error)
|
FindForgotPassword(keycloakId string, code string) (forgotPasswords *entity.ForgotPasswords, err error)
|
||||||
CreateRegistrationOtps(registrationOtps *entity.RegistrationOtps) (err error)
|
CreateOtp(otp *entity.OneTimePasswords) (err error)
|
||||||
FindRegistrationOtps(email string, code string) (registrationOtps *entity.RegistrationOtps, err error)
|
FindOtpByEmail(email string, code string) (otp *entity.OneTimePasswords, err error)
|
||||||
|
FindOtpByIdentity(identity string, code string) (otp *entity.OneTimePasswords, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUsersRepository(db *database.Database, log zerolog.Logger) UsersRepository {
|
func NewUsersRepository(db *database.Database, log zerolog.Logger) UsersRepository {
|
||||||
|
|
@ -168,15 +169,23 @@ func (_i *usersRepository) FindForgotPassword(keycloakId string, code string) (f
|
||||||
return forgotPasswords, nil
|
return forgotPasswords, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersRepository) CreateRegistrationOtps(registrationOtps *entity.RegistrationOtps) (err error) {
|
func (_i *usersRepository) CreateOtp(otp *entity.OneTimePasswords) (err error) {
|
||||||
result := _i.DB.DB.Create(registrationOtps)
|
result := _i.DB.DB.Create(otp)
|
||||||
return result.Error
|
return result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersRepository) FindRegistrationOtps(email string, code string) (registrationOtps *entity.RegistrationOtps, err error) {
|
func (_i *usersRepository) FindOtpByEmail(email string, code string) (otp *entity.OneTimePasswords, err error) {
|
||||||
if err := _i.DB.DB.Where("email = ?", email).Where("otp_code = ?", code).First(®istrationOtps).Error; err != nil {
|
if err := _i.DB.DB.Where("email = ?", email).Where("otp_code = ?", code).First(&otp).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return registrationOtps, nil
|
return otp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_i *usersRepository) FindOtpByIdentity(identity string, code string) (otp *entity.OneTimePasswords, err error) {
|
||||||
|
if err := _i.DB.DB.Where("identity = ?", identity).Where("otp_code = ?", code).First(&otp).Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return otp, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -129,13 +129,21 @@ type UserResetPassword struct {
|
||||||
ConfirmPassword string `json:"confirmPassword"`
|
ConfirmPassword string `json:"confirmPassword"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type UserEmailValidationRequest struct {
|
||||||
|
Username *string `json:"username"`
|
||||||
|
Password *string `json:"password"`
|
||||||
|
OldEmail *string `json:"oldEmail"`
|
||||||
|
NewEmail *string `json:"newEmail"`
|
||||||
|
}
|
||||||
|
|
||||||
type UserOtpRequest struct {
|
type UserOtpRequest struct {
|
||||||
Email string `json:"email" validate:"required,email"`
|
Email string `json:"email" validate:"required,email"`
|
||||||
Name *string `json:"name"`
|
Name *string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserOtpValidation struct {
|
type UserOtpValidation struct {
|
||||||
Email string `json:"email"`
|
Email *string `json:"email"`
|
||||||
|
Username *string `json:"username"`
|
||||||
OtpCode string `json:"otpCode"`
|
OtpCode string `json:"otpCode"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,12 @@ type UsersService interface {
|
||||||
SavePassword(req request.UserSavePassword, authToken string) (err error)
|
SavePassword(req request.UserSavePassword, authToken string) (err error)
|
||||||
ResetPassword(req request.UserResetPassword) (err error)
|
ResetPassword(req request.UserResetPassword) (err error)
|
||||||
ForgotPassword(req request.UserForgotPassword) (err error)
|
ForgotPassword(req request.UserForgotPassword) (err error)
|
||||||
|
EmailValidationPreLogin(req request.UserEmailValidationRequest) (msgResponse *string, err error)
|
||||||
|
SetupEmail(req request.UserEmailValidationRequest) (msgResponse *string, err error)
|
||||||
OtpRequest(req request.UserOtpRequest) (err error)
|
OtpRequest(req request.UserOtpRequest) (err error)
|
||||||
OtpValidation(req request.UserOtpValidation) (err error)
|
OtpValidation(req request.UserOtpValidation) (err error)
|
||||||
|
SendLoginOtp(name string, email string, otp string) error
|
||||||
|
SendRegistrationOtp(name string, email string, otp string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewUsersService init UsersService
|
// NewUsersService init UsersService
|
||||||
|
|
@ -343,47 +347,50 @@ func (_i *usersService) OtpRequest(req request.UserOtpRequest) (err error) {
|
||||||
_i.Log.Info().Interface("data", req).Msg("")
|
_i.Log.Info().Interface("data", req).Msg("")
|
||||||
|
|
||||||
codeRequest, err := utilSvc.GenerateNumericCode(6)
|
codeRequest, err := utilSvc.GenerateNumericCode(6)
|
||||||
|
if req.Name == nil {
|
||||||
|
req.Name = &req.Email
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
otpReq := entity.RegistrationOtps{
|
otpReq := entity.OneTimePasswords{
|
||||||
Email: req.Email,
|
Email: req.Email,
|
||||||
Name: req.Name,
|
Name: req.Name,
|
||||||
OtpCode: codeRequest,
|
OtpCode: codeRequest,
|
||||||
IsActive: true,
|
IsActive: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
subject := "[HUMAS POLRI] Permintaan OTP"
|
err = _i.Repo.CreateOtp(&otpReq)
|
||||||
htmlBody := fmt.Sprintf("<p>Hai %s !</p><p>Berikut kode OTP yang digunakan untuk verifikasi.</p>", *req.Name)
|
|
||||||
htmlBody += fmt.Sprintf("<p style='padding: 10px 50px; background: #eef2f6; border-radius: 8px; max-width: 300px; text-align: center'><b>%s</b></p>", codeRequest)
|
|
||||||
htmlBody += "<p style='padding-top: 10px;'>Kode diatas hanya berlaku selama 10 menit. Harap segera masukan kode tersebut pada aplikasi HUMAS POLRI.</p>"
|
|
||||||
htmlBody += "<p style='padding-top: 10px; padding-bottom: 10px'>Demi menjaga kerahasiaan data kamu, mohon jangan membagikan kode OTP ke siapapun.</p>"
|
|
||||||
err = _i.Smtp.SendEmail(subject, req.Email, req.Email, htmlBody)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = _i.Repo.CreateRegistrationOtps(&otpReq)
|
err = _i.SendRegistrationOtp(*req.Name, req.Email, codeRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// send otp to email
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersService) OtpValidation(req request.UserOtpValidation) (err error) {
|
func (_i *usersService) OtpValidation(req request.UserOtpValidation) (err error) {
|
||||||
_i.Log.Info().Interface("data", req).Msg("")
|
_i.Log.Info().Interface("data", req).Msg("")
|
||||||
|
|
||||||
registrationOtp, err := _i.Repo.FindRegistrationOtps(req.Email, req.OtpCode)
|
var otp *entity.OneTimePasswords
|
||||||
|
if req.Email == nil {
|
||||||
|
otp, err = _i.Repo.FindOtpByIdentity(*req.Username, req.OtpCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("OTP is not valid")
|
return fmt.Errorf("OTP is not valid")
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
otp, err = _i.Repo.FindOtpByEmail(*req.Email, req.OtpCode)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("OTP is not valid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if registrationOtp != nil {
|
if otp != nil {
|
||||||
if registrationOtp.ValidUntil.Before(time.Now()) {
|
if otp.ValidUntil.Before(time.Now()) {
|
||||||
return fmt.Errorf("OTP has expired")
|
return fmt.Errorf("OTP has expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -393,6 +400,108 @@ func (_i *usersService) OtpValidation(req request.UserOtpValidation) (err error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_i *usersService) EmailValidationPreLogin(req request.UserEmailValidationRequest) (msgResponse *string, err error) {
|
||||||
|
_i.Log.Info().Interface("data", req).Msg("")
|
||||||
|
|
||||||
|
var loginResponse *gocloak.JWT
|
||||||
|
loginResponse, err = _i.Keycloak.Login(*req.Username, *req.Password)
|
||||||
|
|
||||||
|
if loginResponse == nil || err != nil {
|
||||||
|
return nil, fmt.Errorf("username / password incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
findUser, err := _i.Repo.FindByUsername(*req.Username)
|
||||||
|
if findUser == nil || err != nil {
|
||||||
|
return nil, fmt.Errorf("username / password incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
isTrue := true
|
||||||
|
if findUser.IsEmailUpdated != &isTrue {
|
||||||
|
message := "Continue to setup email"
|
||||||
|
msgResponse = &message
|
||||||
|
} else {
|
||||||
|
codeRequest, err := utilSvc.GenerateNumericCode(6)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
otpReq := entity.OneTimePasswords{
|
||||||
|
Email: findUser.Email,
|
||||||
|
Identity: &findUser.Username,
|
||||||
|
OtpCode: codeRequest,
|
||||||
|
IsActive: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _i.Repo.CreateOtp(&otpReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _i.SendLoginOtp(findUser.Fullname, findUser.Email, codeRequest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
msg := "Email is valid and OTP has been sent"
|
||||||
|
msgResponse = &msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_i *usersService) SetupEmail(req request.UserEmailValidationRequest) (msgResponse *string, err error) {
|
||||||
|
_i.Log.Info().Interface("data", req).Msg("")
|
||||||
|
|
||||||
|
var loginResponse *gocloak.JWT
|
||||||
|
loginResponse, err = _i.Keycloak.Login(*req.Username, *req.Password)
|
||||||
|
|
||||||
|
if loginResponse == nil || err != nil {
|
||||||
|
return nil, fmt.Errorf("username / password incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
findUser, err := _i.Repo.FindByUsername(*req.Username)
|
||||||
|
if findUser == nil || err != nil {
|
||||||
|
return nil, fmt.Errorf("username / password incorrect")
|
||||||
|
}
|
||||||
|
|
||||||
|
isTrue := true
|
||||||
|
if findUser.Email == *req.OldEmail {
|
||||||
|
findUser.Email = *req.NewEmail
|
||||||
|
findUser.IsEmailUpdated = &isTrue
|
||||||
|
err = _i.Repo.Update(findUser.ID, findUser)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
codeRequest, err := utilSvc.GenerateNumericCode(6)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
otpReq := entity.OneTimePasswords{
|
||||||
|
Email: findUser.Email,
|
||||||
|
Identity: &findUser.Username,
|
||||||
|
OtpCode: codeRequest,
|
||||||
|
IsActive: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _i.Repo.CreateOtp(&otpReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = _i.SendLoginOtp(findUser.Fullname, findUser.Email, codeRequest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
msg := "Email is valid and OTP has been sent"
|
||||||
|
msgResponse = &msg
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("the old email is not same")
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgResponse, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ParseJWTToken(token string) (map[string]interface{}, error) {
|
func ParseJWTToken(token string) (map[string]interface{}, error) {
|
||||||
// Pisahkan JWT menjadi 3 bagian: header, payload, dan signature
|
// Pisahkan JWT menjadi 3 bagian: header, payload, dan signature
|
||||||
parts := strings.Split(token, ".")
|
parts := strings.Split(token, ".")
|
||||||
|
|
@ -414,3 +523,25 @@ func ParseJWTToken(token string) (map[string]interface{}, error) {
|
||||||
|
|
||||||
return payload, nil
|
return payload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_i *usersService) SendLoginOtp(name string, email string, otp string) error {
|
||||||
|
subject := "[HUMAS POLRI] Permintaan OTP"
|
||||||
|
htmlBody := fmt.Sprintf("<p>Hai %s !</p><p>Berikut kode OTP yang digunakan untuk Login.</p>", name)
|
||||||
|
htmlBody += fmt.Sprintf("<p style='padding: 10px 50px; background: #eef2f6; border-radius: 8px; max-width: 300px; text-align: center'><b>%s</b></p>", otp)
|
||||||
|
htmlBody += "<p style='padding-top: 10px;'>Kode diatas hanya berlaku selama 10 menit. Harap segera masukkan kode tersebut pada aplikasi HUMAS POLRI.</p>"
|
||||||
|
htmlBody += "<p style='padding-top: 10px; padding-bottom: 10px'>Demi menjaga kerahasiaan data kamu, mohon jangan membagikan kode OTP ke siapapun.</p>"
|
||||||
|
err := _i.Smtp.SendEmail(subject, email, name, htmlBody)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_i *usersService) SendRegistrationOtp(name string, email string, otp string) error {
|
||||||
|
subject := "[HUMAS POLRI] Permintaan OTP"
|
||||||
|
htmlBody := fmt.Sprintf("<p>Hai %s !</p><p>Berikut kode OTP yang digunakan untuk Verifikasi Registrasi.</p>", name)
|
||||||
|
htmlBody += fmt.Sprintf("<p style='padding: 10px 50px; background: #eef2f6; border-radius: 8px; max-width: 300px; text-align: center'><b>%s</b></p>", otp)
|
||||||
|
htmlBody += "<p style='padding-top: 10px;'>Kode diatas hanya berlaku selama 10 menit. Harap segera masukkan kode tersebut pada aplikasi HUMAS POLRI.</p>"
|
||||||
|
htmlBody += "<p style='padding-top: 10px; padding-bottom: 10px'>Demi menjaga kerahasiaan data kamu, mohon jangan membagikan kode OTP ke siapapun.</p>"
|
||||||
|
err := _i.Smtp.SendEmail(subject, email, name, htmlBody)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ func (_i *UsersRouter) RegisterUsersRoutes() {
|
||||||
router.Post("/forgot-password", usersController.ForgotPassword)
|
router.Post("/forgot-password", usersController.ForgotPassword)
|
||||||
router.Post("/otp-request", usersController.OtpRequest)
|
router.Post("/otp-request", usersController.OtpRequest)
|
||||||
router.Post("/otp-validation", usersController.OtpValidation)
|
router.Post("/otp-validation", usersController.OtpValidation)
|
||||||
|
router.Post("/email-validation", usersController.EmailValidation)
|
||||||
|
router.Post("/setup-email", usersController.SetupEmail)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,10 @@ type middleware = struct {
|
||||||
Max int
|
Max int
|
||||||
Expiration time.Duration `toml:"expiration_seconds"`
|
Expiration time.Duration `toml:"expiration_seconds"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AuditTrails struct {
|
||||||
|
Enable bool
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// minio struct config
|
// minio struct config
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package middleware
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
"go-humas-be/app/database/entity"
|
||||||
|
utilSvc "go-humas-be/utils/service"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AuditTrailsMiddleware(db *gorm.DB) fiber.Handler {
|
||||||
|
return func(c *fiber.Ctx) error {
|
||||||
|
start := time.Now()
|
||||||
|
requestBody := c.Body()
|
||||||
|
|
||||||
|
headersMap := c.GetReqHeaders()
|
||||||
|
headersJSON, _ := json.Marshal(headersMap)
|
||||||
|
|
||||||
|
authHeader := c.Get("Authorization")
|
||||||
|
userId := utilSvc.GetUserId(authHeader)
|
||||||
|
|
||||||
|
err := c.Next()
|
||||||
|
|
||||||
|
audit := entity.AuditTrails{
|
||||||
|
Method: c.Method(),
|
||||||
|
Path: c.OriginalURL(),
|
||||||
|
IP: c.IP(),
|
||||||
|
Status: c.Response().StatusCode(),
|
||||||
|
UserID: userId,
|
||||||
|
RequestHeaders: string(headersJSON),
|
||||||
|
RequestBody: string(requestBody),
|
||||||
|
ResponseBody: string(c.Response().Body()),
|
||||||
|
DurationMs: time.Since(start).Milliseconds(),
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
go db.Create(&audit)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,7 +14,7 @@ body-limit = 1048576000 # "100 * 1024 * 1024"
|
||||||
[db.postgres]
|
[db.postgres]
|
||||||
dsn = "postgresql://humas_user:HumasDB@2024@38.47.180.165:5432/humas_db" # <driver>://<username>:<password>@<host>:<port>/<database>
|
dsn = "postgresql://humas_user:HumasDB@2024@38.47.180.165:5432/humas_db" # <driver>://<username>:<password>@<host>:<port>/<database>
|
||||||
log-mode = "NONE"
|
log-mode = "NONE"
|
||||||
migrate = true
|
migrate = false
|
||||||
seed = false
|
seed = false
|
||||||
|
|
||||||
[logger]
|
[logger]
|
||||||
|
|
@ -39,7 +39,7 @@ level = 1
|
||||||
enable = true
|
enable = true
|
||||||
|
|
||||||
[middleware.monitor]
|
[middleware.monitor]
|
||||||
enable = false
|
enable = true
|
||||||
path = "/monitor"
|
path = "/monitor"
|
||||||
|
|
||||||
[middleware.pprof]
|
[middleware.pprof]
|
||||||
|
|
@ -49,10 +49,13 @@ enable = true
|
||||||
enable = true
|
enable = true
|
||||||
|
|
||||||
[middleware.limiter]
|
[middleware.limiter]
|
||||||
enable = false
|
enable = true
|
||||||
max = 20
|
max = 20
|
||||||
expiration_seconds = 60
|
expiration_seconds = 60
|
||||||
|
|
||||||
|
[middleware.audittrails]
|
||||||
|
enable = true
|
||||||
|
|
||||||
[keycloak]
|
[keycloak]
|
||||||
endpoint = "http://38.47.180.165:8008"
|
endpoint = "http://38.47.180.165:8008"
|
||||||
realm = "humas"
|
realm = "humas"
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,14 @@ func Start(lifecycle fx.Lifecycle, cfg *config.Config, fiber *fiber.App, router
|
||||||
lifecycle.Append(
|
lifecycle.Append(
|
||||||
fx.Hook{
|
fx.Hook{
|
||||||
OnStart: func(ctx context.Context) error {
|
OnStart: func(ctx context.Context) error {
|
||||||
// Register middlewares & routes
|
|
||||||
middlewares.Register()
|
// Connect database
|
||||||
|
db.ConnectDatabase()
|
||||||
|
|
||||||
|
// Register middlewares
|
||||||
|
middlewares.Register(db)
|
||||||
|
|
||||||
|
// Register routes
|
||||||
router.Register()
|
router.Register()
|
||||||
|
|
||||||
// Custom Startup Messages
|
// Custom Startup Messages
|
||||||
|
|
@ -108,8 +114,6 @@ func Start(lifecycle fx.Lifecycle, cfg *config.Config, fiber *fiber.App, router
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
db.ConnectDatabase()
|
|
||||||
|
|
||||||
migrateFlag := flag.Bool("migrate", db.Cfg.DB.Postgres.Migrate, "migrate the database")
|
migrateFlag := flag.Bool("migrate", db.Cfg.DB.Postgres.Migrate, "migrate the database")
|
||||||
seedFlag := flag.Bool("seed", db.Cfg.DB.Postgres.Seed, "seed the database")
|
seedFlag := flag.Bool("seed", db.Cfg.DB.Postgres.Seed, "seed the database")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
|
||||||
|
|
@ -343,6 +343,11 @@ const docTemplate = `{
|
||||||
"name": "description",
|
"name": "description",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"name": "isPublish",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"name": "placement",
|
"name": "placement",
|
||||||
|
|
@ -489,6 +494,62 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/advertisement/publish/{id}": {
|
||||||
|
"put": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Update Publish Advertisement",
|
||||||
|
"tags": [
|
||||||
|
"Advertisement"
|
||||||
|
],
|
||||||
|
"summary": "Update Publish Advertisement",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Advertisement ID",
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Advertisement Publish Status",
|
||||||
|
"name": "isPublish",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/advertisement/upload/{id}": {
|
"/advertisement/upload/{id}": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -548,6 +609,55 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/advertisement/viewer/{filename}": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Viewer Advertisement",
|
||||||
|
"tags": [
|
||||||
|
"Advertisement"
|
||||||
|
],
|
||||||
|
"summary": "Viewer Advertisement",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Content File Name",
|
||||||
|
"name": "filename",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/advertisement/{id}": {
|
"/advertisement/{id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -2332,11 +2442,11 @@ const docTemplate = `{
|
||||||
"Bearer": []
|
"Bearer": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "API for create ArticleFiles",
|
"description": "API for Viewer ArticleFiles",
|
||||||
"tags": [
|
"tags": [
|
||||||
"Article Files"
|
"Article Files"
|
||||||
],
|
],
|
||||||
"summary": "Create ArticleFiles",
|
"summary": "Viewer ArticleFiles",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
@ -3148,6 +3258,62 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/articles/banner/{id}": {
|
||||||
|
"put": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Update Banner Articles",
|
||||||
|
"tags": [
|
||||||
|
"Articles"
|
||||||
|
],
|
||||||
|
"summary": "Update Banner Articles",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Articles ID",
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Articles Banner Status",
|
||||||
|
"name": "isBanner",
|
||||||
|
"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/publish-scheduling": {
|
"/articles/publish-scheduling": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -8164,6 +8330,57 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/users/email-validation": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Email Validation Users",
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"summary": "EmailValidation Users",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "Required payload",
|
||||||
|
"name": "payload",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/request.UserEmailValidationRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/users/forgot-password": {
|
"/users/forgot-password": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -8579,6 +8796,57 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/users/setup-email": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Setup Email Users",
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"summary": "SetupEmail Users",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "Required payload",
|
||||||
|
"name": "payload",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/request.UserEmailValidationRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/users/username/{username}": {
|
"/users/username/{username}": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -9568,6 +9836,23 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"request.UserEmailValidationRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"newEmail": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"oldEmail": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"request.UserForgotPassword": {
|
"request.UserForgotPassword": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -9677,6 +9962,9 @@ const docTemplate = `{
|
||||||
},
|
},
|
||||||
"otpCode": {
|
"otpCode": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -332,6 +332,11 @@
|
||||||
"name": "description",
|
"name": "description",
|
||||||
"in": "query"
|
"in": "query"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"name": "isPublish",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"name": "placement",
|
"name": "placement",
|
||||||
|
|
@ -478,6 +483,62 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/advertisement/publish/{id}": {
|
||||||
|
"put": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Update Publish Advertisement",
|
||||||
|
"tags": [
|
||||||
|
"Advertisement"
|
||||||
|
],
|
||||||
|
"summary": "Update Publish Advertisement",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Advertisement ID",
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Advertisement Publish Status",
|
||||||
|
"name": "isPublish",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/advertisement/upload/{id}": {
|
"/advertisement/upload/{id}": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -537,6 +598,55 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/advertisement/viewer/{filename}": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Viewer Advertisement",
|
||||||
|
"tags": [
|
||||||
|
"Advertisement"
|
||||||
|
],
|
||||||
|
"summary": "Viewer Advertisement",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "Content File Name",
|
||||||
|
"name": "filename",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/advertisement/{id}": {
|
"/advertisement/{id}": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -2321,11 +2431,11 @@
|
||||||
"Bearer": []
|
"Bearer": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"description": "API for create ArticleFiles",
|
"description": "API for Viewer ArticleFiles",
|
||||||
"tags": [
|
"tags": [
|
||||||
"Article Files"
|
"Article Files"
|
||||||
],
|
],
|
||||||
"summary": "Create ArticleFiles",
|
"summary": "Viewer ArticleFiles",
|
||||||
"parameters": [
|
"parameters": [
|
||||||
{
|
{
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|
@ -3137,6 +3247,62 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/articles/banner/{id}": {
|
||||||
|
"put": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Update Banner Articles",
|
||||||
|
"tags": [
|
||||||
|
"Articles"
|
||||||
|
],
|
||||||
|
"summary": "Update Banner Articles",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Articles ID",
|
||||||
|
"name": "id",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Articles Banner Status",
|
||||||
|
"name": "isBanner",
|
||||||
|
"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/publish-scheduling": {
|
"/articles/publish-scheduling": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -8153,6 +8319,57 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/users/email-validation": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Email Validation Users",
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"summary": "EmailValidation Users",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "Required payload",
|
||||||
|
"name": "payload",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/request.UserEmailValidationRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/users/forgot-password": {
|
"/users/forgot-password": {
|
||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -8568,6 +8785,57 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/users/setup-email": {
|
||||||
|
"post": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for Setup Email Users",
|
||||||
|
"tags": [
|
||||||
|
"Users"
|
||||||
|
],
|
||||||
|
"summary": "SetupEmail Users",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"description": "Required payload",
|
||||||
|
"name": "payload",
|
||||||
|
"in": "body",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/request.UserEmailValidationRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/users/username/{username}": {
|
"/users/username/{username}": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -9557,6 +9825,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"request.UserEmailValidationRequest": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"newEmail": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"oldEmail": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"password": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"request.UserForgotPassword": {
|
"request.UserForgotPassword": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
|
@ -9666,6 +9951,9 @@
|
||||||
},
|
},
|
||||||
"otpCode": {
|
"otpCode": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"username": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -573,6 +573,17 @@ definitions:
|
||||||
- pathUrl
|
- pathUrl
|
||||||
- statusId
|
- statusId
|
||||||
type: object
|
type: object
|
||||||
|
request.UserEmailValidationRequest:
|
||||||
|
properties:
|
||||||
|
newEmail:
|
||||||
|
type: string
|
||||||
|
oldEmail:
|
||||||
|
type: string
|
||||||
|
password:
|
||||||
|
type: string
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
request.UserForgotPassword:
|
request.UserForgotPassword:
|
||||||
properties:
|
properties:
|
||||||
username:
|
username:
|
||||||
|
|
@ -646,6 +657,8 @@ definitions:
|
||||||
type: string
|
type: string
|
||||||
otpCode:
|
otpCode:
|
||||||
type: string
|
type: string
|
||||||
|
username:
|
||||||
|
type: string
|
||||||
type: object
|
type: object
|
||||||
request.UserResetPassword:
|
request.UserResetPassword:
|
||||||
properties:
|
properties:
|
||||||
|
|
@ -1109,6 +1122,9 @@ paths:
|
||||||
- in: query
|
- in: query
|
||||||
name: description
|
name: description
|
||||||
type: string
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: isPublish
|
||||||
|
type: boolean
|
||||||
- in: query
|
- in: query
|
||||||
name: placement
|
name: placement
|
||||||
type: string
|
type: string
|
||||||
|
|
@ -1301,6 +1317,42 @@ paths:
|
||||||
summary: update Advertisement
|
summary: update Advertisement
|
||||||
tags:
|
tags:
|
||||||
- Advertisement
|
- Advertisement
|
||||||
|
/advertisement/publish/{id}:
|
||||||
|
put:
|
||||||
|
description: API for Update Publish Advertisement
|
||||||
|
parameters:
|
||||||
|
- description: Advertisement ID
|
||||||
|
in: path
|
||||||
|
name: id
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
- description: Advertisement Publish Status
|
||||||
|
in: path
|
||||||
|
name: isPublish
|
||||||
|
required: true
|
||||||
|
type: boolean
|
||||||
|
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: Update Publish Advertisement
|
||||||
|
tags:
|
||||||
|
- Advertisement
|
||||||
/advertisement/upload/{id}:
|
/advertisement/upload/{id}:
|
||||||
post:
|
post:
|
||||||
description: API for Upload File Advertisement
|
description: API for Upload File Advertisement
|
||||||
|
|
@ -1339,6 +1391,37 @@ paths:
|
||||||
summary: Upload Advertisement
|
summary: Upload Advertisement
|
||||||
tags:
|
tags:
|
||||||
- Advertisement
|
- Advertisement
|
||||||
|
/advertisement/viewer/{filename}:
|
||||||
|
get:
|
||||||
|
description: API for Viewer Advertisement
|
||||||
|
parameters:
|
||||||
|
- description: Content File Name
|
||||||
|
in: path
|
||||||
|
name: filename
|
||||||
|
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 Advertisement
|
||||||
|
tags:
|
||||||
|
- Advertisement
|
||||||
/article-approvals:
|
/article-approvals:
|
||||||
get:
|
get:
|
||||||
description: API for getting all ArticleApprovals
|
description: API for getting all ArticleApprovals
|
||||||
|
|
@ -2501,7 +2584,7 @@ paths:
|
||||||
- Article Files
|
- Article Files
|
||||||
/article-files/viewer/{filename}:
|
/article-files/viewer/{filename}:
|
||||||
get:
|
get:
|
||||||
description: API for create ArticleFiles
|
description: API for Viewer ArticleFiles
|
||||||
parameters:
|
parameters:
|
||||||
- description: Article File Name
|
- description: Article File Name
|
||||||
in: path
|
in: path
|
||||||
|
|
@ -2527,7 +2610,7 @@ paths:
|
||||||
$ref: '#/definitions/response.InternalServerError'
|
$ref: '#/definitions/response.InternalServerError'
|
||||||
security:
|
security:
|
||||||
- Bearer: []
|
- Bearer: []
|
||||||
summary: Create ArticleFiles
|
summary: Viewer ArticleFiles
|
||||||
tags:
|
tags:
|
||||||
- Article Files
|
- Article Files
|
||||||
/article-nulis-ai:
|
/article-nulis-ai:
|
||||||
|
|
@ -2978,6 +3061,42 @@ paths:
|
||||||
summary: Update Articles
|
summary: Update Articles
|
||||||
tags:
|
tags:
|
||||||
- Articles
|
- Articles
|
||||||
|
/articles/banner/{id}:
|
||||||
|
put:
|
||||||
|
description: API for Update Banner Articles
|
||||||
|
parameters:
|
||||||
|
- description: Articles ID
|
||||||
|
in: path
|
||||||
|
name: id
|
||||||
|
required: true
|
||||||
|
type: integer
|
||||||
|
- description: Articles Banner Status
|
||||||
|
in: path
|
||||||
|
name: isBanner
|
||||||
|
required: true
|
||||||
|
type: boolean
|
||||||
|
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: Update Banner Articles
|
||||||
|
tags:
|
||||||
|
- Articles
|
||||||
/articles/publish-scheduling:
|
/articles/publish-scheduling:
|
||||||
post:
|
post:
|
||||||
description: API for Publish Schedule of Article
|
description: API for Publish Schedule of Article
|
||||||
|
|
@ -6123,6 +6242,38 @@ paths:
|
||||||
summary: Get one Users
|
summary: Get one Users
|
||||||
tags:
|
tags:
|
||||||
- Users
|
- Users
|
||||||
|
/users/email-validation:
|
||||||
|
post:
|
||||||
|
description: API for Email Validation Users
|
||||||
|
parameters:
|
||||||
|
- description: Required payload
|
||||||
|
in: body
|
||||||
|
name: payload
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/request.UserEmailValidationRequest'
|
||||||
|
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: EmailValidation Users
|
||||||
|
tags:
|
||||||
|
- Users
|
||||||
/users/forgot-password:
|
/users/forgot-password:
|
||||||
post:
|
post:
|
||||||
description: API for ForgotPassword Users
|
description: API for ForgotPassword Users
|
||||||
|
|
@ -6385,6 +6536,38 @@ paths:
|
||||||
summary: SavePassword Users
|
summary: SavePassword Users
|
||||||
tags:
|
tags:
|
||||||
- Users
|
- Users
|
||||||
|
/users/setup-email:
|
||||||
|
post:
|
||||||
|
description: API for Setup Email Users
|
||||||
|
parameters:
|
||||||
|
- description: Required payload
|
||||||
|
in: body
|
||||||
|
name: payload
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/request.UserEmailValidationRequest'
|
||||||
|
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: SetupEmail Users
|
||||||
|
tags:
|
||||||
|
- Users
|
||||||
/users/username/{username}:
|
/users/username/{username}:
|
||||||
get:
|
get:
|
||||||
description: API for getting one Users
|
description: API for getting one Users
|
||||||
|
|
|
||||||
3
main.go
3
main.go
|
|
@ -32,6 +32,7 @@ import (
|
||||||
"go-humas-be/config/logger"
|
"go-humas-be/config/logger"
|
||||||
"go-humas-be/config/webserver"
|
"go-humas-be/config/webserver"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
@ -90,5 +91,7 @@ func main() {
|
||||||
|
|
||||||
// define logger
|
// define logger
|
||||||
fx.WithLogger(fxzerolog.Init()),
|
fx.WithLogger(fxzerolog.Init()),
|
||||||
|
|
||||||
|
fx.StartTimeout(600*time.Second),
|
||||||
).Run()
|
).Run()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,3 +29,14 @@ func GetUserInfo(log zerolog.Logger, repo repository.UsersRepository, bearerToke
|
||||||
|
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetUserId(bearerToken string) *string {
|
||||||
|
tokenString := strings.TrimPrefix(bearerToken, "Bearer ")
|
||||||
|
token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{})
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
claims := token.Claims.(jwt.MapClaims)
|
||||||
|
sub := claims["sub"].(string)
|
||||||
|
return &sub
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue