Compare commits

...

7 Commits

Author SHA1 Message Date
ericprd
2525eed2ea Merge branch 'main' of github.com:ardeman/project-legalgo-go 2025-03-06 11:07:04 +08:00
ericprd
85247643e6 feat: get news by slug and and author detail 2025-03-06 11:06:06 +08:00
ericprd
d217ec8a62 feat: delete news, tag, and category 2025-03-05 23:55:41 +08:00
ericprd
299fcf949b feat: update and delete tags and categories 2025-03-05 23:13:24 +08:00
ericprd
5c699dfa53 fix: create and get news 2025-03-05 22:15:39 +08:00
ericprd
dd109c8aa0 chores: remove unused code 2025-03-05 21:27:37 +08:00
ericprd
567e0e32ca chores: refactor struct and structure project 2025-03-05 21:21:44 +08:00
132 changed files with 1585 additions and 869 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

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

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
bin
.env
.DS_STORE

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

@ -6,16 +6,11 @@ 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"`
Code string `gorm:"not null;unique" 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"`
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"`
News []News `gorm:"many2many:news_categories" json:"news"`
}

View File

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

View File

@ -6,30 +6,18 @@ 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"`
Title string `json:"title"`
Content string `json:"content"`
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"`
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"`
AuthorID string `gorm:"not null" json:"author_id"`
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"`
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"`
IsPremium bool `gorm:"default:false" json:"is_premium"`
Slug string `gorm:"default:null" json:"slug"`
FeaturedImage string `gorm:"default:null" json:"featured_image"`
AuthorID string `gorm:"not null" json:"author_id"`
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"`
Author Staff `gorm:"foreignKey:AuthorID" json:"author"`
}

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

@ -6,16 +6,11 @@ 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"`
Code string `gorm:"not null;unique" 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"`
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"`
News []News `gorm:"many2many:news_tags" json:"news"`
}

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

@ -48,6 +48,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

@ -31,6 +31,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/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=

View File

