feat: add article stats
This commit is contained in:
parent
4fb34ef46c
commit
6b8ab00e3b
|
|
@ -16,9 +16,9 @@ type Articles struct {
|
||||||
PageUrl *string `json:"page_url" gorm:"type:varchar"`
|
PageUrl *string `json:"page_url" gorm:"type:varchar"`
|
||||||
CreatedById *uint `json:"created_by_id" gorm:"type:int4"`
|
CreatedById *uint `json:"created_by_id" gorm:"type:int4"`
|
||||||
AiArticleId *int `json:"ai_article_id" gorm:"type:int4"`
|
AiArticleId *int `json:"ai_article_id" gorm:"type:int4"`
|
||||||
CommentCount *int `json:"comment_count" gorm:"type:int4"`
|
CommentCount *int `json:"comment_count" gorm:"type:int4;default:0"`
|
||||||
ShareCount *int `json:"share_count" gorm:"type:int4"`
|
ShareCount *int `json:"share_count" gorm:"type:int4;default:0"`
|
||||||
ViewCount *int `json:"view_count" gorm:"type:int4"`
|
ViewCount *int `json:"view_count" gorm:"type:int4;default:0"`
|
||||||
StatusId *int `json:"status_id" gorm:"type:int4"`
|
StatusId *int `json:"status_id" gorm:"type:int4"`
|
||||||
OldId *uint `json:"old_id" gorm:"type:int4"`
|
OldId *uint `json:"old_id" gorm:"type:int4"`
|
||||||
IsPublish *bool `json:"is_publish" gorm:"type:bool;default:false"`
|
IsPublish *bool `json:"is_publish" gorm:"type:bool;default:false"`
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
package entity
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
type Users struct {
|
|
||||||
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
|
||||||
Username string `json:"username" gorm:"type:varchar"`
|
|
||||||
Email string `json:"email" gorm:"type:varchar"`
|
|
||||||
Fullname string `json:"fullname" gorm:"type:varchar"`
|
|
||||||
Address *string `json:"address" gorm:"type:varchar"`
|
|
||||||
PhoneNumber *string `json:"phone_number" gorm:"type:varchar"`
|
|
||||||
WorkType *string `json:"work_type" gorm:"type:varchar"`
|
|
||||||
GenderType *string `json:"gender_type" gorm:"type:varchar"`
|
|
||||||
IdentityType *string `json:"identity_type" gorm:"type:varchar"`
|
|
||||||
IdentityGroup *string `json:"identity_group" gorm:"type:varchar"`
|
|
||||||
IdentityGroupNumber *string `json:"identity_group_number" gorm:"type:varchar"`
|
|
||||||
IdentityNumber *string `json:"identity_number" gorm:"type:varchar"`
|
|
||||||
DateOfBirth *string `json:"date_of_birth" gorm:"type:varchar"`
|
|
||||||
LastEducation *string `json:"last_education" gorm:"type:varchar"`
|
|
||||||
UserRoleId uint `json:"user_role_id" gorm:"type:int4"`
|
|
||||||
UserLevelId uint `json:"user_level_id" gorm:"type:int4"`
|
|
||||||
KeycloakId *string `json:"keycloak_id" gorm:"type:varchar"`
|
|
||||||
StatusId *int `json:"status_id" gorm:"type:int4;default:1"`
|
|
||||||
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"`
|
|
||||||
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()"`
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package users
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go-humas-be/app/database/entity"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Users struct {
|
||||||
|
ID uint `json:"id" gorm:"primaryKey;type:int4;autoIncrement"`
|
||||||
|
Username string `json:"username" gorm:"type:varchar"`
|
||||||
|
Email string `json:"email" gorm:"type:varchar"`
|
||||||
|
Fullname string `json:"fullname" gorm:"type:varchar"`
|
||||||
|
Address *string `json:"address" gorm:"type:varchar"`
|
||||||
|
PhoneNumber *string `json:"phone_number" gorm:"type:varchar"`
|
||||||
|
WorkType *string `json:"work_type" gorm:"type:varchar"`
|
||||||
|
GenderType *string `json:"gender_type" gorm:"type:varchar"`
|
||||||
|
IdentityType *string `json:"identity_type" gorm:"type:varchar"`
|
||||||
|
IdentityGroup *string `json:"identity_group" gorm:"type:varchar"`
|
||||||
|
IdentityGroupNumber *string `json:"identity_group_number" gorm:"type:varchar"`
|
||||||
|
IdentityNumber *string `json:"identity_number" gorm:"type:varchar"`
|
||||||
|
DateOfBirth *string `json:"date_of_birth" gorm:"type:varchar"`
|
||||||
|
LastEducation *string `json:"last_education" gorm:"type:varchar"`
|
||||||
|
UserRoleId uint `json:"user_role_id" gorm:"type:int4"`
|
||||||
|
UserLevelId uint `json:"user_level_id" gorm:"type:int4"`
|
||||||
|
UserLevel *entity.UserLevels `json:"user_levels" gorm:"foreignKey:UserLevelId;references:ID"`
|
||||||
|
KeycloakId *string `json:"keycloak_id" gorm:"type:varchar"`
|
||||||
|
StatusId *int `json:"status_id" gorm:"type:int4;default:1"`
|
||||||
|
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"`
|
||||||
|
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()"`
|
||||||
|
}
|
||||||
|
|
@ -4,9 +4,11 @@ import (
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go-humas-be/app/database/entity"
|
"go-humas-be/app/database/entity"
|
||||||
"go-humas-be/app/database/entity/article_category_details"
|
"go-humas-be/app/database/entity/article_category_details"
|
||||||
|
"go-humas-be/app/database/entity/users"
|
||||||
"go-humas-be/config/config"
|
"go-humas-be/config/config"
|
||||||
"gorm.io/driver/postgres"
|
"gorm.io/driver/postgres"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
"gorm.io/gorm/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Database setup database with gorm
|
// Database setup database with gorm
|
||||||
|
|
@ -32,7 +34,20 @@ func NewDatabase(cfg *config.Config, log zerolog.Logger) *Database {
|
||||||
|
|
||||||
// ConnectDatabase connect database
|
// ConnectDatabase connect database
|
||||||
func (_db *Database) ConnectDatabase() {
|
func (_db *Database) ConnectDatabase() {
|
||||||
conn, err := gorm.Open(postgres.Open(_db.Cfg.DB.Postgres.DSN), &gorm.Config{})
|
logMode := _db.Cfg.DB.Postgres.LogMode
|
||||||
|
var logLevel logger.LogLevel
|
||||||
|
if logMode == "INFO" {
|
||||||
|
logLevel = logger.Info
|
||||||
|
} else if logMode == "WARN" {
|
||||||
|
logLevel = logger.Warn
|
||||||
|
} else if logMode == "ERROR" {
|
||||||
|
logLevel = logger.Error
|
||||||
|
} else if logMode == "NONE" {
|
||||||
|
logLevel = logger.Silent
|
||||||
|
}
|
||||||
|
conn, err := gorm.Open(postgres.Open(_db.Cfg.DB.Postgres.DSN), &gorm.Config{
|
||||||
|
Logger: logger.Default.LogMode(logLevel),
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_db.Log.Error().Err(err).Msg("An unknown error occurred when to connect the database!")
|
_db.Log.Error().Err(err).Msg("An unknown error occurred when to connect the database!")
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -91,7 +106,7 @@ func Models() []interface{} {
|
||||||
entity.UserLevels{},
|
entity.UserLevels{},
|
||||||
entity.UserRoles{},
|
entity.UserRoles{},
|
||||||
entity.UserRoleAccesses{},
|
entity.UserRoleAccesses{},
|
||||||
entity.Users{},
|
users.Users{},
|
||||||
entity.UserRoleLevelDetails{},
|
entity.UserRoleLevelDetails{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,5 +52,7 @@ func (_i *ArticlesRouter) RegisterArticlesRoutes() {
|
||||||
router.Get("/thumbnail/viewer/:thumbnailName", articlesController.Viewer)
|
router.Get("/thumbnail/viewer/:thumbnailName", articlesController.Viewer)
|
||||||
router.Delete("/:id", articlesController.Delete)
|
router.Delete("/:id", articlesController.Delete)
|
||||||
router.Get("/statistic/summary", articlesController.SummaryStats)
|
router.Get("/statistic/summary", articlesController.SummaryStats)
|
||||||
|
router.Get("/statistic/user-levels", articlesController.ArticlePerUserLevelStats)
|
||||||
|
router.Get("/statistic/monthly", articlesController.ArticleMonthlyStats)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,8 @@ type ArticlesController interface {
|
||||||
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
|
||||||
|
ArticlePerUserLevelStats(c *fiber.Ctx) error
|
||||||
|
ArticleMonthlyStats(c *fiber.Ctx) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewArticlesController(articlesService service.ArticlesService) ArticlesController {
|
func NewArticlesController(articlesService service.ArticlesService) ArticlesController {
|
||||||
|
|
@ -264,3 +266,65 @@ func (_i *articlesController) SummaryStats(c *fiber.Ctx) error {
|
||||||
Data: response,
|
Data: response,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ArticlePerUserLevelStats Articles
|
||||||
|
// @Summary ArticlePerUserLevelStats Articles
|
||||||
|
// @Description API for ArticlePerUserLevelStats of Article
|
||||||
|
// @Tags Articles
|
||||||
|
// @Security Bearer
|
||||||
|
// @Param Authorization header string true "Insert your access token" default(Bearer <Add access token here>)
|
||||||
|
// @Param startDate query string false "start date"
|
||||||
|
// @Param endDate query string false "start date"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 400 {object} response.BadRequestError
|
||||||
|
// @Failure 401 {object} response.UnauthorizedError
|
||||||
|
// @Failure 500 {object} response.InternalServerError
|
||||||
|
// @Router /articles/statistic/user-levels [get]
|
||||||
|
func (_i *articlesController) ArticlePerUserLevelStats(c *fiber.Ctx) error {
|
||||||
|
authToken := c.Get("Authorization")
|
||||||
|
startDate := c.Query("startDate")
|
||||||
|
endDate := c.Query("endDate")
|
||||||
|
|
||||||
|
response, err := _i.articlesService.ArticlePerUserLevelStats(authToken, &startDate, &endDate)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return utilRes.Resp(c, utilRes.Response{
|
||||||
|
Success: true,
|
||||||
|
Messages: utilRes.Messages{"ArticlePerUserLevelStats of Articles successfully retrieved"},
|
||||||
|
Data: response,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArticleMonthlyStats Articles
|
||||||
|
// @Summary ArticleMonthlyStats Articles
|
||||||
|
// @Description API for ArticleMonthlyStats of Article
|
||||||
|
// @Tags Articles
|
||||||
|
// @Security Bearer
|
||||||
|
// @Param Authorization header string true "Insert your access token" default(Bearer <Add access token here>)
|
||||||
|
// @Param year query int false "year"
|
||||||
|
// @Success 200 {object} response.Response
|
||||||
|
// @Failure 400 {object} response.BadRequestError
|
||||||
|
// @Failure 401 {object} response.UnauthorizedError
|
||||||
|
// @Failure 500 {object} response.InternalServerError
|
||||||
|
// @Router /articles/statistic/monthly [get]
|
||||||
|
func (_i *articlesController) ArticleMonthlyStats(c *fiber.Ctx) error {
|
||||||
|
authToken := c.Get("Authorization")
|
||||||
|
year := c.Query("year")
|
||||||
|
yearInt, err := strconv.Atoi(year)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := _i.articlesService.ArticleMonthlyStats(authToken, &yearInt)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return utilRes.Resp(c, utilRes.Response{
|
||||||
|
Success: true,
|
||||||
|
Messages: utilRes.Messages{"ArticleMonthlyStats of Articles successfully retrieved"},
|
||||||
|
Data: response,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ type ArticlesRepository interface {
|
||||||
Update(id uint, articles *entity.Articles) (err error)
|
Update(id uint, articles *entity.Articles) (err error)
|
||||||
Delete(id uint) (err error)
|
Delete(id uint) (err error)
|
||||||
SummaryStats(userID uint) (articleSummaryStats *response.ArticleSummaryStats, err error)
|
SummaryStats(userID uint) (articleSummaryStats *response.ArticleSummaryStats, err error)
|
||||||
|
ArticlePerUserLevelStats(userLevelId *uint, levelNumber *int, startDate *time.Time, endDate *time.Time) (articlePerUserLevelStats []*response.ArticlePerUserLevelStats, err error)
|
||||||
|
ArticleMonthlyStats(userLevelId *uint, levelNumber *int, year int) (articleMontlyStats []*response.ArticleMonthlyStats, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewArticlesRepository(db *database.Database, log zerolog.Logger) ArticlesRepository {
|
func NewArticlesRepository(db *database.Database, log zerolog.Logger) ArticlesRepository {
|
||||||
|
|
@ -153,3 +155,134 @@ func (_i *articlesRepository) SummaryStats(userID uint) (articleSummaryStats *re
|
||||||
|
|
||||||
return articleSummaryStats, err
|
return articleSummaryStats, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_i *articlesRepository) ArticlePerUserLevelStats(userLevelId *uint, levelNumber *int, startDate *time.Time, endDate *time.Time) (articlePerUserLevelStats []*response.ArticlePerUserLevelStats, err error) {
|
||||||
|
|
||||||
|
levelNumberTop := 1
|
||||||
|
|
||||||
|
query := _i.DB.DB.Model(&entity.Articles{}).
|
||||||
|
Select("user_levels.id as user_level_id", "user_levels.name as user_level_name", "COUNT(articles.id) as total_article").
|
||||||
|
Joins("LEFT JOIN users ON articles.created_by_id = users.id").
|
||||||
|
Joins("LEFT JOIN user_levels ON users.user_level_id = user_levels.id").
|
||||||
|
Where("articles.is_active = true")
|
||||||
|
|
||||||
|
if userLevelId != nil && *levelNumber != levelNumberTop {
|
||||||
|
query = query.Where("user_levels.id = ? or user_levels.parent_level_id = ?", *userLevelId, *userLevelId)
|
||||||
|
} else {
|
||||||
|
query = _i.DB.DB.Raw(`
|
||||||
|
WITH LevelHierarchy AS (
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
level_number,
|
||||||
|
parent_level_id,
|
||||||
|
CASE
|
||||||
|
WHEN level_number = 2 THEN id
|
||||||
|
WHEN level_number = 3 THEN parent_level_id
|
||||||
|
END AS level_2_id,
|
||||||
|
CASE
|
||||||
|
WHEN level_number = 2 THEN name
|
||||||
|
WHEN level_number = 3 THEN (SELECT name FROM user_levels ul2 WHERE ul2.id = user_levels.parent_level_id)
|
||||||
|
END AS level_2_name
|
||||||
|
FROM user_levels
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
lh.level_2_id AS user_level_id,
|
||||||
|
lh.level_2_name AS user_level_name,
|
||||||
|
COUNT(articles.id) AS total_article
|
||||||
|
FROM articles
|
||||||
|
JOIN users ON articles.created_by_id = users.id
|
||||||
|
JOIN LevelHierarchy lh ON users.user_level_id = lh.id
|
||||||
|
WHERE articles.is_active = true AND lh.level_2_id > 0
|
||||||
|
GROUP BY
|
||||||
|
lh.level_2_id,
|
||||||
|
lh.level_2_name
|
||||||
|
ORDER BY
|
||||||
|
total_article DESC`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply date filters if provided
|
||||||
|
if startDate != nil {
|
||||||
|
query = query.Where("articles.created_at >= ?", *startDate)
|
||||||
|
}
|
||||||
|
if endDate != nil {
|
||||||
|
query = query.Where("articles.created_at <= ?", *endDate)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Group by all non-aggregated columns
|
||||||
|
err = query.Group("user_levels.id, user_levels.name").
|
||||||
|
Order("total_article DESC").
|
||||||
|
Scan(&articlePerUserLevelStats).Error
|
||||||
|
|
||||||
|
return articlePerUserLevelStats, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_i *articlesRepository) ArticleMonthlyStats(userLevelId *uint, levelNumber *int, year int) (articleMontlyStats []*response.ArticleMonthlyStats, err error) {
|
||||||
|
levelNumberTop := 1
|
||||||
|
|
||||||
|
if year < 1900 || year > 2100 {
|
||||||
|
return nil, fmt.Errorf("invalid year")
|
||||||
|
}
|
||||||
|
|
||||||
|
var results []struct {
|
||||||
|
Month int
|
||||||
|
Day int
|
||||||
|
TotalView int
|
||||||
|
TotalComment int
|
||||||
|
TotalShare int
|
||||||
|
}
|
||||||
|
|
||||||
|
query := _i.DB.DB.Model(&entity.Articles{}).
|
||||||
|
Select("EXTRACT(MONTH FROM created_at) as month, EXTRACT(DAY FROM created_at) as day, "+
|
||||||
|
"SUM(view_count) as total_view, "+
|
||||||
|
"SUM(comment_count) as total_comment, "+
|
||||||
|
"SUM(share_count) as total_share").
|
||||||
|
Where("EXTRACT(YEAR FROM created_at) = ?", year)
|
||||||
|
|
||||||
|
if userLevelId != nil && *levelNumber != levelNumberTop {
|
||||||
|
query = _i.DB.DB.Model(&entity.Articles{}).
|
||||||
|
Select("EXTRACT(MONTH FROM articles.created_at) as month, EXTRACT(DAY FROM articles.created_at) as day, "+
|
||||||
|
"SUM(articles.view_count) as total_view, "+
|
||||||
|
"SUM(articles.comment_count) as total_comment, "+
|
||||||
|
"SUM(articles.share_count) as total_share").
|
||||||
|
Joins("LEFT JOIN users ON articles.created_by_id = users.id").
|
||||||
|
Joins("LEFT JOIN user_levels ON users.user_level_id = user_levels.id").
|
||||||
|
Where("articles.is_active = true").
|
||||||
|
Where("EXTRACT(YEAR FROM articles.created_at) = ?", year).
|
||||||
|
Where("(user_levels.id = ? OR user_levels.parent_level_id = ?)", *userLevelId, *userLevelId)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = query.Group("month, day").Scan(&results).Error
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Siapkan struktur untuk menyimpan data bulanan
|
||||||
|
monthlyAnalytics := make([]*response.ArticleMonthlyStats, 12)
|
||||||
|
for i := 0; i < 12; i++ {
|
||||||
|
daysInMonth := time.Date(year, time.Month(i+1), 0, 0, 0, 0, 0, time.UTC).Day()
|
||||||
|
monthlyAnalytics[i] = &response.ArticleMonthlyStats{
|
||||||
|
Year: year,
|
||||||
|
Month: i + 1,
|
||||||
|
View: make([]int, daysInMonth),
|
||||||
|
Comment: make([]int, daysInMonth),
|
||||||
|
Share: make([]int, daysInMonth),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Isi data dari hasil agregasi
|
||||||
|
for _, result := range results {
|
||||||
|
monthIndex := result.Month - 1
|
||||||
|
dayIndex := result.Day - 1
|
||||||
|
|
||||||
|
if monthIndex >= 0 && monthIndex < 12 {
|
||||||
|
if dayIndex >= 0 && dayIndex < len(monthlyAnalytics[monthIndex].View) {
|
||||||
|
monthlyAnalytics[monthIndex].View[dayIndex] = result.TotalView
|
||||||
|
monthlyAnalytics[monthIndex].Comment[dayIndex] = result.TotalComment
|
||||||
|
monthlyAnalytics[monthIndex].Share[dayIndex] = result.TotalShare
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return monthlyAnalytics, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,3 +43,17 @@ type ArticleSummaryStats struct {
|
||||||
TotalShares int `json:"totalShares"`
|
TotalShares int `json:"totalShares"`
|
||||||
TotalComments int `json:"totalComments"`
|
TotalComments int `json:"totalComments"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ArticlePerUserLevelStats struct {
|
||||||
|
UserLevelID uint `json:"userLevelId"`
|
||||||
|
UserLevelName string `json:"userLevelName"`
|
||||||
|
TotalArticle int64 `json:"totalArticle"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ArticleMonthlyStats struct {
|
||||||
|
Year int `json:"year"`
|
||||||
|
Month int `json:"month"`
|
||||||
|
View []int `json:"view"`
|
||||||
|
Comment []int `json:"comment"`
|
||||||
|
Share []int `json:"share"`
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ type ArticlesService interface {
|
||||||
UpdateActivityCount(id uint, activityTypeId int) (err error)
|
UpdateActivityCount(id uint, activityTypeId int) (err 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)
|
||||||
|
ArticleMonthlyStats(authToken string, year *int) (articleMonthlyStats []*response.ArticleMonthlyStats, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewArticlesService init ArticlesService
|
// NewArticlesService init ArticlesService
|
||||||
|
|
@ -400,6 +402,56 @@ func (_i *articlesService) SummaryStats(authToken string) (summaryStats *respons
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (_i *articlesService) ArticlePerUserLevelStats(authToken string, startDate *string, endDate *string) (articlePerUserLevelStats []*response.ArticlePerUserLevelStats, err error) {
|
||||||
|
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
|
||||||
|
|
||||||
|
_i.Log.Info().Str("timestamp", time.Now().
|
||||||
|
Format(time.RFC3339)).Str("Service:Resource", "articlesService:ArticlePerUserLevelStats").
|
||||||
|
Interface("startDate", startDate).Msg("")
|
||||||
|
_i.Log.Info().Str("timestamp", time.Now().
|
||||||
|
Format(time.RFC3339)).Str("Service:Resource", "articlesService:ArticlePerUserLevelStats").
|
||||||
|
Interface("endDate", endDate).Msg("")
|
||||||
|
|
||||||
|
var userLevelId *uint
|
||||||
|
var userLevelNumber *int
|
||||||
|
|
||||||
|
if user != nil {
|
||||||
|
userLevelId = &user.UserLevelId
|
||||||
|
userLevelNumber = &user.UserLevel.LevelNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
_i.Log.Info().Str("timestamp", time.Now().
|
||||||
|
Format(time.RFC3339)).Str("Service:Resource", "articlesService:ArticlePerUserLevelStats").
|
||||||
|
Interface("userLevelId", userLevelId).Msg("")
|
||||||
|
_i.Log.Info().Str("timestamp", time.Now().
|
||||||
|
Format(time.RFC3339)).Str("Service:Resource", "articlesService:ArticlePerUserLevelStats").
|
||||||
|
Interface("userLevelNumber", userLevelNumber).Msg("")
|
||||||
|
|
||||||
|
result, err := _i.Repo.ArticlePerUserLevelStats(userLevelId, userLevelNumber, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_i *articlesService) ArticleMonthlyStats(authToken string, year *int) (articleMonthlyStats []*response.ArticleMonthlyStats, err error) {
|
||||||
|
user := utilSvc.GetUserInfo(_i.Log, _i.UsersRepo, authToken)
|
||||||
|
|
||||||
|
var userLevelId *uint
|
||||||
|
var userLevelNumber *int
|
||||||
|
|
||||||
|
if user != nil {
|
||||||
|
userLevelId = &user.UserLevelId
|
||||||
|
userLevelNumber = &user.UserLevel.LevelNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := _i.Repo.ArticleMonthlyStats(userLevelId, userLevelNumber, *year)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func getFileExtension(filename string) string {
|
func getFileExtension(filename string) string {
|
||||||
// split file name
|
// split file name
|
||||||
parts := strings.Split(filename, ".")
|
parts := strings.Split(filename, ".")
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
package mapper
|
package mapper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go-humas-be/app/database/entity"
|
"go-humas-be/app/database/entity/users"
|
||||||
userLevelsRepository "go-humas-be/app/module/user_levels/repository"
|
userLevelsRepository "go-humas-be/app/module/user_levels/repository"
|
||||||
res "go-humas-be/app/module/users/response"
|
res "go-humas-be/app/module/users/response"
|
||||||
)
|
)
|
||||||
|
|
||||||
func UsersResponseMapper(usersReq *entity.Users, userLevelsRepo userLevelsRepository.UserLevelsRepository) (usersRes *res.UsersResponse) {
|
func UsersResponseMapper(usersReq *users.Users, userLevelsRepo userLevelsRepository.UserLevelsRepository) (usersRes *res.UsersResponse) {
|
||||||
if usersReq != nil {
|
if usersReq != nil {
|
||||||
findUserLevel, _ := userLevelsRepo.FindOne(usersReq.UserLevelId)
|
findUserLevel, _ := userLevelsRepo.FindOne(usersReq.UserLevelId)
|
||||||
userLevelGroup := ""
|
userLevelGroup := ""
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go-humas-be/app/database"
|
"go-humas-be/app/database"
|
||||||
"go-humas-be/app/database/entity"
|
"go-humas-be/app/database/entity"
|
||||||
|
"go-humas-be/app/database/entity/users"
|
||||||
"go-humas-be/app/module/users/request"
|
"go-humas-be/app/module/users/request"
|
||||||
"go-humas-be/utils/paginator"
|
"go-humas-be/utils/paginator"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -17,12 +18,12 @@ type usersRepository struct {
|
||||||
|
|
||||||
// UsersRepository define interface of IUsersRepository
|
// UsersRepository define interface of IUsersRepository
|
||||||
type UsersRepository interface {
|
type UsersRepository interface {
|
||||||
GetAll(req request.UsersQueryRequest) (userss []*entity.Users, paging paginator.Pagination, err error)
|
GetAll(req request.UsersQueryRequest) (userss []*users.Users, paging paginator.Pagination, err error)
|
||||||
FindOne(id uint) (users *entity.Users, err error)
|
FindOne(id uint) (users *users.Users, err error)
|
||||||
FindByKeycloakId(keycloakId string) (users *entity.Users, err error)
|
FindByKeycloakId(keycloakId string) (users *users.Users, err error)
|
||||||
FindByUsername(username string) (users *entity.Users, err error)
|
FindByUsername(username string) (users *users.Users, err error)
|
||||||
Create(users *entity.Users) (userReturn *entity.Users, err error)
|
Create(users *users.Users) (userReturn *users.Users, err error)
|
||||||
Update(id uint, users *entity.Users) (err error)
|
Update(id uint, users *users.Users) (err error)
|
||||||
Delete(id uint) (err error)
|
Delete(id uint) (err error)
|
||||||
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)
|
||||||
|
|
@ -39,10 +40,10 @@ func NewUsersRepository(db *database.Database, log zerolog.Logger) UsersReposito
|
||||||
}
|
}
|
||||||
|
|
||||||
// implement interface of IUsersRepository
|
// implement interface of IUsersRepository
|
||||||
func (_i *usersRepository) GetAll(req request.UsersQueryRequest) (userss []*entity.Users, paging paginator.Pagination, err error) {
|
func (_i *usersRepository) GetAll(req request.UsersQueryRequest) (userss []*users.Users, paging paginator.Pagination, err error) {
|
||||||
var count int64
|
var count int64
|
||||||
|
|
||||||
query := _i.DB.DB.Model(&entity.Users{})
|
query := _i.DB.DB.Model(&users.Users{})
|
||||||
query = query.Where("is_active = ?", true)
|
query = query.Where("is_active = ?", true)
|
||||||
|
|
||||||
if req.Username != nil && *req.Username != "" {
|
if req.Username != nil && *req.Username != "" {
|
||||||
|
|
@ -106,7 +107,7 @@ func (_i *usersRepository) GetAll(req request.UsersQueryRequest) (userss []*enti
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersRepository) FindOne(id uint) (users *entity.Users, err error) {
|
func (_i *usersRepository) FindOne(id uint) (users *users.Users, err error) {
|
||||||
if err := _i.DB.DB.First(&users, id).Error; err != nil {
|
if err := _i.DB.DB.First(&users, id).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -114,15 +115,15 @@ func (_i *usersRepository) FindOne(id uint) (users *entity.Users, err error) {
|
||||||
return users, nil
|
return users, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersRepository) FindByKeycloakId(keycloakId string) (users *entity.Users, err error) {
|
func (_i *usersRepository) FindByKeycloakId(keycloakId string) (users *users.Users, err error) {
|
||||||
if err := _i.DB.DB.Where("keycloak_id = ?", keycloakId).First(&users).Error; err != nil {
|
if err := _i.DB.DB.Where("keycloak_id = ?", keycloakId).Preload("UserLevel").First(&users).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return users, nil
|
return users, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersRepository) FindByUsername(username string) (users *entity.Users, err error) {
|
func (_i *usersRepository) FindByUsername(username string) (users *users.Users, err error) {
|
||||||
if err := _i.DB.DB.Where("username = ?", username).First(&users).Error; err != nil {
|
if err := _i.DB.DB.Where("username = ?", username).First(&users).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -130,19 +131,19 @@ func (_i *usersRepository) FindByUsername(username string) (users *entity.Users,
|
||||||
return users, nil
|
return users, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersRepository) Create(users *entity.Users) (userReturn *entity.Users, err error) {
|
func (_i *usersRepository) Create(users *users.Users) (userReturn *users.Users, err error) {
|
||||||
result := _i.DB.DB.Create(users)
|
result := _i.DB.DB.Create(users)
|
||||||
return users, result.Error
|
return users, result.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersRepository) Update(id uint, users *entity.Users) (err error) {
|
func (_i *usersRepository) Update(id uint, usersReturn *users.Users) (err error) {
|
||||||
return _i.DB.DB.Model(&entity.Users{}).
|
return _i.DB.DB.Model(&users.Users{}).
|
||||||
Where(&entity.Users{ID: id}).
|
Where(&users.Users{ID: id}).
|
||||||
Updates(users).Error
|
Updates(usersReturn).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersRepository) Delete(id uint) error {
|
func (_i *usersRepository) Delete(id uint) error {
|
||||||
return _i.DB.DB.Delete(&entity.Users{}, id).Error
|
return _i.DB.DB.Delete(&users.Users{}, id).Error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersRepository) CreateForgotPassword(forgotPasswords *entity.ForgotPasswords) (err error) {
|
func (_i *usersRepository) CreateForgotPassword(forgotPasswords *entity.ForgotPasswords) (err error) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package request
|
package request
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go-humas-be/app/database/entity"
|
"go-humas-be/app/database/entity/users"
|
||||||
"go-humas-be/utils/paginator"
|
"go-humas-be/utils/paginator"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -46,8 +46,8 @@ type UsersCreateRequest struct {
|
||||||
LastEducation *string `json:"lastEducation"`
|
LastEducation *string `json:"lastEducation"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (req UsersCreateRequest) ToEntity() *entity.Users {
|
func (req UsersCreateRequest) ToEntity() *users.Users {
|
||||||
return &entity.Users{
|
return &users.Users{
|
||||||
Username: req.Username,
|
Username: req.Username,
|
||||||
Email: req.Email,
|
Email: req.Email,
|
||||||
Fullname: req.Fullname,
|
Fullname: req.Fullname,
|
||||||
|
|
@ -85,8 +85,8 @@ type UsersUpdateRequest struct {
|
||||||
StatusId *int `json:"statusId"`
|
StatusId *int `json:"statusId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (req UsersUpdateRequest) ToEntity() *entity.Users {
|
func (req UsersUpdateRequest) ToEntity() *users.Users {
|
||||||
return &entity.Users{
|
return &users.Users{
|
||||||
Username: req.Username,
|
Username: req.Username,
|
||||||
Email: req.Email,
|
Email: req.Email,
|
||||||
Fullname: req.Fullname,
|
Fullname: req.Fullname,
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/Nerzal/gocloak/v13"
|
"github.com/Nerzal/gocloak/v13"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go-humas-be/app/database/entity"
|
"go-humas-be/app/database/entity"
|
||||||
|
"go-humas-be/app/database/entity/users"
|
||||||
userLevelsRepository "go-humas-be/app/module/user_levels/repository"
|
userLevelsRepository "go-humas-be/app/module/user_levels/repository"
|
||||||
"go-humas-be/app/module/users/mapper"
|
"go-humas-be/app/module/users/mapper"
|
||||||
"go-humas-be/app/module/users/repository"
|
"go-humas-be/app/module/users/repository"
|
||||||
|
|
@ -35,7 +36,7 @@ type UsersService interface {
|
||||||
Show(id uint) (users *response.UsersResponse, err error)
|
Show(id uint) (users *response.UsersResponse, err error)
|
||||||
ShowByUsername(username string) (users *response.UsersResponse, err error)
|
ShowByUsername(username string) (users *response.UsersResponse, err error)
|
||||||
ShowUserInfo(authToken string) (users *response.UsersResponse, err error)
|
ShowUserInfo(authToken string) (users *response.UsersResponse, err error)
|
||||||
Save(req request.UsersCreateRequest, authToken string) (userReturn *entity.Users, err error)
|
Save(req request.UsersCreateRequest, authToken string) (userReturn *users.Users, err error)
|
||||||
Login(req request.UserLogin) (res *gocloak.JWT, err error)
|
Login(req request.UserLogin) (res *gocloak.JWT, err error)
|
||||||
ParetoLogin(req request.UserLogin) (res *response.ParetoLoginResponse, err error)
|
ParetoLogin(req request.UserLogin) (res *response.ParetoLoginResponse, err error)
|
||||||
Update(id uint, req request.UsersUpdateRequest) (err error)
|
Update(id uint, req request.UsersUpdateRequest) (err error)
|
||||||
|
|
@ -97,7 +98,7 @@ func (_i *usersService) ShowUserInfo(authToken string) (users *response.UsersRes
|
||||||
return mapper.UsersResponseMapper(userInfo, _i.UserLevelsRepo), nil
|
return mapper.UsersResponseMapper(userInfo, _i.UserLevelsRepo), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (_i *usersService) Save(req request.UsersCreateRequest, authToken string) (userReturn *entity.Users, err error) {
|
func (_i *usersService) Save(req request.UsersCreateRequest, authToken string) (userReturn *users.Users, err error) {
|
||||||
_i.Log.Info().Interface("data", req).Msg("")
|
_i.Log.Info().Interface("data", req).Msg("")
|
||||||
newReq := req.ToEntity()
|
newReq := req.ToEntity()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ type app = struct {
|
||||||
type db = struct {
|
type db = struct {
|
||||||
Postgres struct {
|
Postgres struct {
|
||||||
DSN string `toml:"dsn"`
|
DSN string `toml:"dsn"`
|
||||||
|
LogMode string `toml:"log-mode"`
|
||||||
Migrate bool `toml:"migrate"`
|
Migrate bool `toml:"migrate"`
|
||||||
Seed bool `toml:"seed"`
|
Seed bool `toml:"seed"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,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"
|
||||||
migrate = false
|
migrate = false
|
||||||
seed = false
|
seed = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2339,6 +2339,62 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/articles/statistic/monthly": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for ArticleMonthlyStats of Article",
|
||||||
|
"tags": [
|
||||||
|
"Articles"
|
||||||
|
],
|
||||||
|
"summary": "ArticleMonthlyStats Articles",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"default": "Bearer \u003cAdd access token here\u003e",
|
||||||
|
"description": "Insert your access token",
|
||||||
|
"name": "Authorization",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "year",
|
||||||
|
"name": "year",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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/statistic/summary": {
|
"/articles/statistic/summary": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -2389,6 +2445,68 @@ const docTemplate = `{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/articles/statistic/user-levels": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for ArticlePerUserLevelStats of Article",
|
||||||
|
"tags": [
|
||||||
|
"Articles"
|
||||||
|
],
|
||||||
|
"summary": "ArticlePerUserLevelStats Articles",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"default": "Bearer \u003cAdd access token here\u003e",
|
||||||
|
"description": "Insert your access token",
|
||||||
|
"name": "Authorization",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "start date",
|
||||||
|
"name": "startDate",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "start date",
|
||||||
|
"name": "endDate",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.BadRequestError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Unauthorized",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.UnauthorizedError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.InternalServerError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/articles/thumbnail/viewer/{thumbnailName}": {
|
"/articles/thumbnail/viewer/{thumbnailName}": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
|
||||||
|
|
@ -2328,6 +2328,62 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/articles/statistic/monthly": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for ArticleMonthlyStats of Article",
|
||||||
|
"tags": [
|
||||||
|
"Articles"
|
||||||
|
],
|
||||||
|
"summary": "ArticleMonthlyStats Articles",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"default": "Bearer \u003cAdd access token here\u003e",
|
||||||
|
"description": "Insert your access token",
|
||||||
|
"name": "Authorization",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "integer",
|
||||||
|
"description": "year",
|
||||||
|
"name": "year",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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/statistic/summary": {
|
"/articles/statistic/summary": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
@ -2378,6 +2434,68 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/articles/statistic/user-levels": {
|
||||||
|
"get": {
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"Bearer": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "API for ArticlePerUserLevelStats of Article",
|
||||||
|
"tags": [
|
||||||
|
"Articles"
|
||||||
|
],
|
||||||
|
"summary": "ArticlePerUserLevelStats Articles",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"default": "Bearer \u003cAdd access token here\u003e",
|
||||||
|
"description": "Insert your access token",
|
||||||
|
"name": "Authorization",
|
||||||
|
"in": "header",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "start date",
|
||||||
|
"name": "startDate",
|
||||||
|
"in": "query"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "start date",
|
||||||
|
"name": "endDate",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Bad Request",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.BadRequestError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"401": {
|
||||||
|
"description": "Unauthorized",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.UnauthorizedError"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"500": {
|
||||||
|
"description": "Internal Server Error",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/response.InternalServerError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/articles/thumbnail/viewer/{thumbnailName}": {
|
"/articles/thumbnail/viewer/{thumbnailName}": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
|
|
|
||||||
|
|
@ -2354,6 +2354,42 @@ paths:
|
||||||
summary: Update Articles
|
summary: Update Articles
|
||||||
tags:
|
tags:
|
||||||
- Articles
|
- Articles
|
||||||
|
/articles/statistic/monthly:
|
||||||
|
get:
|
||||||
|
description: API for ArticleMonthlyStats of Article
|
||||||
|
parameters:
|
||||||
|
- default: Bearer <Add access token here>
|
||||||
|
description: Insert your access token
|
||||||
|
in: header
|
||||||
|
name: Authorization
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- description: year
|
||||||
|
in: query
|
||||||
|
name: year
|
||||||
|
type: integer
|
||||||
|
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: ArticleMonthlyStats Articles
|
||||||
|
tags:
|
||||||
|
- Articles
|
||||||
/articles/statistic/summary:
|
/articles/statistic/summary:
|
||||||
get:
|
get:
|
||||||
description: API for Summary Stats of Article
|
description: API for Summary Stats of Article
|
||||||
|
|
@ -2386,6 +2422,46 @@ paths:
|
||||||
summary: SummaryStats Articles
|
summary: SummaryStats Articles
|
||||||
tags:
|
tags:
|
||||||
- Articles
|
- Articles
|
||||||
|
/articles/statistic/user-levels:
|
||||||
|
get:
|
||||||
|
description: API for ArticlePerUserLevelStats of Article
|
||||||
|
parameters:
|
||||||
|
- default: Bearer <Add access token here>
|
||||||
|
description: Insert your access token
|
||||||
|
in: header
|
||||||
|
name: Authorization
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- description: start date
|
||||||
|
in: query
|
||||||
|
name: startDate
|
||||||
|
type: string
|
||||||
|
- description: start date
|
||||||
|
in: query
|
||||||
|
name: endDate
|
||||||
|
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: ArticlePerUserLevelStats Articles
|
||||||
|
tags:
|
||||||
|
- Articles
|
||||||
/articles/thumbnail/{id}:
|
/articles/thumbnail/{id}:
|
||||||
post:
|
post:
|
||||||
description: API for Save Thumbnail of Articles
|
description: API for Save Thumbnail of Articles
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,13 @@ package service
|
||||||
import (
|
import (
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"go-humas-be/app/database/entity"
|
"go-humas-be/app/database/entity/users"
|
||||||
"go-humas-be/app/module/users/repository"
|
"go-humas-be/app/module/users/repository"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetUserInfo(log zerolog.Logger, repo repository.UsersRepository, bearerToken string) *entity.Users {
|
func GetUserInfo(log zerolog.Logger, repo repository.UsersRepository, bearerToken string) *users.Users {
|
||||||
tokenString := strings.TrimPrefix(bearerToken, "Bearer ")
|
tokenString := strings.TrimPrefix(bearerToken, "Bearer ")
|
||||||
token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{})
|
token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue