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"`
|
||||
Placement string `json:"placement" gorm:"type:varchar"`
|
||||
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"`
|
||||
CreatedAt time.Time `json:"created_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"`
|
||||
HasApprovedBy *string `json:"has_approved_by" gorm:"type:varchar"`
|
||||
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"`
|
||||
IsDraft *bool `json:"is_draft" gorm:"type:bool;default:false"`
|
||||
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"
|
||||
|
||||
type RegistrationOtps struct {
|
||||
type OneTimePasswords struct {
|
||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||
Email string `json:"email" 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"`
|
||||
ValidUntil time.Time `json:"valid_until" gorm:"default:(NOW() + INTERVAL '10 minutes')"`
|
||||
IsActive bool `json:"is_active" gorm:"type:bool"`
|
||||
|
|
@ -28,6 +28,7 @@ type Users struct {
|
|||
CreatedById *uint `json:"created_by_id" gorm:"type:int4"`
|
||||
ProfilePicturePath *string `json:"profile_picture_path" 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"`
|
||||
CreatedAt time.Time `json:"created_at" gorm:"default:now()"`
|
||||
UpdatedAt time.Time `json:"updated_at" gorm:"default:now()"`
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ func Models() []interface{} {
|
|||
entity.ArticleFiles{},
|
||||
entity.ArticleComments{},
|
||||
entity.ArticleNulisAI{},
|
||||
entity.AuditTrails{},
|
||||
entity.Cities{},
|
||||
entity.CustomStaticPages{},
|
||||
entity.Districts{},
|
||||
|
|
@ -105,7 +106,7 @@ func Models() []interface{} {
|
|||
entity.MasterStatuses{},
|
||||
entity.MasterApprovalStatuses{},
|
||||
entity.Provinces{},
|
||||
entity.RegistrationOtps{},
|
||||
entity.OneTimePasswords{},
|
||||
entity.UserLevels{},
|
||||
entity.UserRoles{},
|
||||
entity.UserRoleAccesses{},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"go-humas-be/app/database"
|
||||
"go-humas-be/config/config"
|
||||
"go-humas-be/utils"
|
||||
"time"
|
||||
|
|
@ -12,6 +13,8 @@ import (
|
|||
"github.com/gofiber/fiber/v2/middleware/monitor"
|
||||
"github.com/gofiber/fiber/v2/middleware/pprof"
|
||||
"github.com/gofiber/fiber/v2/middleware/recover"
|
||||
|
||||
auditTrails "go-humas-be/config/middleware"
|
||||
)
|
||||
|
||||
// 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
|
||||
func (m *Middleware) Register() {
|
||||
func (m *Middleware) Register(db *database.Database) {
|
||||
// Add Extra Middlewares
|
||||
|
||||
m.App.Use(limiter.New(limiter.Config{
|
||||
|
|
@ -60,6 +63,8 @@ func (m *Middleware) Register() {
|
|||
MaxAge: 12,
|
||||
}))
|
||||
|
||||
m.App.Use(auditTrails.AuditTrailsMiddleware(db.DB))
|
||||
|
||||
//m.App.Use(filesystem.New(filesystem.Config{
|
||||
// Next: utils.IsEnabled(m.Cfg.Middleware.FileSystem.Enable),
|
||||
// Root: http.Dir(m.Cfg.Middleware.FileSystem.Root),
|
||||
|
|
|
|||
|
|
@ -48,7 +48,9 @@ func (_i *AdvertisementRouter) RegisterAdvertisementRoutes() {
|
|||
router.Get("/:id", advertisementController.Show)
|
||||
router.Post("/", advertisementController.Save)
|
||||
router.Post("/upload/:id", advertisementController.Upload)
|
||||
router.Get("/viewer/:filename", advertisementController.Viewer)
|
||||
router.Put("/:id", advertisementController.Update)
|
||||
router.Put("/publish/:id", advertisementController.UpdatePublish)
|
||||
router.Delete("/:id", advertisementController.Delete)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@ type AdvertisementController interface {
|
|||
Save(c *fiber.Ctx) error
|
||||
Upload(c *fiber.Ctx) error
|
||||
Update(c *fiber.Ctx) error
|
||||
UpdatePublish(c *fiber.Ctx) error
|
||||
Delete(c *fiber.Ctx) error
|
||||
Viewer(c *fiber.Ctx) error
|
||||
}
|
||||
|
||||
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
|
||||
// @Summary 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"},
|
||||
})
|
||||
}
|
||||
|
||||
// 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 {
|
||||
GetAll(req request.AdvertisementQueryRequest) (advertisements []*entity.Advertisement, paging paginator.Pagination, 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)
|
||||
Update(id uint, advertisement *entity.Advertisement) (err error)
|
||||
Delete(id uint) (err error)
|
||||
|
|
@ -88,6 +89,15 @@ func (_i *advertisementRepository) FindOne(id uint) (advertisement *entity.Adver
|
|||
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) {
|
||||
result := _i.DB.DB.Create(advertisement)
|
||||
return advertisement, result.Error
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ type AdvertisementQueryRequest struct {
|
|||
Description *string `json:"description"`
|
||||
RedirectLink *string `json:"redirectLink"`
|
||||
Placement *string `json:"placement"`
|
||||
IsPublish *bool `json:"isPublish"`
|
||||
StatusId *int `json:"statusId"`
|
||||
Pagination *paginator.Pagination `json:"pagination"`
|
||||
}
|
||||
|
|
@ -34,6 +35,8 @@ func (req AdvertisementCreateRequest) ToEntity() *entity.Advertisement {
|
|||
RedirectLink: req.RedirectLink,
|
||||
Placement: req.Placement,
|
||||
StatusId: 1,
|
||||
IsPublish: true,
|
||||
IsActive: true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,6 +65,7 @@ type AdvertisementQueryRequestContext struct {
|
|||
RedirectLink string `json:"redirectLink"`
|
||||
Placement string `json:"placement"`
|
||||
StatusId string `json:"statusId"`
|
||||
IsPublish string `json:"isPublish"`
|
||||
}
|
||||
|
||||
func (req AdvertisementQueryRequestContext) ToParamRequest() AdvertisementQueryRequest {
|
||||
|
|
@ -79,6 +83,12 @@ func (req AdvertisementQueryRequestContext) ToParamRequest() AdvertisementQueryR
|
|||
if placement := req.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 != "" {
|
||||
statusId, err := strconv.Atoi(statusIdStr)
|
||||
if err == nil {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,10 @@ import (
|
|||
usersRepository "go-humas-be/app/module/users/repository"
|
||||
minioStorage "go-humas-be/config/config"
|
||||
"go-humas-be/utils/paginator"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"mime"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
|
@ -36,7 +39,9 @@ type AdvertisementService interface {
|
|||
Save(req request.AdvertisementCreateRequest) (advertisement *entity.Advertisement, err error)
|
||||
Upload(c *fiber.Ctx, id uint) (err error)
|
||||
Update(id uint, req request.AdvertisementUpdateRequest) (err error)
|
||||
UpdatePublish(id uint, isPublish bool) (err error)
|
||||
Delete(id uint) error
|
||||
Viewer(c *fiber.Ctx) (err error)
|
||||
}
|
||||
|
||||
// NewAdvertisementService init AdvertisementService
|
||||
|
|
@ -165,6 +170,17 @@ func (_i *advertisementService) Update(id uint, req request.AdvertisementUpdateR
|
|||
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 {
|
||||
result, err := _i.Repo.FindOne(id)
|
||||
if err != nil {
|
||||
|
|
@ -174,3 +190,58 @@ func (_i *advertisementService) Delete(id uint) error {
|
|||
result.IsActive = false
|
||||
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
|
||||
// @Summary Create ArticleFiles
|
||||
// @Description API for create ArticleFiles
|
||||
// @Summary Viewer ArticleFiles
|
||||
// @Description API for Viewer ArticleFiles
|
||||
// @Tags Article Files
|
||||
// @Security Bearer
|
||||
// @Param filename path string true "Article File Name"
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ func (_i *ArticlesRouter) RegisterArticlesRoutes() {
|
|||
router.Get("/:id", articlesController.Show)
|
||||
router.Post("/", articlesController.Save)
|
||||
router.Put("/:id", articlesController.Update)
|
||||
router.Put("/banner/:id", articlesController.UpdateBanner)
|
||||
router.Post("/thumbnail/:id", articlesController.SaveThumbnail)
|
||||
router.Get("/thumbnail/viewer/:thumbnailName", articlesController.Viewer)
|
||||
router.Post("/publish-scheduling", articlesController.PublishScheduling)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ type ArticlesController interface {
|
|||
Save(c *fiber.Ctx) error
|
||||
SaveThumbnail(c *fiber.Ctx) error
|
||||
Update(c *fiber.Ctx) error
|
||||
UpdateBanner(c *fiber.Ctx) error
|
||||
Delete(c *fiber.Ctx) error
|
||||
Viewer(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
|
||||
// @Summary Delete Articles
|
||||
// @Description API for delete Articles
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ type ArticlesService interface {
|
|||
Delete(id uint) error
|
||||
UpdateActivityCount(id uint, activityTypeId 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
|
||||
SummaryStats(authToken string) (summaryStats *response.ArticleSummaryStats, 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
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,8 @@ type UsersController interface {
|
|||
ForgotPassword(c *fiber.Ctx) error
|
||||
OtpRequest(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 {
|
||||
|
|
@ -469,3 +471,59 @@ func (_i *usersController) OtpValidation(c *fiber.Ctx) error {
|
|||
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)
|
||||
UpdateForgotPassword(id uint, forgotPasswords *entity.ForgotPasswords) (err error)
|
||||
FindForgotPassword(keycloakId string, code string) (forgotPasswords *entity.ForgotPasswords, err error)
|
||||
CreateRegistrationOtps(registrationOtps *entity.RegistrationOtps) (err error)
|
||||
FindRegistrationOtps(email string, code string) (registrationOtps *entity.RegistrationOtps, err error)
|
||||
CreateOtp(otp *entity.OneTimePasswords) (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 {
|
||||
|
|
@ -168,15 +169,23 @@ func (_i *usersRepository) FindForgotPassword(keycloakId string, code string) (f
|
|||
return forgotPasswords, nil
|
||||
}
|
||||
|
||||
func (_i *usersRepository) CreateRegistrationOtps(registrationOtps *entity.RegistrationOtps) (err error) {
|
||||
result := _i.DB.DB.Create(registrationOtps)
|
||||
func (_i *usersRepository) CreateOtp(otp *entity.OneTimePasswords) (err error) {
|
||||
result := _i.DB.DB.Create(otp)
|
||||
return result.Error
|
||||
}
|
||||
|
||||
func (_i *usersRepository) FindRegistrationOtps(email string, code string) (registrationOtps *entity.RegistrationOtps, err error) {
|
||||
if err := _i.DB.DB.Where("email = ?", email).Where("otp_code = ?", code).First(®istrationOtps).Error; err != nil {
|
||||
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(&otp).Error; err != nil {
|
||||
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"`
|
||||
}
|
||||
|
||||
type UserEmailValidationRequest struct {
|
||||
Username *string `json:"username"`
|
||||
Password *string `json:"password"`
|
||||
OldEmail *string `json:"oldEmail"`
|
||||
NewEmail *string `json:"newEmail"`
|
||||
}
|
||||
|
||||
type UserOtpRequest struct {
|
||||
Email string `json:"email" validate:"required,email"`
|
||||
Name *string `json:"name"`
|
||||
}
|
||||
|
||||
type UserOtpValidation struct {
|
||||
Email string `json:"email"`
|
||||
Email *string `json:"email"`
|
||||
Username *string `json:"username"`
|
||||
OtpCode string `json:"otpCode"`
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,8 +44,12 @@ type UsersService interface {
|
|||
SavePassword(req request.UserSavePassword, authToken string) (err error)
|
||||
ResetPassword(req request.UserResetPassword) (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)
|
||||
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
|
||||
|
|
@ -343,47 +347,50 @@ func (_i *usersService) OtpRequest(req request.UserOtpRequest) (err error) {
|
|||
_i.Log.Info().Interface("data", req).Msg("")
|
||||
|
||||
codeRequest, err := utilSvc.GenerateNumericCode(6)
|
||||
if req.Name == nil {
|
||||
req.Name = &req.Email
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
otpReq := entity.RegistrationOtps{
|
||||
otpReq := entity.OneTimePasswords{
|
||||
Email: req.Email,
|
||||
Name: req.Name,
|
||||
OtpCode: codeRequest,
|
||||
IsActive: true,
|
||||
}
|
||||
|
||||
subject := "[HUMAS POLRI] Permintaan OTP"
|
||||
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)
|
||||
|
||||
err = _i.Repo.CreateOtp(&otpReq)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = _i.Repo.CreateRegistrationOtps(&otpReq)
|
||||
err = _i.SendRegistrationOtp(*req.Name, req.Email, codeRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// send otp to email
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (_i *usersService) OtpValidation(req request.UserOtpValidation) (err error) {
|
||||
_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 {
|
||||
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 registrationOtp.ValidUntil.Before(time.Now()) {
|
||||
if otp != nil {
|
||||
if otp.ValidUntil.Before(time.Now()) {
|
||||
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) {
|
||||
// Pisahkan JWT menjadi 3 bagian: header, payload, dan signature
|
||||
parts := strings.Split(token, ".")
|
||||
|
|
@ -414,3 +523,25 @@ func ParseJWTToken(token string) (map[string]interface{}, error) {
|
|||
|
||||
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("/otp-request", usersController.OtpRequest)
|
||||
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
|
||||
Expiration time.Duration `toml:"expiration_seconds"`
|
||||
}
|
||||
|
||||
AuditTrails struct {
|
||||
Enable bool
|
||||
}
|
||||
}
|
||||
|
||||
// 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]
|
||||
dsn = "postgresql://humas_user:HumasDB@2024@38.47.180.165:5432/humas_db" # <driver>://<username>:<password>@<host>:<port>/<database>
|
||||
log-mode = "NONE"
|
||||
migrate = true
|
||||
migrate = false
|
||||
seed = false
|
||||
|
||||
[logger]
|
||||
|
|
@ -39,7 +39,7 @@ level = 1
|
|||
enable = true
|
||||
|
||||
[middleware.monitor]
|
||||
enable = false
|
||||
enable = true
|
||||
path = "/monitor"
|
||||
|
||||
[middleware.pprof]
|
||||
|
|
@ -49,10 +49,13 @@ enable = true
|
|||
enable = true
|
||||
|
||||
[middleware.limiter]
|
||||
enable = false
|
||||
enable = true
|
||||
max = 20
|
||||
expiration_seconds = 60
|
||||
|
||||
[middleware.audittrails]
|
||||
enable = true
|
||||
|
||||
[keycloak]
|
||||
endpoint = "http://38.47.180.165:8008"
|
||||
realm = "humas"
|
||||
|
|
|
|||
|
|
@ -48,8 +48,14 @@ func Start(lifecycle fx.Lifecycle, cfg *config.Config, fiber *fiber.App, router
|
|||
lifecycle.Append(
|
||||
fx.Hook{
|
||||
OnStart: func(ctx context.Context) error {
|
||||
// Register middlewares & routes
|
||||
middlewares.Register()
|
||||
|
||||
// Connect database
|
||||
db.ConnectDatabase()
|
||||
|
||||
// Register middlewares
|
||||
middlewares.Register(db)
|
||||
|
||||
// Register routes
|
||||
router.Register()
|
||||
|
||||
// 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")
|
||||
seedFlag := flag.Bool("seed", db.Cfg.DB.Postgres.Seed, "seed the database")
|
||||
flag.Parse()
|
||||
|
|
|
|||
|
|
@ -343,6 +343,11 @@ const docTemplate = `{
|
|||
"name": "description",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"name": "isPublish",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"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}": {
|
||||
"post": {
|
||||
"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}": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
|
@ -2332,11 +2442,11 @@ const docTemplate = `{
|
|||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "API for create ArticleFiles",
|
||||
"description": "API for Viewer ArticleFiles",
|
||||
"tags": [
|
||||
"Article Files"
|
||||
],
|
||||
"summary": "Create ArticleFiles",
|
||||
"summary": "Viewer ArticleFiles",
|
||||
"parameters": [
|
||||
{
|
||||
"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": {
|
||||
"post": {
|
||||
"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": {
|
||||
"post": {
|
||||
"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}": {
|
||||
"get": {
|
||||
"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": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -9677,6 +9962,9 @@ const docTemplate = `{
|
|||
},
|
||||
"otpCode": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -332,6 +332,11 @@
|
|||
"name": "description",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"name": "isPublish",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"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}": {
|
||||
"post": {
|
||||
"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}": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
|
@ -2321,11 +2431,11 @@
|
|||
"Bearer": []
|
||||
}
|
||||
],
|
||||
"description": "API for create ArticleFiles",
|
||||
"description": "API for Viewer ArticleFiles",
|
||||
"tags": [
|
||||
"Article Files"
|
||||
],
|
||||
"summary": "Create ArticleFiles",
|
||||
"summary": "Viewer ArticleFiles",
|
||||
"parameters": [
|
||||
{
|
||||
"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": {
|
||||
"post": {
|
||||
"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": {
|
||||
"post": {
|
||||
"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}": {
|
||||
"get": {
|
||||
"security": [
|
||||
|
|
@ -9557,6 +9825,23 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"request.UserEmailValidationRequest": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"newEmail": {
|
||||
"type": "string"
|
||||
},
|
||||
"oldEmail": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request.UserForgotPassword": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -9666,6 +9951,9 @@
|
|||
},
|
||||
"otpCode": {
|
||||
"type": "string"
|
||||
},
|
||||
"username": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -573,6 +573,17 @@ definitions:
|
|||
- pathUrl
|
||||
- statusId
|
||||
type: object
|
||||
request.UserEmailValidationRequest:
|
||||
properties:
|
||||
newEmail:
|
||||
type: string
|
||||
oldEmail:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
request.UserForgotPassword:
|
||||
properties:
|
||||
username:
|
||||
|
|
@ -646,6 +657,8 @@ definitions:
|
|||
type: string
|
||||
otpCode:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
request.UserResetPassword:
|
||||
properties:
|
||||
|
|
@ -1109,6 +1122,9 @@ paths:
|
|||
- in: query
|
||||
name: description
|
||||
type: string
|
||||
- in: query
|
||||
name: isPublish
|
||||
type: boolean
|
||||
- in: query
|
||||
name: placement
|
||||
type: string
|
||||
|
|
@ -1301,6 +1317,42 @@ paths:
|
|||
summary: update Advertisement
|
||||
tags:
|
||||
- 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}:
|
||||
post:
|
||||
description: API for Upload File Advertisement
|
||||
|
|
@ -1339,6 +1391,37 @@ paths:
|
|||
summary: Upload Advertisement
|
||||
tags:
|
||||
- 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:
|
||||
get:
|
||||
description: API for getting all ArticleApprovals
|
||||
|
|
@ -2501,7 +2584,7 @@ paths:
|
|||
- Article Files
|
||||
/article-files/viewer/{filename}:
|
||||
get:
|
||||
description: API for create ArticleFiles
|
||||
description: API for Viewer ArticleFiles
|
||||
parameters:
|
||||
- description: Article File Name
|
||||
in: path
|
||||
|
|
@ -2527,7 +2610,7 @@ paths:
|
|||
$ref: '#/definitions/response.InternalServerError'
|
||||
security:
|
||||
- Bearer: []
|
||||
summary: Create ArticleFiles
|
||||
summary: Viewer ArticleFiles
|
||||
tags:
|
||||
- Article Files
|
||||
/article-nulis-ai:
|
||||
|
|
@ -2978,6 +3061,42 @@ paths:
|
|||
summary: Update Articles
|
||||
tags:
|
||||
- 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:
|
||||
post:
|
||||
description: API for Publish Schedule of Article
|
||||
|
|
@ -6123,6 +6242,38 @@ paths:
|
|||
summary: Get one Users
|
||||
tags:
|
||||
- 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:
|
||||
post:
|
||||
description: API for ForgotPassword Users
|
||||
|
|
@ -6385,6 +6536,38 @@ paths:
|
|||
summary: SavePassword Users
|
||||
tags:
|
||||
- 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}:
|
||||
get:
|
||||
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/webserver"
|
||||
"go.uber.org/fx"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
@ -90,5 +91,7 @@ func main() {
|
|||
|
||||
// define logger
|
||||
fx.WithLogger(fxzerolog.Init()),
|
||||
|
||||
fx.StartTimeout(600*time.Second),
|
||||
).Run()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,3 +29,14 @@ func GetUserInfo(log zerolog.Logger, repo repository.UsersRepository, bearerToke
|
|||
|
||||
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