@ -1,19 +1,20 @@
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,
}
if err := a.DB.Create(&data).Error; err != nil {
if err := a.db.Create(&data).Error; err != nil {
return err
}

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

@ -0,0 +1,24 @@
package categoryrepository
import (
"fmt"
"legalgo-BE-go/database"
)
func (a *accessor) Delete(id string) error {
var category database.Category
if err := a.db.First(&category, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to find category: %v", err)
}
if err := a.db.Model(&category).Association("News").Clear(); err != nil {
return fmt.Errorf("failed to remove categories association: %v", err)
}
if err := a.db.Delete(&category).Error; err != nil {
return fmt.Errorf("failed to delete category %s : %v", id, err)
}
return nil
}

View File

@ -1,11 +1,13 @@
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 {
if err := a.db.Find(&categories).Error; err != nil {
return nil, err
}

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,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

@ -7,7 +7,7 @@ import (
func (a *accessor) GetByIDs(ids []string) ([]categorydomain.Category, error) {
var categories []categorydomain.Category
if err := a.DB.Find(&categories, "id IN ?", ids).Error; err != nil {
if err := a.db.Find(&categories, "id IN ?", ids).Error; err != nil {
return nil, err
}

View File

@ -6,18 +6,15 @@ import (
)
type accessor struct {
DB *database.DB
db *database.DB
}
type Category interface {
Create(categorydomain.CategoryReq) error
CreateModel(categorydomain.CategoryReq) error
GetAll() ([]categorydomain.Category, error)
GetAllModel() ([]database.CategoryModel, error)
GetAllModel() ([]categorydomain.Category, error)
GetByIDs([]string) ([]categorydomain.Category, error)
GetBulks([]string) ([]database.CategoryModel, error)
CreateModel(categorydomain.CategoryReq) error
Update(categorydomain.Category) error
Delete(string) 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"}),
}).Select("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 (
newsdomain "legalgo-BE-go/internal/domain/news"
)
func (a *accessor) Create(spec *newsdomain.News) error {
func (a *accessor) Create(spec newsdomain.News) error {
if err := a.db.Create(&spec).Error; err != nil {
return fmt.Errorf("failed to create news: %w", err)
}

View File

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

View File

@ -0,0 +1,28 @@
package newsrepository
import (
"fmt"
newsdomain "legalgo-BE-go/internal/domain/news"
)
func (a *accessor) Delete(id string) error {
var news newsdomain.News
if err := a.db.Preload("Categories").Preload("Tags").First(&news, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to find news: %v", err)
}
if err := a.db.Model(&news).Association("Categories").Clear(); err != nil {
return fmt.Errorf("failed to remove categories association: %v", err)
}
if err := a.db.Model(&news).Association("Tags").Clear(); err != nil {
return fmt.Errorf("failed to remove tags association: %v", err)
}
if err := a.db.Delete(&news, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to delete news %s : %v", id, err)
}
return nil
}

View File

@ -5,7 +5,11 @@ import newsdomain "legalgo-BE-go/internal/domain/news"
func (a *accessor) GetAll() ([]newsdomain.News, error) {
var news []newsdomain.News
if err := a.db.Preload("Tags").Preload("Categories").Find(&news).Error; err != nil {
if err := a.db.
Preload("Tags").
Preload("Categories").
Preload("Author").
Find(&news).Error; err != nil {
return nil, err
}

View File

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

View File

@ -0,0 +1,17 @@
package newsrepository
import newsdomain "legalgo-BE-go/internal/domain/news"
func (a *accessor) GetBySlug(slug string) (*newsdomain.News, error) {
var news newsdomain.News
if err := a.db.
Preload("Tags").
Preload("Categories").
Preload("Author").
First(&news, "slug = ?", slug).Error; err != nil {
return nil, err
}
return &news, nil
}

View File

@ -11,9 +11,9 @@ type accessor struct {
type News interface {
GetAll() ([]newsdomain.News, error)
GetAllModel() ([]database.NewsModel, error)
Create(*newsdomain.News) error
CreateModel(database.NewsModel) error
GetBySlug(string) (*newsdomain.News, error)
Create(newsdomain.News) error
Delete(string) 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

@ -13,7 +13,7 @@ func (acc *accessor) Create(spec tagdomain.TagReq) error {
Name: spec.Name,
}
if err := acc.DB.Create(&data).Error; err != nil {
if err := acc.db.Create(&data).Error; err != nil {
return err
}

View File

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

View File

@ -0,0 +1,24 @@
package tagrepository
import (
"fmt"
"legalgo-BE-go/database"
)
func (a *accessor) Delete(id string) error {
var tag database.Tag
if err := a.db.First(&tag, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to find tag: %v", err)
}
if err := a.db.Model(&tag).Association("News").Clear(); err != nil {
return fmt.Errorf("failed to remove tag association: %v", err)
}
if err := a.db.Delete(&tag).Error; err != nil {
return fmt.Errorf("failed to delete tag %s : %v", id, err)
}
return nil
}

View File

@ -7,7 +7,7 @@ import (
func (acc *accessor) GetAll() ([]tagdomain.Tag, error) {
var tags []tagdomain.Tag
if err := acc.DB.Find(&tags).Error; err != nil {
if err := acc.db.Find(&tags).Error; err != nil {
return nil, err
}

View File

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

View File

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

View File

@ -5,7 +5,7 @@ import tagdomain "legalgo-BE-go/internal/domain/tag"
func (a *accessor) GetByIDs(ids []string) ([]tagdomain.Tag, error) {
var tags []tagdomain.Tag
if err := a.DB.Find(&tags, "id IN ?", ids).Error; err != nil {
if err := a.db.Find(&tags, "id IN ?", ids).Error; err != nil {
return nil, err
}

View File

@ -6,16 +6,15 @@ import (
)
type accessor struct {
DB *database.DB
db *database.DB
}
type TagAccessor interface {
Create(tagdomain.TagReq) error
CreateModel(tagdomain.TagReq) error
GetAll() ([]tagdomain.Tag, error)
GetAllModel() ([]database.TagModel, error)
GetByIDs([]string) ([]tagdomain.Tag, error)
GetBulks(ids []string) ([]database.TagModel, error)
Update(tagdomain.Tag) error
Delete(string) error
}
func New(

View File

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

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,52 +17,54 @@ func Create(
validate *validator.Validate,
categorySvc categorysvc.Category,
) {
router.Post("/category/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
router.
With(authmiddleware.Authorize()).
Post("/category/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec categorydomain.CategoryReq
var spec categorydomain.CategoryReq
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
if err := utils.UnmarshalBody(r, &spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
if err := categorySvc.Create(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrCreateEntity.Code,
response.ErrCreateEntity.HttpCode,
err.Error(),
)
return
}
if err := categorySvc.Create(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrCreateEntity.Code,
response.ErrCreateEntity.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "category created successfully",
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "category created successfully",
})
})
})
}

View File

@ -0,0 +1,53 @@
package categoryhttp
import (
"fmt"
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
categorysvc "legalgo-BE-go/internal/services/category"
"legalgo-BE-go/internal/utilities/response"
"net/http"
"github.com/go-chi/chi/v5"
)
func Delete(
router chi.Router,
categorySvc categorysvc.Category,
) {
router.
With(authmiddleware.Authorize()).
Delete("/category/{category_id}/delete", 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
}
if err := categorySvc.Delete(categoryID); err != nil {
response.RespondJsonErrorWithCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "category has been deleted",
})
})
}

View File

@ -14,8 +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(
ctx,

View File

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

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,5 +0,0 @@
package contenthttp
import "go.uber.org/fx"
var Module = fx.Module("content-api", fx.Invoke())

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) {
@ -72,7 +72,7 @@ func Create(
return
}
if err := newsSvc.CreateModel(spec, staffProfile.ID); err != nil {
if err := newsSvc.Create(spec, staffProfile.ID); err != nil {
response.ResponseWithErrorCode(
ctx,
w,

View File

@ -0,0 +1,53 @@
package newshttp
import (
"fmt"
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
newssvc "legalgo-BE-go/internal/services/news"
"legalgo-BE-go/internal/utilities/response"
"net/http"
"github.com/go-chi/chi/v5"
)
func Delete(
router chi.Router,
newsSvc newssvc.News,
) {
router.
With(authmiddleware.Authorize()).
Delete("/news/{news_id}/delete", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
newsID := chi.URLParam(r, "news_id")
if newsID == "" {
response.RespondJsonErrorWithCode(
ctx,
w,
fmt.Errorf("category id is not provided"),
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"news id is not provided",
)
return
}
if err := newsSvc.Delete(newsID); err != nil {
response.RespondJsonErrorWithCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "news has been deleted",
})
})
}

View File

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

View File

@ -0,0 +1,34 @@
package newshttp
import (
newssvc "legalgo-BE-go/internal/services/news"
"legalgo-BE-go/internal/utilities/response"
"net/http"
"github.com/go-chi/chi/v5"
)
func GetBySlug(
router chi.Router,
newsSvc newssvc.News,
) {
router.Get("/news/{slug}", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
slug := chi.URLParam(r, "slug")
news, err := newsSvc.GetBySlug(slug)
if err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, news)
})
}

View File

@ -4,5 +4,7 @@ import "go.uber.org/fx"
var Module = fx.Module("news", fx.Invoke(
GetAll,
GetBySlug,
Create,
Delete,
))

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,53 +16,55 @@ 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) {
ctx := r.Context()
router.
With(authmiddleware.Authorize()).
Post("/subscribe-plan/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec subscribeplandomain.SubscribePlanReq
var spec subscribeplandomain.SubscribePlanReq
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 := 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
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
if err := subsSvc.CreatePlan(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrCreateEntity.Code,
response.ErrCreateEntity.HttpCode,
err.Error(),
)
return
}
if err := subsSvc.CreatePlan(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrCreateEntity.Code,
response.ErrCreateEntity.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "subscription plan created successfully.",
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "subscription plan created successfully.",
})
})
})
}

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,53 +16,55 @@ 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) {
ctx := r.Context()
router.
With(authmiddleware.Authorize()).
Post("/tag/create", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var spec tagdomain.TagReq
var spec tagdomain.TagReq
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 := 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
}
if err := validate.Struct(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.(validator.ValidationErrors).Error(),
)
return
}
if err := tagSvc.Create(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrCreateEntity.Code,
response.ErrCreateEntity.HttpCode,
err.Error(),
)
return
}
if err := tagSvc.Create(spec); err != nil {
response.ResponseWithErrorCode(
ctx,
w,
err,
response.ErrCreateEntity.Code,
response.ErrCreateEntity.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "tag created successfully.",
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "tag created successfully.",
})
})
})
}

