chores: refactor struct and structure project

This commit is contained in:
ericprd 2025-03-05 21:21:44 +08:00
parent 13a8481f22
commit 567e0e32ca
103 changed files with 1126 additions and 732 deletions

View File

@ -14,3 +14,4 @@ REDIS_PORT=
REDIS_PASSWORD=
REDIS_TTL=
REDIS_DB=
REDIS_TIMEOUT=

View File

@ -15,6 +15,7 @@ import (
"github.com/go-chi/chi/v5"
"github.com/joho/godotenv"
"github.com/redis/go-redis/v9"
"go.uber.org/fx"
)
@ -32,16 +33,26 @@ func init() {
config.InitEnv()
}
func run(lc fx.Lifecycle, db *database.DB, apiRouter chi.Router) {
func run(
lc fx.Lifecycle,
db *database.DB,
apiRouter chi.Router,
rdb *redis.Client,
) {
lc.Append(fx.Hook{
OnStart: func(ctx context.Context) error {
fmt.Println("Application has started...")
_, err := rdb.Ping(ctx).Result()
if err != nil {
log.Fatalf("Could not connect to Redis: %v", err)
}
pkgconfig.Router(apiRouter)
return nil
},
OnStop: func(ctx context.Context) error {
fmt.Println("Shutting down...")
rdb.Close()
return nil
},
})

View File

@ -1,7 +1,11 @@
package config
import "fmt"
var (
APP_PORT int
APP_PORT,
REDIS_DB,
REDIS_TIMEOUT,
GRACEFULL_TIMEOUT int
// DB
@ -10,6 +14,9 @@ var (
DB_PASSWORD,
DB_NAME,
DB_PORT,
REDIS_PASSWORD,
REDIS_ADDR,
REDIS_USERNAME,
SALT_SECURITY string
)
@ -24,4 +31,10 @@ func InitEnv() {
APP_PORT = GetOrDefault("APP_PORT", 3000)
GRACEFULL_TIMEOUT = GetOrDefault("GRACEFULL_TIMEOUT", 10)
REDIS_DB = GetOrDefault("REDIS_DB", 0)
REDIS_PASSWORD = GetOrDefault("REDIS_PASSWORD", "")
REDIS_ADDR = fmt.Sprintf("%s:%s", GetOrDefault("REDIS_HOST", "localhost"), GetOrDefault("REDIS_PORT", "6379"))
REDIS_USERNAME = GetOrDefault("REDIS_USERNAME", "")
REDIS_TIMEOUT = GetOrDefault("REDIS_TIMEOUT", 60)
}

View File

@ -5,17 +5,10 @@ import (
)
type Category struct {
ID string `gorm:"primaryKey" json:"id"`
Code string `gorm:"not null;unique" json:"code"`
Name string `gorm:"not null" json:"name"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
type CategoryModel struct {
ID string `gorm:"primaryKey" json:"id"`
Name string `gorm:"not null;unique" json:"name"`
Code string `gorm:"not null" json:"code"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
}

View File

@ -58,8 +58,8 @@ func (db *DB) Migrate() error {
// &Tag{},
// &Category{},
// &News{},
&NewsModel{},
&TagModel{},
&CategoryModel{},
&News{},
&Tag{},
&Category{},
)
}

View File

@ -5,26 +5,11 @@ import (
)
type News struct {
ID string `gorm:"primaryKey" json:"id"`
Title string `gorm:"default:null" json:"title"`
Tags []Tag `gorm:"many2many:news_tags" json:"tags"`
Categories []Category `gorm:"many2many:news_categories" json:"categories"`
Content string `gorm:"default:null" json:"content"`
LiveAt time.Time `gorm:"not null" json:"live_at"`
AuthorID string `gorm:"not null" json:"author_id"`
IsPremium bool `gorm:"default:false" json:"is_premium"`
Slug string `gorm:"default:null" json:"slug"`
FeaturedImage string `gorm:"default:null" json:"featured_image"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
type NewsModel struct {
ID string `gorm:"primaryKey" json:"id"`
Title string `json:"title"`
Content string `json:"content"`
Categories []CategoryModel `gorm:"many2many:news_categories" json:"categories"`
Tags []TagModel `gorm:"many2many:news_tags" json:"tags"`
Categories []Category `gorm:"many2many:news_categories" json:"categories"`
Tags []Tag `gorm:"many2many:news_tags" json:"tags"`
IsPremium bool `gorm:"default:false" json:"is_premium"`
Slug string `gorm:"default:null" json:"slug"`
FeaturedImage string `gorm:"default:null" json:"featured_image"`
@ -32,4 +17,5 @@ type NewsModel struct {
LiveAt time.Time `gorm:"not null" json:"live_at"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
}

View File

@ -12,4 +12,5 @@ type Staff struct {
Password string `gorm:"not null" json:"password"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
}

View File

@ -13,8 +13,9 @@ type Subscribe struct {
AutoRenew bool `gorm:"default:true"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
SubscribePlan SubscribePlan `gorm:"foreignKey:SubscribePlanID;constraint:OnDelete:CASCADE"`
SubscribePlan SubscribePlan `gorm:"foreignKey:SubscribePlanID;constraint:OnDelete:CASCADE" json:"subscribe_plan"`
}
type SubscribePlan struct {

View File

@ -5,17 +5,10 @@ import (
)
type Tag struct {
ID string `gorm:"primaryKey" json:"id"`
Code string `gorm:"not null;unique" json:"code"`
Name string `gorm:"not null" json:"name"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
}
type TagModel struct {
ID string `gorm:"primaryKey" json:"id"`
Name string `gorm:"not null;unique" json:"name"`
Code string `gorm:"not null" json:"code"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
}

View File

@ -12,6 +12,7 @@ type User struct {
Phone string `gorm:"default:not null;unique" json:"phone"`
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
Subscribe Subscribe `gorm:"foreignKey:SubscribeID;constraint:OnDelete:CASCADE"`
Subscribe Subscribe `gorm:"foreignKey:SubscribeID;constraint:OnDelete:CASCADE" json:"subscribe"`
}

1
go.mod
View File

@ -31,6 +31,7 @@ require (
github.com/go-chi/chi/v5 v5.2.1
github.com/go-chi/cors v1.2.1
github.com/go-playground/validator/v10 v10.25.0
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/google/uuid v1.6.0
github.com/redis/go-redis/v9 v9.7.1
github.com/sirupsen/logrus v1.9.3

2
go.sum
View File

@ -23,6 +23,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=

View File

@ -1,13 +1,14 @@
package categoryrepository
import (
"legalgo-BE-go/database"
categorydomain "legalgo-BE-go/internal/domain/category"
"github.com/google/uuid"
)
func (a *accessor) Create(spec categorydomain.CategoryReq) error {
data := categorydomain.Category{
func (a *accessor) CreateModel(spec categorydomain.CategoryReq) error {
data := database.Category{
ID: uuid.NewString(),
Name: spec.Name,
Code: spec.Code,

View File

@ -1,22 +0,0 @@
package categoryrepository
import (
"legalgo-BE-go/database"
categorydomain "legalgo-BE-go/internal/domain/category"
"github.com/google/uuid"
)
func (a *accessor) CreateModel(spec categorydomain.CategoryReq) error {
data := database.CategoryModel{
ID: uuid.NewString(),
Name: spec.Name,
Code: spec.Code,
}
if err := a.DB.Create(&data).Error; err != nil {
return err
}
return nil
}

View File

@ -1,8 +1,10 @@
package categoryrepository
import categorydomain "legalgo-BE-go/internal/domain/category"
import (
categorydomain "legalgo-BE-go/internal/domain/category"
)
func (a *accessor) GetAll() ([]categorydomain.Category, error) {
func (a *accessor) GetAllModel() ([]categorydomain.Category, error) {
var categories []categorydomain.Category
if err := a.DB.Find(&categories).Error; err != nil {

View File

@ -1,15 +0,0 @@
package categoryrepository
import (
"legalgo-BE-go/database"
)
func (a *accessor) GetAllModel() ([]database.CategoryModel, error) {
var categories []database.CategoryModel
if err := a.DB.Find(&categories).Error; err != nil {
return nil, err
}
return categories, nil
}

View File

@ -1,11 +1,11 @@
package categoryrepository
import (
categorydomain "legalgo-BE-go/internal/domain/category"
"legalgo-BE-go/database"
)
func (a *accessor) GetByIDs(ids []string) ([]categorydomain.Category, error) {
var categories []categorydomain.Category
func (a *accessor) GetByIDs(ids []string) ([]database.Category, error) {
var categories []database.Category
if err := a.DB.Find(&categories, "id IN ?", ids).Error; err != nil {
return nil, err

View File

@ -1,15 +0,0 @@
package categoryrepository
import (
"legalgo-BE-go/database"
)
func (a *accessor) GetBulks(ids []string) ([]database.CategoryModel, error) {
var categories []database.CategoryModel
if err := a.DB.Find(&categories, "id IN ?", ids).Error; err != nil {
return nil, err
}
return categories, nil
}

View File

@ -10,14 +10,11 @@ type accessor struct {
}
type Category interface {
Create(categorydomain.CategoryReq) error
CreateModel(categorydomain.CategoryReq) error
Update(categorydomain.Category) error
GetAll() ([]categorydomain.Category, error)
GetAllModel() ([]database.CategoryModel, error)
GetByIDs([]string) ([]categorydomain.Category, error)
GetBulks([]string) ([]database.CategoryModel, error)
GetAllModel() ([]categorydomain.Category, error)
GetByIDs([]string) ([]database.Category, error)
}
func New(

View File

@ -0,0 +1,19 @@
package categoryrepository
import (
"fmt"
categorydomain "legalgo-BE-go/internal/domain/category"
"gorm.io/gorm/clause"
)
func (a *accessor) Update(spec categorydomain.Category) error {
if err := a.DB.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoUpdates: clause.AssignmentColumns([]string{"name", "code", "updated_at"}),
}).Save(&spec).Error; err != nil {
return fmt.Errorf("failed to update category: %v", err)
}
return nil
}

View File

@ -5,7 +5,7 @@ import (
"legalgo-BE-go/database"
)
func (a *accessor) CreateModel(spec database.NewsModel) error {
func (a *accessor) CreateModel(spec database.News) error {
if err := a.db.Create(&spec).Error; err != nil {
return fmt.Errorf("failed to create news: %w", err)
}

View File

@ -2,8 +2,8 @@ package newsrepository
import "legalgo-BE-go/database"
func (a *accessor) GetAllModel() ([]database.NewsModel, error) {
var news []database.NewsModel
func (a *accessor) GetAllModel() ([]database.News, error) {
var news []database.News
if err := a.db.Preload("Tags").Preload("Categories").Find(&news).Error; err != nil {
return nil, err

View File

@ -11,9 +11,9 @@ type accessor struct {
type News interface {
GetAll() ([]newsdomain.News, error)
GetAllModel() ([]database.NewsModel, error)
GetAllModel() ([]database.News, error)
Create(*newsdomain.News) error
CreateModel(database.NewsModel) error
CreateModel(database.News) error
}
func New(db *database.DB) News {

View File

@ -1,8 +1,7 @@
package redisaccessor
import (
"fmt"
"os"
"legalgo-BE-go/config"
"github.com/redis/go-redis/v9"
)
@ -14,18 +13,11 @@ func Get() *redis.Client {
}
func New() *redis.Client {
var (
username = os.Getenv("REDIS_USERNAME")
addr = fmt.Sprintf("%s:%s", os.Getenv("REDIS_HOST"), os.Getenv("REDIS_PORT"))
password = os.Getenv("REDIS_PASSWORD")
db = 2 // TODO: change later
)
redisClient = redis.NewClient(&redis.Options{
Username: username,
Addr: addr,
Password: password,
DB: db,
Username: config.REDIS_USERNAME,
Addr: config.REDIS_ADDR,
Password: config.REDIS_PASSWORD,
DB: config.REDIS_DB,
})
return redisClient

View File

@ -1,11 +1,13 @@
package staffrepository
import authdomain "legalgo-BE-go/internal/domain/auth"
import (
staffdomain "legalgo-BE-go/internal/domain/staff"
)
func (ur *StaffRepository) Create(spec *authdomain.Staff) (*authdomain.Staff, error) {
if err := ur.DB.Create(&spec).Error; err != nil {
return nil, err
func (ur *impl) Create(spec staffdomain.Staff) error {
if err := ur.db.Create(&spec).Error; err != nil {
return err
}
return spec, nil
return nil
}

View File

@ -3,19 +3,19 @@ package staffrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
staffdomain "legalgo-BE-go/internal/domain/staff"
"gorm.io/gorm"
)
func (sr *StaffRepository) GetStaffByEmail(email string) (*authdomain.Staff, error) {
var staff authdomain.Staff
func (sr *impl) GetStaffByEmail(email string) (*staffdomain.Staff, error) {
var staff staffdomain.Staff
if email == "" {
return nil, errors.New("email is required")
}
if err := sr.DB.First(&staff, "email = ?", email).Error; err != nil {
if err := sr.db.First(&staff, "email = ?", email).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("staff not found")
}

View File

@ -2,19 +2,19 @@ package staffrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
staffdomain "legalgo-BE-go/internal/domain/staff"
"gorm.io/gorm"
)
func (sr *StaffRepository) GetStaffByID(ID string) (*authdomain.Staff, error) {
var staff authdomain.Staff
func (sr *impl) GetStaffByID(ID string) (*staffdomain.Staff, error) {
var staff staffdomain.Staff
if ID == "" {
return nil, errors.New("id is required")
}
if err := sr.DB.First(&staff, "id = ? ", ID).Error; err != nil {
if err := sr.db.First(&staff, "id = ? ", ID).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("staff not found")
}

View File

@ -2,20 +2,20 @@ package staffrepository
import (
"legalgo-BE-go/database"
authdomain "legalgo-BE-go/internal/domain/auth"
staffdomain "legalgo-BE-go/internal/domain/staff"
)
type StaffRepository struct {
DB *database.DB
type impl struct {
db *database.DB
}
type StaffIntf interface {
GetStaffByEmail(string) (*authdomain.Staff, error)
GetStaffByID(string) (*authdomain.Staff, error)
Create(*authdomain.Staff) (*authdomain.Staff, error)
Update(authdomain.Staff) error
type Staff interface {
GetStaffByEmail(string) (*staffdomain.Staff, error)
GetStaffByID(string) (*staffdomain.Staff, error)
Create(staffdomain.Staff) error
Update(staffdomain.Staff) error
}
func New(db *database.DB) StaffIntf {
return &StaffRepository{db}
func New(db *database.DB) Staff {
return &impl{db}
}

View File

@ -1,17 +1,17 @@
package staffrepository
import (
authdomain "legalgo-BE-go/internal/domain/auth"
staffdomain "legalgo-BE-go/internal/domain/staff"
"legalgo-BE-go/internal/utilities/utils"
)
func (ur *StaffRepository) Update(spec authdomain.Staff) error {
func (ur *impl) Update(spec staffdomain.Staff) error {
val, err := utils.StructToMap(spec)
if err != nil {
return err
}
if err := ur.DB.Model(&authdomain.Staff{}).Where("id = ?", spec.ID).Updates(val).Error; err != nil {
if err := ur.db.Model(&staffdomain.Staff{}).Where("id = ?", spec.ID).Updates(val).Error; err != nil {
return err
}

View File

@ -0,0 +1,23 @@
package subscriberepository
import (
"errors"
"fmt"
"legalgo-BE-go/database"
"gorm.io/gorm"
)
func (s *SubsAccs) GetByID(id string) (database.Subscribe, error) {
var subscribe database.Subscribe
if err := s.DB.First(&subscribe, "id = ?", id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return subscribe, fmt.Errorf("subscribe data not found: %v", err)
}
return subscribe, err
}
return subscribe, nil
}

View File

@ -8,6 +8,8 @@ type SubsAccs struct {
type SubsIntf interface {
Create(string) (string, error)
GetByID(string) (database.Subscribe, error)
UpdateSubscribeStatus(database.Subscribe) error
}
func New(db *database.DB) SubsIntf {

View File

@ -0,0 +1,19 @@
package subscriberepository
import (
"fmt"
"legalgo-BE-go/database"
"gorm.io/gorm/clause"
)
func (a *SubsAccs) UpdateSubscribeStatus(spec database.Subscribe) error {
if err := a.DB.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "id"}},
DoUpdates: clause.AssignmentColumns([]string{"status"}),
}).Create(&spec).Error; err != nil {
return fmt.Errorf("failed to update status: %v", err)
}
return nil
}

View File

@ -2,13 +2,13 @@ package subscribeplanrepository
import (
"errors"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
"legalgo-BE-go/database"
"gorm.io/gorm"
)
func (s *SubsPlan) GetByID(id string) (subscribeplandomain.SubscribePlan, error) {
var subscribePlan subscribeplandomain.SubscribePlan
func (s *SubsPlan) GetByID(id string) (*database.SubscribePlan, error) {
var subscribePlan *database.SubscribePlan
if err := s.DB.First(&subscribePlan, "id = ? ", id).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {

View File

@ -1,16 +1,16 @@
package subscribeplanrepository
import (
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
"legalgo-BE-go/database"
"github.com/google/uuid"
)
func (s *SubsPlan) GetDefault() (subscribeplandomain.SubscribePlan, error) {
var subscribePlan subscribeplandomain.SubscribePlan
func (s *SubsPlan) GetDefault() (*database.SubscribePlan, error) {
var subscribePlan *database.SubscribePlan
if err := s.DB.First(&subscribePlan, "code = ?", "basic").Error; err != nil {
s.DB.Create(&subscribeplandomain.SubscribePlan{
s.DB.Create(&database.SubscribePlan{
ID: uuid.NewString(),
Code: "basic",
Name: "Basic",

View File

@ -12,8 +12,8 @@ type SubsPlan struct {
type SubsPlanIntf interface {
Create(subscribeplandomain.SubscribePlanReq) error
GetAll() ([]subscribeplandomain.SubscribePlan, error)
GetByID(string) (subscribeplandomain.SubscribePlan, error)
GetDefault() (subscribeplandomain.SubscribePlan, error)
GetByID(string) (*database.SubscribePlan, error)
GetDefault() (*database.SubscribePlan, error)
}
func New(

View File

@ -8,7 +8,7 @@ import (
)
func (acc *accessor) CreateModel(spec tagdomain.TagReq) error {
data := &database.TagModel{
data := &database.Tag{
ID: uuid.NewString(),
Code: spec.Code,
Name: spec.Name,

View File

@ -2,8 +2,8 @@ package tagrepository
import "legalgo-BE-go/database"
func (acc *accessor) GetAllModel() ([]database.TagModel, error) {
var tags []database.TagModel
func (acc *accessor) GetAllModel() ([]database.Tag, error) {
var tags []database.Tag
if err := acc.DB.Find(&tags).Error; err != nil {
return nil, err

View File

@ -2,8 +2,8 @@ package tagrepository
import "legalgo-BE-go/database"
func (a *accessor) GetBulks(ids []string) ([]database.TagModel, error) {
var tags []database.TagModel
func (a *accessor) GetBulks(ids []string) ([]database.Tag, error) {
var tags []database.Tag
if err := a.DB.Find(&tags, "id IN ?", ids).Error; err != nil {
return nil, err

View File

@ -13,9 +13,9 @@ type TagAccessor interface {
Create(tagdomain.TagReq) error
CreateModel(tagdomain.TagReq) error
GetAll() ([]tagdomain.Tag, error)
GetAllModel() ([]database.TagModel, error)
GetAllModel() ([]database.Tag, error)
GetByIDs([]string) ([]tagdomain.Tag, error)
GetBulks(ids []string) ([]database.TagModel, error)
GetBulks(ids []string) ([]database.Tag, error)
}
func New(

View File

@ -1,13 +1,13 @@
package userrepository
import (
authdomain "legalgo-BE-go/internal/domain/auth"
userdomain "legalgo-BE-go/internal/domain/user"
)
func (ur *UserRepository) CreateUser(spec *authdomain.User) (*authdomain.User, error) {
func (ur *UserRepository) CreateUser(spec userdomain.User) error {
if err := ur.DB.Create(&spec).Error; err != nil {
return nil, err
return err
}
return spec, nil
return nil
}

View File

@ -2,14 +2,13 @@ package userrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
userdomain "legalgo-BE-go/internal/domain/user"
"gorm.io/gorm"
)
func (ur *UserRepository) GetUserByEmail(email string) (*authdomain.User, error) {
var user authdomain.User
func (ur *UserRepository) GetUserByEmail(email string) (*userdomain.User, error) {
var user *userdomain.User
if email == "" {
return nil, errors.New("email is empty")
@ -22,5 +21,5 @@ func (ur *UserRepository) GetUserByEmail(email string) (*authdomain.User, error)
return nil, err
}
return &user, nil
return user, nil
}

View File

@ -3,28 +3,22 @@ package userrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
"gorm.io/gorm"
userdomain "legalgo-BE-go/internal/domain/user"
)
func (ur *UserRepository) GetUserByID(email string) (*authdomain.UserProfile, error) {
var users []authdomain.UserProfile
func (ur *UserRepository) GetUserByID(email string) (*userdomain.User, error) {
var user userdomain.User
if email == "" {
return nil, errors.New("email is empty")
}
if err := ur.DB.Table("users u").
Select("u.email, u.id, s.status as subscribe_status, sp.code as subscribe_plan_code, sp.name as subscribe_plan_name").
Joins("join subscribes s on s.id = u.subscribe_id").
Joins("join subscribe_plans sp on s.subscribe_plan_id = sp.id").
Scan(&users).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("user not found")
}
if err := ur.DB.
Preload("Subscribe").
Preload("Subscribe.SubscribePlan").
First(&user, "email = ?", email).Error; err != nil {
return nil, err
}
return &users[0], nil
return &user, nil
}

View File

@ -2,29 +2,30 @@ package userrepository
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
"gorm.io/gorm"
userdomain "legalgo-BE-go/internal/domain/user"
)
func (ur *UserRepository) GetUserProfile(email string) (*authdomain.UserProfile, error) {
var users []authdomain.UserProfile
func (ur *UserRepository) GetUserProfile(email string) (*userdomain.UserProfile, error) {
var user *userdomain.User
if email == "" {
return nil, errors.New("email is empty")
}
if err := ur.DB.Table("users u").
Where("email = ?", email).
Select("u.email, u.id, s.status as subscribe_status, sp.code as subscribe_plan_code, sp.name as subscribe_plan_name").
Joins("join subscribes s on s.id = u.subscribe_id").
Joins("join subscribe_plans sp on s.subscribe_plan_id = sp.id").
Scan(&users).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, errors.New("user not found")
}
if err := ur.DB.
Preload("Subscribe").
Preload("Subscribe.SubscribePlan").
First(&user, "email = ?", email).
Error; err != nil {
return nil, err
}
return &users[0], nil
userProfile := &userdomain.UserProfile{
ID: user.ID,
Email: user.Email,
Phone: user.Phone,
Subscribe: user.Subscribe,
}
return userProfile, nil
}

View File

@ -2,7 +2,7 @@ package userrepository
import (
"legalgo-BE-go/database"
authdomain "legalgo-BE-go/internal/domain/auth"
userdomain "legalgo-BE-go/internal/domain/user"
)
type UserRepository struct {
@ -10,10 +10,10 @@ type UserRepository struct {
}
type UserIntf interface {
GetUserByEmail(string) (*authdomain.User, error)
GetUserByID(string) (*authdomain.UserProfile, error)
GetUserProfile(string) (*authdomain.UserProfile, error)
CreateUser(*authdomain.User) (*authdomain.User, error)
GetUserByEmail(string) (*userdomain.User, error)
GetUserByID(string) (*userdomain.User, error)
GetUserProfile(string) (*userdomain.UserProfile, error)
CreateUser(userdomain.User) error
}
func New(

View File

@ -3,24 +3,27 @@ package authhttp
import (
"net/http"
authdomain "legalgo-BE-go/internal/domain/auth"
responsedomain "legalgo-BE-go/internal/domain/reponse"
staffdomain "legalgo-BE-go/internal/domain/staff"
authsvc "legalgo-BE-go/internal/services/auth"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
"github.com/redis/go-redis/v9"
)
func LoginStaff(
router chi.Router,
authSvc authsvc.AuthIntf,
authSvc authsvc.Auth,
validate *validator.Validate,
rdb *redis.Client,
) {
router.Post("/staff/login", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec authdomain.LoginReq
var spec staffdomain.StaffLogin
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
@ -59,50 +62,7 @@ func LoginStaff(
return
}
responsePayload := &authdomain.AuthResponse{
Token: token,
}
response.RespondJsonSuccess(ctx, w, responsePayload)
})
}
func LoginUser(
router chi.Router,
authSvc authsvc.AuthIntf,
validate *validator.Validate,
) {
router.Post("/user/login", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec authdomain.LoginReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
token, err := authSvc.LoginAsUser(spec)
if err != nil {
if err := utils.StoreTokenRedis(ctx, rdb, token, spec.Email); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
@ -114,7 +74,7 @@ func LoginUser(
return
}
responsePayload := &authdomain.AuthResponse{
responsePayload := &responsedomain.Auth{
Token: token,
}

View File

@ -0,0 +1,82 @@
package authhttp
import (
responsedomain "legalgo-BE-go/internal/domain/reponse"
userdomain "legalgo-BE-go/internal/domain/user"
authsvc "legalgo-BE-go/internal/services/auth"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
"github.com/redis/go-redis/v9"
)
func LoginUser(
router chi.Router,
authSvc authsvc.Auth,
validate *validator.Validate,
rdb *redis.Client,
) {
router.Post("/user/login", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec userdomain.UserLogin
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
token, err := authSvc.LoginAsUser(spec)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
if err := utils.StoreTokenRedis(ctx, rdb, token, spec.Email); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
responsePayload := &responsedomain.Auth{
Token: token,
}
response.RespondJsonSuccess(ctx, w, responsePayload)
})
}

View File

@ -11,7 +11,7 @@ import (
func GetStaffProfile(
router chi.Router,
authSvc authsvc.AuthIntf,
authSvc authsvc.Auth,
) {
router.Get("/staff/profile", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
@ -47,7 +47,7 @@ func GetStaffProfile(
func GetUserProfile(
router chi.Router,
authSvc authsvc.AuthIntf,
authSvc authsvc.Auth,
) {
router.Get("/user/profile", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

View File

@ -3,79 +3,27 @@ package authhttp
import (
"net/http"
authdomain "legalgo-BE-go/internal/domain/auth"
responsedomain "legalgo-BE-go/internal/domain/reponse"
staffdomain "legalgo-BE-go/internal/domain/staff"
authsvc "legalgo-BE-go/internal/services/auth"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
"github.com/redis/go-redis/v9"
)
func RegisterUser(
router chi.Router,
validate *validator.Validate,
authSvc authsvc.AuthIntf,
) {
router.Post("/user/register", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec authdomain.RegisterUserReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
token, err := authSvc.RegisterUser(spec)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
responsePayload := &authdomain.AuthResponse{
Token: token,
}
response.RespondJsonSuccess(ctx, w, responsePayload)
})
}
func RegisterStaff(
router chi.Router,
validate *validator.Validate,
authSvc authsvc.AuthIntf,
authSvc authsvc.Auth,
rdb *redis.Client,
) {
router.Post("/staff/register", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec authdomain.RegisterStaffReq
var spec staffdomain.StaffRegister
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
@ -113,7 +61,20 @@ func RegisterStaff(
)
return
}
responsePayload := &authdomain.AuthResponse{
if err := utils.StoreTokenRedis(ctx, rdb, token, spec.Email); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
responsePayload := &responsedomain.Auth{
Token: token,
}
response.RespondJsonSuccess(ctx, w, responsePayload)

View File

@ -0,0 +1,82 @@
package authhttp
import (
responsedomain "legalgo-BE-go/internal/domain/reponse"
userdomain "legalgo-BE-go/internal/domain/user"
authsvc "legalgo-BE-go/internal/services/auth"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
"github.com/redis/go-redis/v9"
)
func RegisterUser(
router chi.Router,
validate *validator.Validate,
authSvc authsvc.Auth,
rdb *redis.Client,
) {
router.Post("/user/register", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec userdomain.UserRegister
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal request",
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
token, err := authSvc.RegisterUser(spec)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
if err := utils.StoreTokenRedis(ctx, rdb, token, spec.Email); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
responsePayload := &responsedomain.Auth{
Token: token,
}
response.RespondJsonSuccess(ctx, w, responsePayload)
})
}

View File

@ -2,7 +2,7 @@ package authhttp
import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
staffdomain "legalgo-BE-go/internal/domain/staff"
authsvc "legalgo-BE-go/internal/services/auth"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
@ -13,7 +13,7 @@ import (
func UpdateStaff(
router chi.Router,
authSvc authsvc.AuthIntf,
authSvc authsvc.Auth,
) {
router.Patch("/staff/{id}/update", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
@ -31,7 +31,7 @@ func UpdateStaff(
return
}
var spec authdomain.RegisterStaffReq
var spec staffdomain.StaffRegister
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
@ -45,7 +45,7 @@ func UpdateStaff(
return
}
staff := authdomain.Staff{
staff := staffdomain.Staff{
ID: id,
Email: spec.Email,
Password: spec.Password,

View File

@ -1,6 +1,7 @@
package categoryhttp
import (
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
categorydomain "legalgo-BE-go/internal/domain/category"
categorysvc "legalgo-BE-go/internal/services/category"
"legalgo-BE-go/internal/utilities/response"
@ -16,7 +17,9 @@ func Create(
validate *validator.Validate,
categorySvc categorysvc.Category,
) {
router.Post("/category/create", func(w http.ResponseWriter, r *http.Request) {
router.
With(authmiddleware.Authorize()).
Post("/category/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec categorydomain.CategoryReq

View File

@ -14,7 +14,7 @@ func GetAll(
) {
router.Get("/category", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
subsPlan, err := categorySvc.GetAllModel()
subsPlan, err := categorySvc.GetAll()
// subsPlan, err := categorySvc.GetAll()
if err != nil {
response.ResponseWithErrorCode(

View File

@ -5,4 +5,5 @@ import "go.uber.org/fx"
var Module = fx.Module("categories", fx.Invoke(
Create,
GetAll,
Update,
))

View File

@ -0,0 +1,82 @@
package categoryhttp
import (
"fmt"
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
categorydomain "legalgo-BE-go/internal/domain/category"
categorysvc "legalgo-BE-go/internal/services/category"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-playground/validator/v10"
)
func Update(
router chi.Router,
validate *validator.Validate,
categorySvc categorysvc.Category,
) {
router.
With(authmiddleware.Authorize()).
Put("/category/{category_id}/update", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
categoryID := chi.URLParam(r, "category_id")
if categoryID == "" {
response.RespondJsonErrorWithCode(
ctx,
w,
fmt.Errorf("category id is not provided"),
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"category id is not provided",
)
return
}
var spec categorydomain.CategoryReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.RespondJsonErrorWithCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"failed to unmarshal body",
)
return
}
if err := validate.Struct(spec); err != nil {
response.RespondJsonErrorWithCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
if err := categorySvc.Update(categoryID, spec); err != nil {
response.RespondJsonErrorWithCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "update category success",
})
})
}

View File

@ -1,138 +1,76 @@
package authmiddleware
// import (
// "context"
// "fmt"
// "net/http"
// "strings"
import (
"context"
"fmt"
"net/http"
"time"
// redisaccessor "legalgo-BE-go/internal/accessor/redis"
// contextkeyenum "legalgo-BE-go/internal/enums/context_key"
// jwtclaimenum "legalgo-BE-go/internal/enums/jwt"
// resourceenum "legalgo-BE-go/internal/enums/resource"
// "legalgo-BE-go/internal/services/auth"
// "github.com/golang-jwt/jwt/v5"
// )
redisaccessor "legalgo-BE-go/internal/accessor/redis"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
// const SessionHeader = "Authorization"
"github.com/golang-jwt/jwt/v5"
)
// func Authorization() func(next http.Handler) http.Handler {
// return func(next http.Handler) http.Handler {
// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// ctx := r.Context()
const SessionHeader = "Authorization"
// tokenString, err := GetToken(r)
// if err != nil {
// RespondWithError(w, r, err, "Invalid auth header")
// return
// }
func Authorize() func(next http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
// token, err := ValidateToken(ctx, tokenString)
// if err != nil {
// RespondWithError(w, r, err, err.Error())
// return
// }
tokenString, err := utils.GetToken(r)
if err != nil {
response.RespondWithError(w, r, err, "Invalid auth header")
return
}
// if isAuthorized, ctx := VerifyClaims(ctx, token, nil); !isAuthorized {
// RespondWithError(w, r, errorcode.ErrCodeUnauthorized, errorcode.ErrCodeUnauthorized.Message)
// return
// } else {
// next.ServeHTTP(w, r.WithContext(ctx))
// return
// }
// })
// }
// }
spec, err := utils.GetTokenDetail(r)
// func GetToken(r *http.Request) (string, error) {
// tokenString := GetTokenFromHeader(r)
// if tokenString == "" {
// tokenString = getTokenFromQuery(r)
// }
token, err := ValidateToken(ctx, spec.Email)
if err != nil {
response.RespondWithError(w, r, err, err.Error())
return
}
// if tokenString == "" {
// return "", fmt.Errorf("token not found")
// }
isValid := token == tokenString
// return tokenString, nil
// }
if !isValid {
response.RespondWithError(w, r, err, "invalid token")
return
}
// func GetTokenFromHeader(r *http.Request) string {
// session := r.Header.Get(SessionHeader)
// arr := strings.Split(session, " ")
next.ServeHTTP(w, r.WithContext(ctx))
})
}
}
// if len(arr) != 2 || strings.ToUpper(arr[0]) != "BEARER" {
// return ""
// }
func ValidateToken(ctx context.Context, id string) (string, error) {
redisClient := redisaccessor.Get()
redisToken, err := utils.GetTokenRedis(ctx, redisClient, id)
// return arr[1]
// }
if err != nil {
return "", err
}
// func getTokenFromQuery(r *http.Request) string {
// token := r.URL.Query().Get("token")
// return token
// }
token, err := utils.ParseToken(redisToken)
// func VerifyClaims(ctx context.Context, token *jwt.Token,
// requiredResources []resourceenum.Resource) (bool, context.Context) {
// if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
// rawResources := []interface{}{}
// if claimValue, exist := claims[string(jwtclaimenum.RESOURCES)]; exist {
// rawResources = claimValue.([]interface{})
// }
if err != nil {
return "", fmt.Errorf("invalid token: %w", err)
}
// resources := []resourceenum.Resource{}
// resourceMap := map[string]bool{}
// Check if the token is valid
if !token.Valid {
return "", fmt.Errorf("invalid token: token is not valid")
}
// for _, v := range rawResources {
// value := v.(string)
// resources = append(resources, resourceenum.Resource(value))
// resourceMap[value] = true
// }
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
expirationTime := claims["exp"].(float64) // Expiration time in Unix timestamp format
if time.Unix(int64(expirationTime), 0).Before(time.Now()) {
return "", fmt.Errorf("token has expired")
}
}
// ctx = context.WithValue(ctx, contextkeyenum.Authorization, UserAuthorization{
// Type: claims[string(jwtclaimenum.TYPE)].(string),
// UserId: claims[string(jwtclaimenum.AUDIENCE)].(string),
// Username: claims[string(jwtclaimenum.USERNAME)].(string),
// Resources: resources,
// })
// isResourceFulfilled := false
// for _, v := range requiredResources {
// if _, ok := resourceMap[string(v)]; ok {
// isResourceFulfilled = true
// ctx = context.WithValue(ctx, contextkeyenum.Resource, v)
// break
// }
// }
// if isResourceFulfilled || len(requiredResources) == 0 {
// return true, ctx
// }
// }
// return false, nil
// }
// func ValidateToken(ctx context.Context, tokenString string) (*jwt.Token, error) {
// redisClient := redisaccessor.Get()
// redisToken, err := redisClient.Exists(ctx, fmt.Sprintf("%s:%s", auth.BLACKLISTED_TOKEN_KEY, tokenString)).Result()
// if err != nil || redisToken > 0 {
// return nil, fmt.Errorf("session already expired")
// }
// token, err := jwt.Parse(tokenString, authsvc.VerifyToken(conf.JWTAccessToken))
// if err != nil {
// if ve, ok := err.(*jwt.ValidationError); ok {
// if ve.Errors&jwt.ValidationErrorExpired != 0 {
// err = errorcode.ErrCodeExpiredToken
// }
// }
// return nil, err
// }
// return token, nil
// }
return redisToken, nil
}

View File

@ -15,7 +15,7 @@ import (
func Create(
validate *validator.Validate,
newsSvc newssvc.News,
staffRepo staffrepository.StaffIntf,
staffRepo staffrepository.Staff,
router chi.Router,
) {
router.Post("/news/create", func(w http.ResponseWriter, r *http.Request) {

View File

@ -0,0 +1,5 @@
package subscribehttp
import "go.uber.org/fx"
var Module = fx.Module("subscribe", fx.Invoke())

View File

@ -0,0 +1,77 @@
package subscribehttp
import (
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
userdomain "legalgo-BE-go/internal/domain/user"
authsvc "legalgo-BE-go/internal/services/auth"
subscribesvc "legalgo-BE-go/internal/services/subscribe"
"legalgo-BE-go/internal/utilities/response"
"legalgo-BE-go/internal/utilities/utils"
"net/http"
"github.com/go-chi/chi/v5"
)
func Update(
router chi.Router,
authSvc authsvc.Auth,
subSvc subscribesvc.Subscribe,
) {
router.
With(authmiddleware.Authorize()).
Patch("/subscribe/update", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
detail, err := utils.GetTokenDetail(r)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
if detail.Role != "user" {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrUnauthorized.Code,
response.ErrUnauthorized.HttpCode,
"unauthorized",
)
return
}
var body userdomain.UserSubsUpdate
err = utils.UnmarshalBody(r, &body)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
user, err := authSvc.GetUserProfile(detail.Email)
if err := subSvc.Update(user.ID, body); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
})
}

View File

@ -3,6 +3,7 @@ package subscribeplanhttp
import (
"net/http"
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
subscribeplansvc "legalgo-BE-go/internal/services/subscribe_plan"
"legalgo-BE-go/internal/utilities/response"
@ -15,9 +16,11 @@ import (
func CreateSubscribePlan(
router chi.Router,
validate *validator.Validate,
subsSvc subscribeplansvc.SubsPlanIntf,
subsSvc subscribeplansvc.SubscribePlan,
) {
router.Post("/subscribe-plan/create", func(w http.ResponseWriter, r *http.Request) {
router.
With(authmiddleware.Authorize()).
Post("/subscribe-plan/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec subscribeplandomain.SubscribePlanReq

View File

@ -11,7 +11,7 @@ import (
func GetAllPlan(
router chi.Router,
subsPlanSvc subscribeplansvc.SubsPlanIntf,
subsPlanSvc subscribeplansvc.SubscribePlan,
) {
router.Get("/subscribe-plan", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

View File

@ -3,6 +3,7 @@ package taghttp
import (
"net/http"
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
tagdomain "legalgo-BE-go/internal/domain/tag"
tagsvc "legalgo-BE-go/internal/services/tag"
"legalgo-BE-go/internal/utilities/response"
@ -15,9 +16,11 @@ import (
func Create(
router chi.Router,
validate *validator.Validate,
tagSvc tagsvc.TagIntf,
tagSvc tagsvc.Tag,
) {
router.Post("/tag/create", func(w http.ResponseWriter, r *http.Request) {
router.
With(authmiddleware.Authorize()).
Post("/tag/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec tagdomain.TagReq

View File

@ -10,7 +10,7 @@ import (
func GetAll(
router chi.Router,
tagSvc tagsvc.TagIntf,
tagSvc tagsvc.Tag,
) {
router.Get("/tag", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

View File

@ -1,32 +0,0 @@
package authdomain
type LoginReq struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
}
type AuthResponse struct {
Token string `json:"token"`
}
type LoginRepoResponse struct {
ID string `json:"id"`
Email string `json:"email"`
Password string `json:"password"`
Username string `json:"username"`
}
type StaffProfile struct {
ID string `json:"id"`
Email string `json:"email"`
Name string `json:"name"`
ProfilePicture string `json:"profile_picture"`
}
type UserProfile struct {
ID string `json:"id"`
Email string `json:"email"`
SubscribePlanCode string `json:"subscribe_plan_code"`
SubscribePlanName string `json:"subscribe_plan_name"`
SubscribeStatus string `json:"subscribe_status"`
}

View File

@ -1,37 +0,0 @@
package authdomain
type RegisterUserReq struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Phone string `json:"phone" validate:"required"`
SubscribePlanID string `json:"subscribe_plan_id"`
}
type User struct {
ID string `json:"id"`
Email string `json:"email"`
Password string `json:"password"`
Phone string `json:"phone"`
SubscribeID string `json:"subscribe_id"`
}
type RegisterStaffReq struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Name string `json:"name" validate:"required"`
ProfilePicture string `json:"profile_picture"`
}
type UpdateStaffReq struct {
Email string `json:"email"`
Password string `json:"password"`
Name string `json:"name"`
}
type Staff struct {
ID string `json:"id"`
Email string `json:"email"`
Password string `json:"password"`
Name string `json:"name"`
ProfilePicture string `json:"profile_picture"`
}

View File

@ -3,4 +3,5 @@ package authdomain
type AuthToken struct {
Email string
SessionID string
Role string
}

View File

@ -1,9 +1,13 @@
package categorydomain
import "time"
type Category struct {
ID string `json:"id" gorm:"primaryKey"`
ID string `json:"id"`
Name string `json:"name"`
Code string `json:"code"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type CategoryReq struct {

View File

@ -1,7 +1,7 @@
package newsdomain
import (
categorydomain "legalgo-BE-go/internal/domain/category"
"legalgo-BE-go/database"
tagdomain "legalgo-BE-go/internal/domain/tag"
"time"
)
@ -22,7 +22,7 @@ type News struct {
Content string `json:"content"`
FeaturedImage string `json:"featured_image"`
Tags []tagdomain.Tag `json:"tags"`
Categories []categorydomain.Category `json:"categories"`
Categories []database.Category `json:"categories"`
IsPremium bool `json:"is_premium"`
Slug string `json:"slug"`
AuthorID string `json:"author_id"`

View File

@ -0,0 +1,5 @@
package responsedomain
type Auth struct {
Token string `json:"token"`
}

View File

@ -0,0 +1,28 @@
package staffdomain
type Staff struct {
ID string `json:"id"`
Name string `json:"name"`
ProfilePicture string `json:"profile_picture"`
Email string `json:"email"`
Password string `json:"password"`
}
type StaffRegister struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Name string `json:"name" validate:"required"`
ProfilePicture string `json:"profile_picture"`
}
type StaffProfile struct {
ID string `json:"id"`
Name string `json:"name"`
ProfilePicture string `json:"profile_picture"`
Email string `json:"email"`
}
type StaffLogin struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
}

View File

@ -1,6 +1,28 @@
package subscribedomain
type Subscribe struct {
import (
subscribeplandm "legalgo-BE-go/internal/domain/subscribe_plan_model"
"time"
)
type SubscribeDepecrate struct {
ID string `json:"id"`
SubscribePlanID string `json:"subscribe_plan_id"`
}
type SubscribeUpdateReqDepecrate struct {
ID string `json:"id"`
Status string `json:"status"`
}
// refactored
type Subscribe struct {
ID string `gorm:"primaryKey" json:"id"`
SubscribePlanID string `gorm:"not null" json:"subscribe_plan_id"`
StartDate time.Time `gorm:"default:CURRENT_TIMESTAMP"`
EndDate time.Time `gorm:"default:null"`
Status string `gorm:"default:'inactive'"`
AutoRenew bool `gorm:"default:true"`
SubscribePlan subscribeplandm.SubscribePlan `gorm:"foreignKey:SubscribePlanID;constraint:OnDelete:CASCADE" json:"subscribe_plan"`
}

View File

@ -0,0 +1,17 @@
package subscribedm
import (
subscribeplandm "legalgo-BE-go/internal/domain/subscribe_plan_model"
"time"
)
type Subscribe struct {
ID string `json:"id"`
SubscribePlanID string `json:"subscribe_plan_id"`
StartDate time.Time `json:"start_date"`
EndDate *time.Time `json:"end_date"`
Status string `json:"status"`
AutoRenew bool `json:"auto_renew"`
SubscribePlan subscribeplandm.SubscribePlan `gorm:"foreignKey:SubscribePlanID" json:"subscribe_plan"`
}

View File

@ -0,0 +1,8 @@
package subscribeplandm
// refactored
type SubscribePlan struct {
ID string `json:"id"`
Code string `json:"code"`
Name string `json:"name"`
}

View File

@ -0,0 +1,37 @@
package userdomain
import subscribedm "legalgo-BE-go/internal/domain/subscribe_model"
type User struct {
ID string `json:"id"`
SubscribeID string `json:"subscribe_id"`
Password string `json:"password"`
Email string `json:"email"`
Phone string `json:"phone"`
Subscribe subscribedm.Subscribe `gorm:"foreignKey:SubscribeID" json:"subscribe"`
}
type UserRegister struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
Phone string `json:"phone" validate:"required"`
SubscribePlanID string `json:"subscribe_plan_id"`
}
type UserProfile struct {
ID string `json:"id"`
Email string `json:"email"`
Phone string `json:"phone"`
Subscribe subscribedm.Subscribe `gorm:"foreignKey:SubscribeID" json:"subscribe"`
}
type UserLogin struct {
Email string `json:"email" validate:"required"`
Password string `json:"password" validate:"required"`
}
type UserSubsUpdate struct {
Status string `json:"status"`
}

View File

@ -1,14 +1,16 @@
package authsvc
import authdomain "legalgo-BE-go/internal/domain/auth"
import (
staffdomain "legalgo-BE-go/internal/domain/staff"
)
func (as *AuthSvc) GetStaffProfile(email string) (*authdomain.StaffProfile, error) {
func (as *impl) GetStaffProfile(email string) (*staffdomain.StaffProfile, error) {
staff, err := as.staffRepo.GetStaffByEmail(email)
if err != nil {
return nil, err
}
profile := &authdomain.StaffProfile{
profile := &staffdomain.StaffProfile{
ID: staff.ID,
Name: staff.Name,
Email: staff.Email,

View File

@ -1,8 +1,10 @@
package authsvc
import authdomain "legalgo-BE-go/internal/domain/auth"
import (
userdomain "legalgo-BE-go/internal/domain/user"
)
func (as *AuthSvc) GetUserProfile(email string) (*authdomain.UserProfile, error) {
func (as *impl) GetUserProfile(email string) (*userdomain.UserProfile, error) {
user, err := as.userRepo.GetUserProfile(email)
if err != nil {
return nil, err

View File

@ -5,34 +5,35 @@ import (
subscriberepository "legalgo-BE-go/internal/accessor/subscribe"
subscribeplanrepository "legalgo-BE-go/internal/accessor/subscribeplan"
userrepository "legalgo-BE-go/internal/accessor/user_repository"
authdomain "legalgo-BE-go/internal/domain/auth"
staffdomain "legalgo-BE-go/internal/domain/staff"
userdomain "legalgo-BE-go/internal/domain/user"
)
type AuthSvc struct {
staffRepo staffrepository.StaffIntf
type impl struct {
staffRepo staffrepository.Staff
userRepo userrepository.UserIntf
subsRepo subscriberepository.SubsIntf
subsPlanRepo subscribeplanrepository.SubsPlanIntf
}
type AuthIntf interface {
LoginAsStaff(authdomain.LoginReq) (string, error)
RegisterUser(authdomain.RegisterUserReq) (string, error)
GetUserProfile(string) (*authdomain.UserProfile, error)
type Auth interface {
LoginAsStaff(staffdomain.StaffLogin) (string, error)
RegisterStaff(staffdomain.StaffRegister) (string, error)
GetStaffProfile(string) (*staffdomain.StaffProfile, error)
UpdateStaff(staffdomain.Staff) error
LoginAsUser(authdomain.LoginReq) (string, error)
RegisterStaff(authdomain.RegisterStaffReq) (string, error)
UpdateStaff(authdomain.Staff) error
GetStaffProfile(string) (*authdomain.StaffProfile, error)
LoginAsUser(userdomain.UserLogin) (string, error)
RegisterUser(userdomain.UserRegister) (string, error)
GetUserProfile(string) (*userdomain.UserProfile, error)
}
func New(
staffRepo staffrepository.StaffIntf,
staffRepo staffrepository.Staff,
userRepo userrepository.UserIntf,
subsRepo subscriberepository.SubsIntf,
subsPlanRepo subscribeplanrepository.SubsPlanIntf,
) AuthIntf {
return &AuthSvc{
) Auth {
return &impl{
staffRepo: staffRepo,
userRepo: userRepo,
subsRepo: subsRepo,

View File

@ -4,12 +4,13 @@ import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
staffdomain "legalgo-BE-go/internal/domain/staff"
"legalgo-BE-go/internal/utilities/utils"
"github.com/google/uuid"
)
func (sv *AuthSvc) LoginAsStaff(spec authdomain.LoginReq) (string, error) {
func (sv *impl) LoginAsStaff(spec staffdomain.StaffLogin) (string, error) {
staff, err := sv.staffRepo.GetStaffByEmail(spec.Email)
if err != nil {
return "", errors.New(err.Error())
@ -23,6 +24,7 @@ func (sv *AuthSvc) LoginAsStaff(spec authdomain.LoginReq) (string, error) {
authToken := authdomain.AuthToken{
Email: staff.Email,
SessionID: uuid.NewString(),
Role: "staff",
}
token, err := utils.GenerateToken(authToken)

View File

@ -4,12 +4,13 @@ import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
userdomain "legalgo-BE-go/internal/domain/user"
"legalgo-BE-go/internal/utilities/utils"
"github.com/google/uuid"
)
func (a *AuthSvc) LoginAsUser(spec authdomain.LoginReq) (string, error) {
func (a *impl) LoginAsUser(spec userdomain.UserLogin) (string, error) {
user, err := a.userRepo.GetUserByEmail(spec.Email)
if err != nil {
return "", errors.New(err.Error())
@ -23,6 +24,7 @@ func (a *AuthSvc) LoginAsUser(spec authdomain.LoginReq) (string, error) {
authToken := authdomain.AuthToken{
Email: user.Email,
SessionID: uuid.NewString(),
Role: "user",
}
token, err := utils.GenerateToken(authToken)

View File

@ -4,12 +4,13 @@ import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
staffdomain "legalgo-BE-go/internal/domain/staff"
"legalgo-BE-go/internal/utilities/utils"
"github.com/google/uuid"
)
func (a *AuthSvc) RegisterStaff(spec authdomain.RegisterStaffReq) (string, error) {
func (a *impl) RegisterStaff(spec staffdomain.StaffRegister) (string, error) {
_, err := a.staffRepo.GetStaffByEmail(spec.Email)
if err == nil {
return "", errors.New("this email address is already in use")
@ -19,7 +20,7 @@ func (a *AuthSvc) RegisterStaff(spec authdomain.RegisterStaffReq) (string, error
return "", err
}
staff := authdomain.Staff{
staff := staffdomain.Staff{
ID: uuid.NewString(),
Email: spec.Email,
Password: hashedPwd,
@ -27,7 +28,7 @@ func (a *AuthSvc) RegisterStaff(spec authdomain.RegisterStaffReq) (string, error
ProfilePicture: spec.ProfilePicture,
}
_, err = a.staffRepo.Create(&staff)
err = a.staffRepo.Create(staff)
if err != nil {
return "", errors.New(err.Error())
}
@ -35,6 +36,7 @@ func (a *AuthSvc) RegisterStaff(spec authdomain.RegisterStaffReq) (string, error
authToken := authdomain.AuthToken{
Email: staff.Email,
SessionID: uuid.NewString(),
Role: "staff",
}
token, err := utils.GenerateToken(authToken)

View File

@ -4,12 +4,13 @@ import (
"errors"
authdomain "legalgo-BE-go/internal/domain/auth"
userdomain "legalgo-BE-go/internal/domain/user"
"legalgo-BE-go/internal/utilities/utils"
"github.com/google/uuid"
)
func (a *AuthSvc) RegisterUser(spec authdomain.RegisterUserReq) (string, error) {
func (a *impl) RegisterUser(spec userdomain.UserRegister) (string, error) {
_, err := a.userRepo.GetUserByEmail(spec.Email)
if err == nil {
@ -40,7 +41,7 @@ func (a *AuthSvc) RegisterUser(spec authdomain.RegisterUserReq) (string, error)
return "", err
}
user := authdomain.User{
user := userdomain.User{
ID: uuid.NewString(),
Email: spec.Email,
SubscribeID: subsId,
@ -48,7 +49,7 @@ func (a *AuthSvc) RegisterUser(spec authdomain.RegisterUserReq) (string, error)
Phone: spec.Phone,
}
_, err = a.userRepo.CreateUser(&user)
err = a.userRepo.CreateUser(user)
if err != nil {
return "", errors.New(err.Error())
}
@ -56,6 +57,7 @@ func (a *AuthSvc) RegisterUser(spec authdomain.RegisterUserReq) (string, error)
authToken := authdomain.AuthToken{
Email: user.Email,
SessionID: uuid.NewString(),
Role: "user",
}
token, err := utils.GenerateToken(authToken)

View File

@ -1,8 +1,10 @@
package authsvc
import authdomain "legalgo-BE-go/internal/domain/auth"
import (
staffdomain "legalgo-BE-go/internal/domain/staff"
)
func (as *AuthSvc) UpdateStaff(spec authdomain.Staff) error {
func (as *impl) UpdateStaff(spec staffdomain.Staff) error {
if _, err := as.staffRepo.GetStaffByID(spec.ID); err != nil {
return err
}

View File

@ -1,7 +1,9 @@
package categorysvc
import categorydomain "legalgo-BE-go/internal/domain/category"
import (
categorydomain "legalgo-BE-go/internal/domain/category"
)
func (i *impl) GetAll() ([]categorydomain.Category, error) {
return i.categoryRepo.GetAll()
return i.categoryRepo.GetAllModel()
}

View File

@ -1,9 +0,0 @@
package categorysvc
import (
"legalgo-BE-go/database"
)
func (i *impl) GetAllModel() ([]database.CategoryModel, error) {
return i.categoryRepo.GetAllModel()
}

View File

@ -1,7 +1,6 @@
package categorysvc
import (
"legalgo-BE-go/database"
categoryrepository "legalgo-BE-go/internal/accessor/category"
categorydomain "legalgo-BE-go/internal/domain/category"
)
@ -13,7 +12,7 @@ type impl struct {
type Category interface {
Create(categorydomain.CategoryReq) error
GetAll() ([]categorydomain.Category, error)
GetAllModel() ([]database.CategoryModel, error)
Update(string, categorydomain.CategoryReq) error
}
func New(

View File

@ -0,0 +1,21 @@
package categorysvc
import (
categorydomain "legalgo-BE-go/internal/domain/category"
timeutils "legalgo-BE-go/internal/utilities/time_utils"
)
func (i *impl) Update(categoryID string, spec categorydomain.CategoryReq) error {
updateData := categorydomain.Category{
ID: categoryID,
Name: spec.Name,
Code: spec.Code,
UpdatedAt: timeutils.Now(),
}
if err := i.categoryRepo.Update(updateData); err != nil {
return err
}
return nil
}

View File

@ -17,7 +17,7 @@ func (i *impl) CreateModel(spec newsdomain.NewsReq, staffId string) error {
return err
}
categories, err := i.categoryRepo.GetBulks(spec.Categories)
categories, err := i.categoryRepo.GetByIDs(spec.Categories)
if err != nil {
return err
}
@ -27,7 +27,7 @@ func (i *impl) CreateModel(spec newsdomain.NewsReq, staffId string) error {
return err
}
newSpec := database.NewsModel{
newSpec := database.News{
ID: uuid.NewString(),
Title: spec.Title,
Content: spec.Content,

View File

@ -4,6 +4,6 @@ import (
"legalgo-BE-go/database"
)
func (i *impl) GetAllModel() ([]database.NewsModel, error) {
func (i *impl) GetAllModel() ([]database.News, error) {
return i.newsRepo.GetAllModel()
}

View File

@ -16,7 +16,7 @@ type impl struct {
type News interface {
GetAll() ([]newsdomain.News, error)
GetAllModel() ([]database.NewsModel, error)
GetAllModel() ([]database.News, error)
Create(newsdomain.NewsReq, string) error
CreateModel(newsdomain.NewsReq, string) error
}

View File

@ -1,6 +1,6 @@
package subscribesvc
func (s *SubsSvc) Create(subsPlanId string) (string, error) {
func (s *impl) Create(subsPlanId string) (string, error) {
subsId, err := s.subsRepo.Create(subsPlanId)
if err != nil {
return "", err

View File

@ -1,15 +1,19 @@
package subscribesvc
import subscriberepository "legalgo-BE-go/internal/accessor/subscribe"
import (
subscriberepository "legalgo-BE-go/internal/accessor/subscribe"
userdomain "legalgo-BE-go/internal/domain/user"
)
type SubsSvc struct {
type impl struct {
subsRepo subscriberepository.SubsIntf
}
type SubsIntf interface {
type Subscribe interface {
Create(string) (string, error)
Update(string, userdomain.UserSubsUpdate) error
}
func New(subsRepo subscriberepository.SubsIntf) SubsIntf {
return &SubsSvc{subsRepo}
func New(subsRepo subscriberepository.SubsIntf) Subscribe {
return &impl{subsRepo}
}

View File

@ -0,0 +1,9 @@
package subscribesvc
import (
userdomain "legalgo-BE-go/internal/domain/user"
)
func (i *impl) Update(id string, spec userdomain.UserSubsUpdate) error {
return nil
}

View File

@ -2,6 +2,6 @@ package subscribeplansvc
import subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
func (sb *SubsPlanSvc) CreatePlan(spec subscribeplandomain.SubscribePlanReq) error {
func (sb *impl) CreatePlan(spec subscribeplandomain.SubscribePlanReq) error {
return sb.subsAccs.Create(spec)
}

View File

@ -4,6 +4,6 @@ import (
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
)
func (s *SubsPlanSvc) GetAllPlan() ([]subscribeplandomain.SubscribePlan, error) {
func (s *impl) GetAllPlan() ([]subscribeplandomain.SubscribePlan, error) {
return s.subsAccs.GetAll()
}

View File

@ -5,17 +5,17 @@ import (
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
)
type SubsPlanSvc struct {
type impl struct {
subsAccs subscribeplanrepository.SubsPlanIntf
}
type SubsPlanIntf interface {
type SubscribePlan interface {
CreatePlan(subscribeplandomain.SubscribePlanReq) error
GetAllPlan() ([]subscribeplandomain.SubscribePlan, error)
}
func New(
subsAccs subscribeplanrepository.SubsPlanIntf,
) SubsPlanIntf {
return &SubsPlanSvc{subsAccs}
) SubscribePlan {
return &impl{subsAccs}
}

View File

@ -4,6 +4,6 @@ import (
"legalgo-BE-go/database"
)
func (i *impl) GetAllModel() ([]database.TagModel, error) {
func (i *impl) GetAllModel() ([]database.Tag, error) {
return i.tagRepo.GetAllModel()
}

View File

@ -10,14 +10,14 @@ type impl struct {
tagRepo tagrepository.TagAccessor
}
type TagIntf interface {
type Tag interface {
Create(tagdomain.TagReq) error
GetAll() ([]tagdomain.Tag, error)
GetAllModel() ([]database.TagModel, error)
GetAllModel() ([]database.Tag, error)
}
func New(
tagRepo tagrepository.TagAccessor,
) TagIntf {
) Tag {
return &impl{tagRepo}
}

View File

@ -15,7 +15,9 @@ func (e ErrorCode) Error() string {
var (
// 4xx
ErrBadRequest = &ErrorCode{Code: "BAD_REQUEST", Message: "BAD_REQUEST", HttpCode: http.StatusBadRequest}
ErrUnauthorized = &ErrorCode{Code: "UNAUTHORIZED", Message: "UNAUTHORIZED", HttpCode: http.StatusUnauthorized}
ErrDBRequest = &ErrorCode{Code: "BAD_DB_REQUEST", Message: "DB_ERROR", HttpCode: http.StatusBadRequest}
ErrExpiryToken = &ErrorCode{Code: "EXPIRED_TOKEN", Message: "EXPIRED_TOKEN", HttpCode: http.StatusUnauthorized}
// 5xx
ErrMarshal = &ErrorCode{Code: "FAILED_MARSHAL", Message: "FAILED_MARSHAL_BODY", HttpCode: http.StatusInternalServerError}

View File

@ -0,0 +1,23 @@
package response
import (
"context"
"encoding/json"
"net/http"
)
func RespondJsonErrorWithCode(ctx context.Context, w http.ResponseWriter,
err error, code string, statusCode int, message string) {
setDefaultHeaders(ctx, w.Header())
w.WriteHeader(statusCode)
b, _ := json.Marshal(ErrorResponse{
Error: ErrorResponseData{
Code: code,
Message: message,
},
})
w.Write(b)
}

View File

@ -0,0 +1,23 @@
package response
import (
"errors"
"net/http"
)
func RespondWithError(w http.ResponseWriter, r *http.Request, err error, msg string) {
if err != nil {
code := ErrUnauthorized.Code
status := http.StatusUnauthorized
if errors.Is(err, ErrExpiryToken) {
code = ErrExpiryToken.Code
status = ErrExpiryToken.HttpCode
}
RespondJsonErrorWithCode(r.Context(), w, err, code, status, msg)
} else {
RespondJsonErrorWithCode(r.Context(), w, nil,
ErrUnauthorized.Code, http.StatusUnauthorized, msg)
}
}

View File

@ -0,0 +1,30 @@
package utils
import (
"fmt"
"net/http"
"strings"
)
const SessionHeader = "Authorization"
func GetToken(r *http.Request) (string, error) {
token := getTokenFromHeader(r)
if token == "" {
return "", fmt.Errorf("token not found")
}
return token, nil
}
func getTokenFromHeader(r *http.Request) string {
session := r.Header.Get(SessionHeader)
arr := strings.Split(session, " ")
if len(arr) != 2 || strings.ToUpper(arr[0]) != "BEARER" {
return ""
}
return arr[1]
}

Some files were not shown because too many files have changed in this diff Show More