View File

@ -0,0 +1,53 @@
package taghttp
import (
"fmt"
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
tagsvc "legalgo-BE-go/internal/services/tag"
"legalgo-BE-go/internal/utilities/response"
"net/http"
"github.com/go-chi/chi/v5"
)
func Delete(
router chi.Router,
tagSvc tagsvc.Tag,
) {
router.
With(authmiddleware.Authorize()).
Delete("/tag/{category_id}/delete", 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
}
if err := tagSvc.Delete(categoryID); err != nil {
response.RespondJsonErrorWithCode(
ctx,
w,
err,
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
err.Error(),
)
return
}
response.RespondJsonSuccess(ctx, w, struct {
Message string
}{
Message: "tag has been deleted",
})
})
}

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

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

View File

@ -0,0 +1,82 @@
package taghttp
import (
"fmt"
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"
"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,
tagSvc tagsvc.Tag,
) {
router.
With(authmiddleware.Authorize()).
Put("/tag/{tag_id}/update", func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
tagID := chi.URLParam(r, "tag_id")
if tagID == "" {
response.RespondJsonErrorWithCode(
ctx,
w,
fmt.Errorf("tag id is not provided"),
response.ErrBadRequest.Code,
response.ErrBadRequest.HttpCode,
"tag id is not provided",
)
return
}
var spec tagdomain.TagReq
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 := tagSvc.Update(tagID, 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 tag success",
})
})
}

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,15 @@
package categorydomain
import (
"time"
)
type Category struct {
ID string `json:"id" gorm:"primaryKey"`
Name string `json:"name"`
Code string `json:"code"`
ID string `json:"id" gorm:"primaryKey"`
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

@ -16,17 +16,25 @@ type NewsReq struct {
LiveAt string `json:"live_at" validate:"required"`
}
type Staff struct {
ID string `json:"id"`
Name string `json:"name"`
ProfilePicture string `json:"profile_picture"`
}
type News struct {
ID string `json:"id"`
ID string `json:"id" gorm:"primaryKey"`
Title string `json:"title"`
Content string `json:"content"`
FeaturedImage string `json:"featured_image"`
Tags []tagdomain.Tag `json:"tags"`
Categories []categorydomain.Category `json:"categories"`
Tags []tagdomain.Tag `gorm:"many2many:news_tags" json:"tags"`
Categories []categorydomain.Category `gorm:"many2many:news_categories" json:"categories"`
IsPremium bool `json:"is_premium"`
Slug string `json:"slug"`
AuthorID string `json:"author_id"`
LiveAt time.Time `json:"live_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Author Staff `json:"author"`
}

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

@ -1,12 +1,16 @@
package tagdomain
import "time"
type TagReq struct {
Code string `json:"code" validate:"required"`
Name string `json:"name" validate:"required"`
}
type Tag struct {
ID string `json:"id" gorm:"primaryKey"`
Code string `json:"code"`
Name string `json:"name"`
ID string `json:"id" gorm:"primaryKey"`
Code string `json:"code"`
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}

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)

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