Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c48a4b944b | ||
|
|
c410e651ce | ||
|
|
51b50a3132 | ||
|
|
e3a9b67e28 | ||
|
|
2046021e01 | ||
|
|
a2a6fe6374 | ||
|
|
d6a680634c | ||
|
|
cf410bdf05 | ||
|
|
efc87ee63e | ||
|
|
c037da4879 | ||
|
|
53fda59e3c | ||
|
|
2525eed2ea | ||
|
|
85247643e6 | ||
|
|
d217ec8a62 | ||
|
|
299fcf949b | ||
|
|
5c699dfa53 | ||
|
|
dd109c8aa0 | ||
|
|
567e0e32ca | ||
|
|
2b54a9343b | ||
|
|
43d5608a51 | ||
|
|
883ff8b7d1 | ||
|
|
750a4dc3db | ||
|
|
13a8481f22 | ||
|
|
642566c8b2 | ||
|
|
afe6f4e9a6 | ||
|
|
20c9660c3a |
@@ -14,3 +14,4 @@ REDIS_PORT=
|
|||||||
REDIS_PASSWORD=
|
REDIS_PASSWORD=
|
||||||
REDIS_TTL=
|
REDIS_TTL=
|
||||||
REDIS_DB=
|
REDIS_DB=
|
||||||
|
REDIS_TIMEOUT=
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
bin
|
bin
|
||||||
.env
|
.env
|
||||||
|
.DS_Store
|
||||||
|
/cmd/legalgo/env
|
||||||
|
|||||||
@@ -148,6 +148,12 @@ make run
|
|||||||
|
|
||||||
This command will compile and execute your Go application.
|
This command will compile and execute your Go application.
|
||||||
|
|
||||||
|
Or you can execute the compiled binary at `bin/legalgo` by:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./bin/legalgo
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Note:** Ensure that your `Makefile` is correctly set up to handle these commands. If not, you may need to create
|
**Note:** Ensure that your `Makefile` is correctly set up to handle these commands. If not, you may need to create
|
||||||
|
|||||||
+12
-1
@@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -32,16 +33,26 @@ func init() {
|
|||||||
config.InitEnv()
|
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{
|
lc.Append(fx.Hook{
|
||||||
OnStart: func(ctx context.Context) error {
|
OnStart: func(ctx context.Context) error {
|
||||||
fmt.Println("Application has started...")
|
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)
|
pkgconfig.Router(apiRouter)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
OnStop: func(ctx context.Context) error {
|
OnStop: func(ctx context.Context) error {
|
||||||
fmt.Println("Shutting down...")
|
fmt.Println("Shutting down...")
|
||||||
|
rdb.Close()
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
+14
-1
@@ -1,7 +1,11 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
APP_PORT int
|
APP_PORT,
|
||||||
|
REDIS_DB,
|
||||||
|
REDIS_TIMEOUT,
|
||||||
GRACEFULL_TIMEOUT int
|
GRACEFULL_TIMEOUT int
|
||||||
|
|
||||||
// DB
|
// DB
|
||||||
@@ -10,6 +14,9 @@ var (
|
|||||||
DB_PASSWORD,
|
DB_PASSWORD,
|
||||||
DB_NAME,
|
DB_NAME,
|
||||||
DB_PORT,
|
DB_PORT,
|
||||||
|
REDIS_PASSWORD,
|
||||||
|
REDIS_ADDR,
|
||||||
|
REDIS_USERNAME,
|
||||||
SALT_SECURITY string
|
SALT_SECURITY string
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -24,4 +31,10 @@ func InitEnv() {
|
|||||||
|
|
||||||
APP_PORT = GetOrDefault("APP_PORT", 3000)
|
APP_PORT = GetOrDefault("APP_PORT", 3000)
|
||||||
GRACEFULL_TIMEOUT = GetOrDefault("GRACEFULL_TIMEOUT", 10)
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ type Config struct {
|
|||||||
Database Database `mapstructure:"postgresql"`
|
Database Database `mapstructure:"postgresql"`
|
||||||
Jwt Jwt `mapstructure:"jwt"`
|
Jwt Jwt `mapstructure:"jwt"`
|
||||||
OSSConfig OSSConfig `mapstructure:"oss"`
|
OSSConfig OSSConfig `mapstructure:"oss"`
|
||||||
|
Redis Redis `mapstructure:"redis"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
type Redis struct {
|
||||||
|
Host string `mapstructure:"host"`
|
||||||
|
Port string `mapstructure:"port"`
|
||||||
|
DB int `mapstructure:"db"`
|
||||||
|
Username string `mapstructure:"username"`
|
||||||
|
Password string `mapstructure:"password"`
|
||||||
|
SslMode string `mapstructure:"ssl-mode"`
|
||||||
|
Debug bool `mapstructure:"debug"`
|
||||||
|
MaxIdleConnectionsInSecond int `mapstructure:"max-idle-connections-in-second"`
|
||||||
|
MaxOpenConnectionsInSecond int `mapstructure:"max-open-connections-in-second"`
|
||||||
|
ConnectionMaxLifetimeInSecond int64 `mapstructure:"connection-max-life-time-in-second"`
|
||||||
|
}
|
||||||
@@ -6,16 +6,11 @@ import (
|
|||||||
|
|
||||||
type Category struct {
|
type Category struct {
|
||||||
ID string `gorm:"primaryKey" json:"id"`
|
ID string `gorm:"primaryKey" json:"id"`
|
||||||
Code string `gorm:"not null;unique" json:"code"`
|
|
||||||
Name string `gorm:"not null" json:"name"`
|
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"`
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
||||||
}
|
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
|
||||||
|
|
||||||
type CategoryModel struct {
|
News []News `gorm:"many2many:news_categories" json:"news"`
|
||||||
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"`
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -58,8 +58,8 @@ func (db *DB) Migrate() error {
|
|||||||
// &Tag{},
|
// &Tag{},
|
||||||
// &Category{},
|
// &Category{},
|
||||||
// &News{},
|
// &News{},
|
||||||
&NewsModel{},
|
&News{},
|
||||||
&TagModel{},
|
&Tag{},
|
||||||
&CategoryModel{},
|
&Category{},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-17
@@ -5,26 +5,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type News struct {
|
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"`
|
ID string `gorm:"primaryKey" json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
Categories []CategoryModel `gorm:"many2many:news_categories" json:"categories"`
|
Categories []Category `gorm:"many2many:news_categories" json:"categories"`
|
||||||
Tags []TagModel `gorm:"many2many:news_tags" json:"tags"`
|
Tags []Tag `gorm:"many2many:news_tags" json:"tags"`
|
||||||
IsPremium bool `gorm:"default:false" json:"is_premium"`
|
IsPremium bool `gorm:"default:false" json:"is_premium"`
|
||||||
Slug string `gorm:"default:null" json:"slug"`
|
Slug string `gorm:"default:null" json:"slug"`
|
||||||
FeaturedImage string `gorm:"default:null" json:"featured_image"`
|
FeaturedImage string `gorm:"default:null" json:"featured_image"`
|
||||||
@@ -32,4 +17,7 @@ type NewsModel struct {
|
|||||||
LiveAt time.Time `gorm:"not null" json:"live_at"`
|
LiveAt time.Time `gorm:"not null" json:"live_at"`
|
||||||
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
||||||
|
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
|
||||||
|
|
||||||
|
Author Staff `gorm:"foreignKey:AuthorID" json:"author"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,11 @@ import (
|
|||||||
|
|
||||||
type Staff struct {
|
type Staff struct {
|
||||||
ID string `gorm:"primaryKey" json:"id"`
|
ID string `gorm:"primaryKey" json:"id"`
|
||||||
Username string `gorm:"default:null;unique" json:"username"`
|
Name string `gorm:"default:null" json:"name"`
|
||||||
|
ProfilePicture string `gorm:"default:null" json:"profile_picture"`
|
||||||
Email string `gorm:"unique;not null" json:"email"`
|
Email string `gorm:"unique;not null" json:"email"`
|
||||||
Password string `gorm:"not null" json:"password"`
|
Password string `gorm:"not null" json:"password"`
|
||||||
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
||||||
|
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ type Subscribe struct {
|
|||||||
AutoRenew bool `gorm:"default:true"`
|
AutoRenew bool `gorm:"default:true"`
|
||||||
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP"`
|
||||||
UpdatedAt 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 {
|
type SubscribePlan struct {
|
||||||
|
|||||||
@@ -6,16 +6,11 @@ import (
|
|||||||
|
|
||||||
type Tag struct {
|
type Tag struct {
|
||||||
ID string `gorm:"primaryKey" json:"id"`
|
ID string `gorm:"primaryKey" json:"id"`
|
||||||
Code string `gorm:"not null;unique" json:"code"`
|
|
||||||
Name string `gorm:"not null" json:"name"`
|
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"`
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_at"`
|
||||||
}
|
DeletedAt time.Time `gorm:"default:null" json:"deleted_at"`
|
||||||
|
|
||||||
type TagModel struct {
|
News []News `gorm:"many2many:news_tags" json:"news"`
|
||||||
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"`
|
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@ type User struct {
|
|||||||
Phone string `gorm:"default:not null;unique" json:"phone"`
|
Phone string `gorm:"default:not null;unique" json:"phone"`
|
||||||
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
CreatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"default:CURRENT_TIMESTAMP" json:"updated_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"`
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+12
-1
@@ -14,7 +14,7 @@ postgresql:
|
|||||||
driver: postgres
|
driver: postgres
|
||||||
db: legalgonews-dev
|
db: legalgonews-dev
|
||||||
username: legalgo_admin
|
username: legalgo_admin
|
||||||
password: 'K4K!2Kg7c@KW6H&4A2aBy2dFCRY3Sh'
|
password: "K4K!2Kg7c@KW6H&4A2aBy2dFCRY3Sh"
|
||||||
ssl-mode: disable
|
ssl-mode: disable
|
||||||
max-idle-connections-in-second: 600
|
max-idle-connections-in-second: 600
|
||||||
max-open-connections-in-second: 600
|
max-open-connections-in-second: 600
|
||||||
@@ -29,3 +29,14 @@ oss:
|
|||||||
log_level: Error
|
log_level: Error
|
||||||
host_url: https://sin1.contabostorage.com
|
host_url: https://sin1.contabostorage.com
|
||||||
public_url: https://sin1.contabostorage.com/fda98c2228f246f29a7e466b86b3b9e7
|
public_url: https://sin1.contabostorage.com/fda98c2228f246f29a7e466b86b3b9e7
|
||||||
|
|
||||||
|
redis:
|
||||||
|
host: 62.72.45.250
|
||||||
|
port: 26379
|
||||||
|
password: mDtpsyEW8W26vwLhglpO
|
||||||
|
db: 5
|
||||||
|
ssl: false
|
||||||
|
max-idle-connections-in-second: 600
|
||||||
|
max-open-connections-in-second: 600
|
||||||
|
connection-max-life-time-in-second: 600
|
||||||
|
debug: false
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
package categoryrepository
|
package categoryrepository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"legalgo-BE-go/database"
|
||||||
categorydomain "legalgo-BE-go/internal/domain/category"
|
categorydomain "legalgo-BE-go/internal/domain/category"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (a *accessor) Create(spec categorydomain.CategoryReq) error {
|
func (a *accessor) CreateModel(spec categorydomain.CategoryReq) error {
|
||||||
data := categorydomain.Category{
|
data := database.Category{
|
||||||
ID: uuid.NewString(),
|
ID: uuid.NewString(),
|
||||||
Name: spec.Name,
|
Name: spec.Name,
|
||||||
Code: spec.Code,
|
Code: spec.Code,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := a.DB.Create(&data).Error; err != nil {
|
if err := a.db.Create(&data).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -1,11 +1,13 @@
|
|||||||
package categoryrepository
|
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
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package categoryrepository
|
||||||
|
|
||||||
|
import (
|
||||||
|
categorydomain "legalgo-BE-go/internal/domain/category"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *accessor) GetIDByCode(codes []string) ([]string, error) {
|
||||||
|
var categories []string
|
||||||
|
|
||||||
|
if err := a.db.
|
||||||
|
Model(&categorydomain.Category{}).
|
||||||
|
Select("id").Where("code IN ?", codes).
|
||||||
|
Pluck("id", &categories).
|
||||||
|
Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return categories, nil
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
func (a *accessor) GetByIDs(ids []string) ([]categorydomain.Category, error) {
|
func (a *accessor) GetByIDs(ids []string) ([]categorydomain.Category, error) {
|
||||||
var categories []categorydomain.Category
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6,18 +6,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type accessor struct {
|
type accessor struct {
|
||||||
DB *database.DB
|
db *database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type Category interface {
|
type Category interface {
|
||||||
Create(categorydomain.CategoryReq) error
|
GetAllModel() ([]categorydomain.Category, error)
|
||||||
CreateModel(categorydomain.CategoryReq) error
|
|
||||||
|
|
||||||
GetAll() ([]categorydomain.Category, error)
|
|
||||||
GetAllModel() ([]database.CategoryModel, error)
|
|
||||||
|
|
||||||
GetByIDs([]string) ([]categorydomain.Category, error)
|
GetByIDs([]string) ([]categorydomain.Category, error)
|
||||||
GetBulks([]string) ([]database.CategoryModel, error)
|
GetIDByCode([]string) ([]string, error)
|
||||||
|
CreateModel(categorydomain.CategoryReq) error
|
||||||
|
Update(categorydomain.Category) error
|
||||||
|
Delete(string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
newsdomain "legalgo-BE-go/internal/domain/news"
|
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 {
|
if err := a.db.Create(&spec).Error; err != nil {
|
||||||
return fmt.Errorf("failed to create news: %w", err)
|
return fmt.Errorf("failed to create news: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -2,10 +2,25 @@ package newsrepository
|
|||||||
|
|
||||||
import newsdomain "legalgo-BE-go/internal/domain/news"
|
import newsdomain "legalgo-BE-go/internal/domain/news"
|
||||||
|
|
||||||
func (a *accessor) GetAll() ([]newsdomain.News, error) {
|
func (a *accessor) GetAll(filter newsdomain.NewsFilter) ([]newsdomain.News, error) {
|
||||||
var news []newsdomain.News
|
var news []newsdomain.News
|
||||||
|
query := a.db.
|
||||||
|
Preload("Tags").
|
||||||
|
Preload("Categories").
|
||||||
|
Preload("Author")
|
||||||
|
|
||||||
if err := a.db.Preload("Tags").Preload("Categories").Find(&news).Error; err != nil {
|
if len(filter.Category) > 0 {
|
||||||
|
query = query.Joins("JOIN news_categories nc ON nc.news_id = news.id").
|
||||||
|
Where("nc.category_id IN (?)", filter.Category)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(filter.Tags) > 0 {
|
||||||
|
query = query.Joins("JOIN news_tags nt ON nt.news_id = news.id").
|
||||||
|
Where("nt.tag_id IN (?)", filter.Tags)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := query.
|
||||||
|
Find(&news).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -10,10 +10,11 @@ type accessor struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type News interface {
|
type News interface {
|
||||||
GetAll() ([]newsdomain.News, error)
|
GetAll(filter newsdomain.NewsFilter) ([]newsdomain.News, error)
|
||||||
GetAllModel() ([]database.NewsModel, error)
|
GetBySlug(string) (*newsdomain.News, error)
|
||||||
Create(*newsdomain.News) error
|
Create(newsdomain.News) error
|
||||||
CreateModel(database.NewsModel) error
|
Update(newsdomain.News) error
|
||||||
|
Delete(string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(db *database.DB) News {
|
func New(db *database.DB) News {
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package newsrepository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
categorydomain "legalgo-BE-go/internal/domain/category"
|
||||||
|
newsdomain "legalgo-BE-go/internal/domain/news"
|
||||||
|
tagdomain "legalgo-BE-go/internal/domain/tag"
|
||||||
|
|
||||||
|
"gorm.io/gorm/clause"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *accessor) Update(spec newsdomain.News) error {
|
||||||
|
tx := a.db.Begin()
|
||||||
|
if err := tx.Clauses(clause.OnConflict{
|
||||||
|
Columns: []clause.Column{{Name: "id"}},
|
||||||
|
DoUpdates: clause.AssignmentColumns([]string{
|
||||||
|
"title",
|
||||||
|
"content",
|
||||||
|
"featured_image",
|
||||||
|
"is_premium",
|
||||||
|
"slug",
|
||||||
|
"author_id",
|
||||||
|
"live_at",
|
||||||
|
"updated_at",
|
||||||
|
}),
|
||||||
|
}).Select(
|
||||||
|
"title",
|
||||||
|
"content",
|
||||||
|
"featured_image",
|
||||||
|
"is_premium",
|
||||||
|
"slug",
|
||||||
|
"author_id",
|
||||||
|
"live_at",
|
||||||
|
"updated_at",
|
||||||
|
).Save(&spec).Error; err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("failed to update news: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tagsDeleted := make([]tagdomain.Tag, len(spec.Tags))
|
||||||
|
copy(tagsDeleted, spec.Tags)
|
||||||
|
if err := tx.Model(&spec).Association("Tags").Clear(); err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("failed to remove previous tags: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&spec).Association("Tags").Append(tagsDeleted); err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("failed to add tags: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
categoriesDeleted := make([]categorydomain.Category, len(spec.Categories))
|
||||||
|
copy(categoriesDeleted, spec.Categories)
|
||||||
|
if err := tx.Model(&spec).Association("Categories").Clear(); err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("failed to remove previous categories: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Model(&spec).Association("Categories").Append(categoriesDeleted); err != nil {
|
||||||
|
tx.Rollback()
|
||||||
|
return fmt.Errorf("failed to add categories: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tx.Commit().Error; err != nil {
|
||||||
|
return fmt.Errorf("failed to commit transaction: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package redisaccessor
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"legalgo-BE-go/config"
|
||||||
|
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
@@ -13,19 +13,13 @@ func Get() *redis.Client {
|
|||||||
return redisClient
|
return redisClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() *redis.Client {
|
func New(cfg *config.Config) *redis.Client {
|
||||||
var (
|
addr := fmt.Sprintf("%s:%s", cfg.Redis.Host, cfg.Redis.Port)
|
||||||
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{
|
redisClient = redis.NewClient(&redis.Options{
|
||||||
Username: username,
|
|
||||||
Addr: addr,
|
Addr: addr,
|
||||||
Password: password,
|
Password: cfg.Redis.Password,
|
||||||
DB: db,
|
DB: cfg.Redis.DB,
|
||||||
})
|
})
|
||||||
|
|
||||||
return redisClient
|
return redisClient
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package staffrepository
|
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) {
|
func (ur *impl) Create(spec staffdomain.Staff) error {
|
||||||
if err := ur.DB.Create(&spec).Error; err != nil {
|
if err := ur.db.Create(&spec).Error; err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return spec, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,19 @@ package staffrepository
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
authdomain "legalgo-BE-go/internal/domain/auth"
|
staffdomain "legalgo-BE-go/internal/domain/staff"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (sr *StaffRepository) GetStaffByEmail(email string) (*authdomain.Staff, error) {
|
func (sr *impl) GetStaffByEmail(email string) (*staffdomain.Staff, error) {
|
||||||
var staff authdomain.Staff
|
var staff staffdomain.Staff
|
||||||
|
|
||||||
if email == "" {
|
if email == "" {
|
||||||
return nil, errors.New("email is required")
|
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) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, errors.New("staff not found")
|
return nil, errors.New("staff not found")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,19 +2,19 @@ package staffrepository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
authdomain "legalgo-BE-go/internal/domain/auth"
|
staffdomain "legalgo-BE-go/internal/domain/staff"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (sr *StaffRepository) GetStaffByID(ID string) (*authdomain.Staff, error) {
|
func (sr *impl) GetStaffByID(ID string) (*staffdomain.Staff, error) {
|
||||||
var staff authdomain.Staff
|
var staff staffdomain.Staff
|
||||||
|
|
||||||
if ID == "" {
|
if ID == "" {
|
||||||
return nil, errors.New("id is required")
|
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) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, errors.New("staff not found")
|
return nil, errors.New("staff not found")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,20 @@ package staffrepository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"legalgo-BE-go/database"
|
"legalgo-BE-go/database"
|
||||||
authdomain "legalgo-BE-go/internal/domain/auth"
|
staffdomain "legalgo-BE-go/internal/domain/staff"
|
||||||
)
|
)
|
||||||
|
|
||||||
type StaffRepository struct {
|
type impl struct {
|
||||||
DB *database.DB
|
db *database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type StaffIntf interface {
|
type Staff interface {
|
||||||
GetStaffByEmail(string) (*authdomain.Staff, error)
|
GetStaffByEmail(string) (*staffdomain.Staff, error)
|
||||||
GetStaffByID(string) (*authdomain.Staff, error)
|
GetStaffByID(string) (*staffdomain.Staff, error)
|
||||||
Create(*authdomain.Staff) (*authdomain.Staff, error)
|
Create(staffdomain.Staff) error
|
||||||
Update(authdomain.Staff) error
|
Update(staffdomain.Staff) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(db *database.DB) StaffIntf {
|
func New(db *database.DB) Staff {
|
||||||
return &StaffRepository{db}
|
return &impl{db}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package staffrepository
|
package staffrepository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
authdomain "legalgo-BE-go/internal/domain/auth"
|
staffdomain "legalgo-BE-go/internal/domain/staff"
|
||||||
"legalgo-BE-go/internal/utilities/utils"
|
"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)
|
val, err := utils.StructToMap(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ type SubsAccs struct {
|
|||||||
|
|
||||||
type SubsIntf interface {
|
type SubsIntf interface {
|
||||||
Create(string) (string, error)
|
Create(string) (string, error)
|
||||||
|
GetByID(string) (database.Subscribe, error)
|
||||||
|
UpdateSubscribeStatus(database.Subscribe) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(db *database.DB) SubsIntf {
|
func New(db *database.DB) SubsIntf {
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -2,13 +2,13 @@ package subscribeplanrepository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
|
"legalgo-BE-go/database"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *SubsPlan) GetByID(id string) (subscribeplandomain.SubscribePlan, error) {
|
func (s *SubsPlan) GetByID(id string) (*database.SubscribePlan, error) {
|
||||||
var subscribePlan subscribeplandomain.SubscribePlan
|
var subscribePlan *database.SubscribePlan
|
||||||
|
|
||||||
if err := s.DB.First(&subscribePlan, "id = ? ", id).Error; err != nil {
|
if err := s.DB.First(&subscribePlan, "id = ? ", id).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
package subscribeplanrepository
|
package subscribeplanrepository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
|
"legalgo-BE-go/database"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *SubsPlan) GetDefault() (subscribeplandomain.SubscribePlan, error) {
|
func (s *SubsPlan) GetDefault() (*database.SubscribePlan, error) {
|
||||||
var subscribePlan subscribeplandomain.SubscribePlan
|
var subscribePlan *database.SubscribePlan
|
||||||
|
|
||||||
if err := s.DB.First(&subscribePlan, "code = ?", "basic").Error; err != nil {
|
if err := s.DB.First(&subscribePlan, "code = ?", "basic").Error; err != nil {
|
||||||
s.DB.Create(&subscribeplandomain.SubscribePlan{
|
s.DB.Create(&database.SubscribePlan{
|
||||||
ID: uuid.NewString(),
|
ID: uuid.NewString(),
|
||||||
Code: "basic",
|
Code: "basic",
|
||||||
Name: "Basic",
|
Name: "Basic",
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ type SubsPlan struct {
|
|||||||
type SubsPlanIntf interface {
|
type SubsPlanIntf interface {
|
||||||
Create(subscribeplandomain.SubscribePlanReq) error
|
Create(subscribeplandomain.SubscribePlanReq) error
|
||||||
GetAll() ([]subscribeplandomain.SubscribePlan, error)
|
GetAll() ([]subscribeplandomain.SubscribePlan, error)
|
||||||
GetByID(string) (subscribeplandomain.SubscribePlan, error)
|
GetByID(string) (*database.SubscribePlan, error)
|
||||||
GetDefault() (subscribeplandomain.SubscribePlan, error)
|
GetDefault() (*database.SubscribePlan, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ func (acc *accessor) Create(spec tagdomain.TagReq) error {
|
|||||||
Name: spec.Name,
|
Name: spec.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := acc.DB.Create(&data).Error; err != nil {
|
if err := acc.db.Create(&data).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
func (acc *accessor) GetAll() ([]tagdomain.Tag, error) {
|
func (acc *accessor) GetAll() ([]tagdomain.Tag, error) {
|
||||||
var tags []tagdomain.Tag
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package tagrepository
|
||||||
|
|
||||||
|
import tagdomain "legalgo-BE-go/internal/domain/tag"
|
||||||
|
|
||||||
|
func (a *accessor) GetIDsByCodes(codes []string) ([]string, error) {
|
||||||
|
var tags []string
|
||||||
|
|
||||||
|
if err := a.db.
|
||||||
|
Model(&tagdomain.Tag{}).
|
||||||
|
Select("id").Where("code IN ?", codes).
|
||||||
|
Pluck("id", &tags).
|
||||||
|
Error; err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags, nil
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import tagdomain "legalgo-BE-go/internal/domain/tag"
|
|||||||
func (a *accessor) GetByIDs(ids []string) ([]tagdomain.Tag, error) {
|
func (a *accessor) GetByIDs(ids []string) ([]tagdomain.Tag, error) {
|
||||||
var tags []tagdomain.Tag
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6,16 +6,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type accessor struct {
|
type accessor struct {
|
||||||
DB *database.DB
|
db *database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type TagAccessor interface {
|
type TagAccessor interface {
|
||||||
Create(tagdomain.TagReq) error
|
Create(tagdomain.TagReq) error
|
||||||
CreateModel(tagdomain.TagReq) error
|
|
||||||
GetAll() ([]tagdomain.Tag, error)
|
GetAll() ([]tagdomain.Tag, error)
|
||||||
GetAllModel() ([]database.TagModel, error)
|
|
||||||
GetByIDs([]string) ([]tagdomain.Tag, error)
|
GetByIDs([]string) ([]tagdomain.Tag, error)
|
||||||
GetBulks(ids []string) ([]database.TagModel, error)
|
GetIDsByCodes([]string) ([]string, error)
|
||||||
|
Update(tagdomain.Tag) error
|
||||||
|
Delete(string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
package userrepository
|
package userrepository
|
||||||
|
|
||||||
import (
|
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 *accessor) CreateUser(spec userdomain.User) error {
|
||||||
if err := ur.DB.Create(&spec).Error; err != nil {
|
if err := ur.db.Create(&spec).Error; err != nil {
|
||||||
return nil, err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return spec, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,25 +2,24 @@ package userrepository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
userdomain "legalgo-BE-go/internal/domain/user"
|
||||||
authdomain "legalgo-BE-go/internal/domain/auth"
|
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ur *UserRepository) GetUserByEmail(email string) (*authdomain.User, error) {
|
func (ur *accessor) GetUserByEmail(email string) (*userdomain.User, error) {
|
||||||
var user authdomain.User
|
var user *userdomain.User
|
||||||
|
|
||||||
if email == "" {
|
if email == "" {
|
||||||
return nil, errors.New("email is empty")
|
return nil, errors.New("email is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ur.DB.First(&user, "email = ?", email).Error; err != nil {
|
if err := ur.db.First(&user, "email = ?", email).Error; err != nil {
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
return nil, errors.New("user not found")
|
return nil, errors.New("user not found")
|
||||||
}
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &user, nil
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,28 +3,22 @@ package userrepository
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
|
||||||
authdomain "legalgo-BE-go/internal/domain/auth"
|
userdomain "legalgo-BE-go/internal/domain/user"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ur *UserRepository) GetUserByID(email string) (*authdomain.UserProfile, error) {
|
func (ur *accessor) GetUserByID(id string) (*userdomain.User, error) {
|
||||||
var users []authdomain.UserProfile
|
var user userdomain.User
|
||||||
|
|
||||||
if email == "" {
|
if id == "" {
|
||||||
return nil, errors.New("email is empty")
|
return nil, errors.New("id is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ur.DB.Table("users u").
|
if err := ur.db.
|
||||||
Select("u.email, u.id, s.status as subscribe_status, sp.code as subscribe_plan_code, sp.name as subscribe_plan_name").
|
Preload("Subscribe").
|
||||||
Joins("join subscribes s on s.id = u.subscribe_id").
|
Preload("Subscribe.SubscribePlan").
|
||||||
Joins("join subscribe_plans sp on s.subscribe_plan_id = sp.id").
|
First(&user, "id = ?", id).Error; err != nil {
|
||||||
Scan(&users).Error; err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, errors.New("user not found")
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &users[0], nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,29 +2,30 @@ package userrepository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
authdomain "legalgo-BE-go/internal/domain/auth"
|
userdomain "legalgo-BE-go/internal/domain/user"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ur *UserRepository) GetUserProfile(email string) (*authdomain.UserProfile, error) {
|
func (ur *accessor) GetUserProfile(email string) (*userdomain.UserProfile, error) {
|
||||||
var users []authdomain.UserProfile
|
var user *userdomain.User
|
||||||
|
|
||||||
if email == "" {
|
if email == "" {
|
||||||
return nil, errors.New("email is empty")
|
return nil, errors.New("email is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := ur.DB.Table("users u").
|
if err := ur.db.
|
||||||
Where("email = ?", email).
|
Preload("Subscribe").
|
||||||
Select("u.email, u.id, s.status as subscribe_status, sp.code as subscribe_plan_code, sp.name as subscribe_plan_name").
|
Preload("Subscribe.SubscribePlan").
|
||||||
Joins("join subscribes s on s.id = u.subscribe_id").
|
First(&user, "email = ?", email).
|
||||||
Joins("join subscribe_plans sp on s.subscribe_plan_id = sp.id").
|
Error; err != nil {
|
||||||
Scan(&users).Error; err != nil {
|
|
||||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
|
||||||
return nil, errors.New("user not found")
|
|
||||||
}
|
|
||||||
return nil, err
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,22 +2,22 @@ package userrepository
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"legalgo-BE-go/database"
|
"legalgo-BE-go/database"
|
||||||
authdomain "legalgo-BE-go/internal/domain/auth"
|
userdomain "legalgo-BE-go/internal/domain/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UserRepository struct {
|
type accessor struct {
|
||||||
DB *database.DB
|
db *database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserIntf interface {
|
type User interface {
|
||||||
GetUserByEmail(string) (*authdomain.User, error)
|
GetUserByEmail(string) (*userdomain.User, error)
|
||||||
GetUserByID(string) (*authdomain.UserProfile, error)
|
GetUserByID(string) (*userdomain.User, error)
|
||||||
GetUserProfile(string) (*authdomain.UserProfile, error)
|
GetUserProfile(string) (*userdomain.UserProfile, error)
|
||||||
CreateUser(*authdomain.User) (*authdomain.User, error)
|
CreateUser(userdomain.User) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(
|
func New(
|
||||||
db *database.DB,
|
db *database.DB,
|
||||||
) UserIntf {
|
) User {
|
||||||
return &UserRepository{db}
|
return &accessor{db}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,24 +3,27 @@ package authhttp
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"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"
|
authsvc "legalgo-BE-go/internal/services/auth"
|
||||||
"legalgo-BE-go/internal/utilities/response"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
"legalgo-BE-go/internal/utilities/utils"
|
"legalgo-BE-go/internal/utilities/utils"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
|
"github.com/redis/go-redis/v9"
|
||||||
)
|
)
|
||||||
|
|
||||||
func LoginStaff(
|
func LoginStaff(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
authSvc authsvc.AuthIntf,
|
authSvc authsvc.Auth,
|
||||||
validate *validator.Validate,
|
validate *validator.Validate,
|
||||||
|
rdb *redis.Client,
|
||||||
) {
|
) {
|
||||||
router.Post("/staff/login", func(w http.ResponseWriter, r *http.Request) {
|
router.Post("/staff/login", func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
var spec authdomain.LoginReq
|
var spec staffdomain.StaffLogin
|
||||||
|
|
||||||
if err := utils.UnmarshalBody(r, &spec); err != nil {
|
if err := utils.UnmarshalBody(r, &spec); err != nil {
|
||||||
response.ResponseWithErrorCode(
|
response.ResponseWithErrorCode(
|
||||||
@@ -59,50 +62,7 @@ func LoginStaff(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
responsePayload := &authdomain.AuthResponse{
|
if err := utils.StoreTokenRedis(ctx, rdb, token, spec.Email); err != nil {
|
||||||
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 {
|
|
||||||
response.ResponseWithErrorCode(
|
response.ResponseWithErrorCode(
|
||||||
ctx,
|
ctx,
|
||||||
w,
|
w,
|
||||||
@@ -114,7 +74,7 @@ func LoginUser(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
responsePayload := &authdomain.AuthResponse{
|
responsePayload := &responsedomain.Auth{
|
||||||
Token: token,
|
Token: token,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
func GetStaffProfile(
|
func GetStaffProfile(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
authSvc authsvc.AuthIntf,
|
authSvc authsvc.Auth,
|
||||||
) {
|
) {
|
||||||
router.Get("/staff/profile", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/staff/profile", func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
@@ -47,7 +47,7 @@ func GetStaffProfile(
|
|||||||
|
|
||||||
func GetUserProfile(
|
func GetUserProfile(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
authSvc authsvc.AuthIntf,
|
authSvc authsvc.Auth,
|
||||||
) {
|
) {
|
||||||
router.Get("/user/profile", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/user/profile", func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|||||||
@@ -3,79 +3,27 @@ package authhttp
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"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"
|
authsvc "legalgo-BE-go/internal/services/auth"
|
||||||
"legalgo-BE-go/internal/utilities/response"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
"legalgo-BE-go/internal/utilities/utils"
|
"legalgo-BE-go/internal/utilities/utils"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-playground/validator/v10"
|
"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(
|
func RegisterStaff(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
validate *validator.Validate,
|
validate *validator.Validate,
|
||||||
authSvc authsvc.AuthIntf,
|
authSvc authsvc.Auth,
|
||||||
|
rdb *redis.Client,
|
||||||
) {
|
) {
|
||||||
router.Post("/staff/register", func(w http.ResponseWriter, r *http.Request) {
|
router.Post("/staff/register", func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
var spec authdomain.RegisterStaffReq
|
var spec staffdomain.StaffRegister
|
||||||
|
|
||||||
if err := utils.UnmarshalBody(r, &spec); err != nil {
|
if err := utils.UnmarshalBody(r, &spec); err != nil {
|
||||||
response.ResponseWithErrorCode(
|
response.ResponseWithErrorCode(
|
||||||
@@ -113,7 +61,20 @@ func RegisterStaff(
|
|||||||
)
|
)
|
||||||
return
|
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,
|
Token: token,
|
||||||
}
|
}
|
||||||
response.RespondJsonSuccess(ctx, w, responsePayload)
|
response.RespondJsonSuccess(ctx, w, responsePayload)
|
||||||
@@ -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)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package authhttp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
authdomain "legalgo-BE-go/internal/domain/auth"
|
staffdomain "legalgo-BE-go/internal/domain/staff"
|
||||||
authsvc "legalgo-BE-go/internal/services/auth"
|
authsvc "legalgo-BE-go/internal/services/auth"
|
||||||
"legalgo-BE-go/internal/utilities/response"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
"legalgo-BE-go/internal/utilities/utils"
|
"legalgo-BE-go/internal/utilities/utils"
|
||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
func UpdateStaff(
|
func UpdateStaff(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
authSvc authsvc.AuthIntf,
|
authSvc authsvc.Auth,
|
||||||
) {
|
) {
|
||||||
router.Patch("/staff/{id}/update", func(w http.ResponseWriter, r *http.Request) {
|
router.Patch("/staff/{id}/update", func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
@@ -31,7 +31,7 @@ func UpdateStaff(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var spec authdomain.RegisterStaffReq
|
var spec staffdomain.StaffRegister
|
||||||
|
|
||||||
if err := utils.UnmarshalBody(r, &spec); err != nil {
|
if err := utils.UnmarshalBody(r, &spec); err != nil {
|
||||||
response.ResponseWithErrorCode(
|
response.ResponseWithErrorCode(
|
||||||
@@ -45,11 +45,11 @@ func UpdateStaff(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
staff := authdomain.Staff{
|
staff := staffdomain.Staff{
|
||||||
ID: id,
|
ID: id,
|
||||||
Email: spec.Email,
|
Email: spec.Email,
|
||||||
Password: spec.Password,
|
Password: spec.Password,
|
||||||
Username: spec.Username,
|
Name: spec.Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := authSvc.UpdateStaff(staff); err != nil {
|
if err := authSvc.UpdateStaff(staff); err != nil {
|
||||||
@@ -64,9 +64,9 @@ func UpdateStaff(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
responsePayload := struct{
|
responsePayload := struct {
|
||||||
Message string
|
Message string
|
||||||
} {
|
}{
|
||||||
Message: "update staff success",
|
Message: "update staff success",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package categoryhttp
|
package categoryhttp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
|
||||||
categorydomain "legalgo-BE-go/internal/domain/category"
|
categorydomain "legalgo-BE-go/internal/domain/category"
|
||||||
categorysvc "legalgo-BE-go/internal/services/category"
|
categorysvc "legalgo-BE-go/internal/services/category"
|
||||||
"legalgo-BE-go/internal/utilities/response"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
@@ -16,7 +17,9 @@ func Create(
|
|||||||
validate *validator.Validate,
|
validate *validator.Validate,
|
||||||
categorySvc categorysvc.Category,
|
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()
|
ctx := r.Context()
|
||||||
|
|
||||||
var spec categorydomain.CategoryReq
|
var spec categorydomain.CategoryReq
|
||||||
|
|||||||
@@ -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",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -14,8 +14,7 @@ func GetAll(
|
|||||||
) {
|
) {
|
||||||
router.Get("/category", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/category", func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
subsPlan, err := categorySvc.GetAllModel()
|
subsPlan, err := categorySvc.GetAll()
|
||||||
// subsPlan, err := categorySvc.GetAll()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ResponseWithErrorCode(
|
response.ResponseWithErrorCode(
|
||||||
ctx,
|
ctx,
|
||||||
|
|||||||
@@ -5,4 +5,6 @@ import "go.uber.org/fx"
|
|||||||
var Module = fx.Module("categories", fx.Invoke(
|
var Module = fx.Module("categories", fx.Invoke(
|
||||||
Create,
|
Create,
|
||||||
GetAll,
|
GetAll,
|
||||||
|
Update,
|
||||||
|
Delete,
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -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",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package contenthttp
|
|
||||||
|
|
||||||
import "go.uber.org/fx"
|
|
||||||
|
|
||||||
var Module = fx.Module("content-api", fx.Invoke())
|
|
||||||
@@ -1,138 +1,76 @@
|
|||||||
package authmiddleware
|
package authmiddleware
|
||||||
|
|
||||||
// import (
|
import (
|
||||||
// "context"
|
"context"
|
||||||
// "fmt"
|
"fmt"
|
||||||
// "net/http"
|
"net/http"
|
||||||
// "strings"
|
"time"
|
||||||
|
|
||||||
// redisaccessor "legalgo-BE-go/internal/accessor/redis"
|
redisaccessor "legalgo-BE-go/internal/accessor/redis"
|
||||||
// contextkeyenum "legalgo-BE-go/internal/enums/context_key"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
// jwtclaimenum "legalgo-BE-go/internal/enums/jwt"
|
"legalgo-BE-go/internal/utilities/utils"
|
||||||
// resourceenum "legalgo-BE-go/internal/enums/resource"
|
|
||||||
// "legalgo-BE-go/internal/services/auth"
|
|
||||||
// "github.com/golang-jwt/jwt/v5"
|
|
||||||
// )
|
|
||||||
|
|
||||||
// const SessionHeader = "Authorization"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
)
|
||||||
|
|
||||||
// func Authorization() func(next http.Handler) http.Handler {
|
const SessionHeader = "Authorization"
|
||||||
// return func(next http.Handler) http.Handler {
|
|
||||||
// return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// ctx := r.Context()
|
|
||||||
|
|
||||||
// tokenString, err := GetToken(r)
|
func Authorize() func(next http.Handler) http.Handler {
|
||||||
// if err != nil {
|
return func(next http.Handler) http.Handler {
|
||||||
// RespondWithError(w, r, err, "Invalid auth header")
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// return
|
ctx := r.Context()
|
||||||
// }
|
|
||||||
|
|
||||||
// token, err := ValidateToken(ctx, tokenString)
|
tokenString, err := utils.GetToken(r)
|
||||||
// if err != nil {
|
if err != nil {
|
||||||
// RespondWithError(w, r, err, err.Error())
|
response.RespondWithError(w, r, err, "Invalid auth header")
|
||||||
// return
|
return
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if isAuthorized, ctx := VerifyClaims(ctx, token, nil); !isAuthorized {
|
spec, err := utils.GetTokenDetail(r)
|
||||||
// RespondWithError(w, r, errorcode.ErrCodeUnauthorized, errorcode.ErrCodeUnauthorized.Message)
|
|
||||||
// return
|
|
||||||
// } else {
|
|
||||||
// next.ServeHTTP(w, r.WithContext(ctx))
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func GetToken(r *http.Request) (string, error) {
|
token, err := ValidateToken(ctx, spec.Email)
|
||||||
// tokenString := GetTokenFromHeader(r)
|
if err != nil {
|
||||||
// if tokenString == "" {
|
response.RespondWithError(w, r, err, err.Error())
|
||||||
// tokenString = getTokenFromQuery(r)
|
return
|
||||||
// }
|
}
|
||||||
|
|
||||||
// if tokenString == "" {
|
isValid := token == tokenString
|
||||||
// return "", fmt.Errorf("token not found")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return tokenString, nil
|
if !isValid {
|
||||||
// }
|
response.RespondWithError(w, r, err, "invalid token")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// func GetTokenFromHeader(r *http.Request) string {
|
next.ServeHTTP(w, r.WithContext(ctx))
|
||||||
// session := r.Header.Get(SessionHeader)
|
})
|
||||||
// arr := strings.Split(session, " ")
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if len(arr) != 2 || strings.ToUpper(arr[0]) != "BEARER" {
|
func ValidateToken(ctx context.Context, id string) (string, error) {
|
||||||
// return ""
|
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, err := utils.ParseToken(redisToken)
|
||||||
// token := r.URL.Query().Get("token")
|
|
||||||
// return token
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func VerifyClaims(ctx context.Context, token *jwt.Token,
|
if err != nil {
|
||||||
// requiredResources []resourceenum.Resource) (bool, context.Context) {
|
return "", fmt.Errorf("invalid token: %w", err)
|
||||||
// if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
}
|
||||||
// rawResources := []interface{}{}
|
|
||||||
// if claimValue, exist := claims[string(jwtclaimenum.RESOURCES)]; exist {
|
|
||||||
// rawResources = claimValue.([]interface{})
|
|
||||||
// }
|
|
||||||
|
|
||||||
// resources := []resourceenum.Resource{}
|
// Check if the token is valid
|
||||||
// resourceMap := map[string]bool{}
|
if !token.Valid {
|
||||||
|
return "", fmt.Errorf("invalid token: token is not valid")
|
||||||
|
}
|
||||||
|
|
||||||
// for _, v := range rawResources {
|
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
|
||||||
// value := v.(string)
|
expirationTime := claims["exp"].(float64) // Expiration time in Unix timestamp format
|
||||||
// resources = append(resources, resourceenum.Resource(value))
|
if time.Unix(int64(expirationTime), 0).Before(time.Now()) {
|
||||||
// resourceMap[value] = true
|
return "", fmt.Errorf("token has expired")
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ctx = context.WithValue(ctx, contextkeyenum.Authorization, UserAuthorization{
|
return redisToken, nil
|
||||||
// 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
|
|
||||||
// }
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import (
|
|||||||
func Create(
|
func Create(
|
||||||
validate *validator.Validate,
|
validate *validator.Validate,
|
||||||
newsSvc newssvc.News,
|
newsSvc newssvc.News,
|
||||||
staffRepo staffrepository.StaffIntf,
|
staffRepo staffrepository.Staff,
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
) {
|
) {
|
||||||
router.Post("/news/create", func(w http.ResponseWriter, r *http.Request) {
|
router.Post("/news/create", func(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -72,7 +72,7 @@ func Create(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := newsSvc.CreateModel(spec, staffProfile.ID); err != nil {
|
if err := newsSvc.Create(spec, staffProfile.ID); err != nil {
|
||||||
response.ResponseWithErrorCode(
|
response.ResponseWithErrorCode(
|
||||||
ctx,
|
ctx,
|
||||||
w,
|
w,
|
||||||
|
|||||||
@@ -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",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package newshttp
|
package newshttp
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
newsdomain "legalgo-BE-go/internal/domain/news"
|
||||||
newssvc "legalgo-BE-go/internal/services/news"
|
newssvc "legalgo-BE-go/internal/services/news"
|
||||||
"legalgo-BE-go/internal/utilities/response"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -13,8 +14,18 @@ func GetAll(
|
|||||||
newsSvc newssvc.News,
|
newsSvc newssvc.News,
|
||||||
) {
|
) {
|
||||||
router.Get("/news", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/news", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
var (
|
||||||
|
news []newsdomain.News
|
||||||
|
err error
|
||||||
|
)
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
news, err := newsSvc.GetAllModel()
|
query := r.URL.Query()
|
||||||
|
|
||||||
|
category := query.Get("categories")
|
||||||
|
tags := query.Get("tags")
|
||||||
|
|
||||||
|
news, err = newsSvc.GetAll(category, tags)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.ResponseWithErrorCode(
|
response.ResponseWithErrorCode(
|
||||||
ctx,
|
ctx,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -4,5 +4,8 @@ import "go.uber.org/fx"
|
|||||||
|
|
||||||
var Module = fx.Module("news", fx.Invoke(
|
var Module = fx.Module("news", fx.Invoke(
|
||||||
GetAll,
|
GetAll,
|
||||||
|
GetBySlug,
|
||||||
Create,
|
Create,
|
||||||
|
Update,
|
||||||
|
Delete,
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package newshttp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
|
||||||
|
newsdomain "legalgo-BE-go/internal/domain/news"
|
||||||
|
authsvc "legalgo-BE-go/internal/services/auth"
|
||||||
|
newssvc "legalgo-BE-go/internal/services/news"
|
||||||
|
"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,
|
||||||
|
newsSvc newssvc.News,
|
||||||
|
authSvc authsvc.Auth,
|
||||||
|
) {
|
||||||
|
router.With(authmiddleware.Authorize()).
|
||||||
|
Put("/news/{news_id}/update", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
ctx := r.Context()
|
||||||
|
newsID := chi.URLParam(r, "news_id")
|
||||||
|
|
||||||
|
if newsID == "" {
|
||||||
|
response.ResponseWithErrorCode(
|
||||||
|
ctx,
|
||||||
|
w,
|
||||||
|
fmt.Errorf("news id is not provided"),
|
||||||
|
response.ErrBadRequest.Code,
|
||||||
|
response.ErrBadRequest.HttpCode,
|
||||||
|
"news id is not provided",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
destructedToken, err := utils.GetTokenDetail(r)
|
||||||
|
if err != nil {
|
||||||
|
response.ResponseWithErrorCode(
|
||||||
|
ctx,
|
||||||
|
w,
|
||||||
|
err,
|
||||||
|
response.ErrBadRequest.Code,
|
||||||
|
response.ErrBadRequest.HttpCode,
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
staff, err := authSvc.GetStaffProfile(destructedToken.Email)
|
||||||
|
if err != nil {
|
||||||
|
response.ResponseWithErrorCode(
|
||||||
|
ctx,
|
||||||
|
w,
|
||||||
|
err,
|
||||||
|
response.ErrBadRequest.Code,
|
||||||
|
response.ErrBadRequest.HttpCode,
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var spec newsdomain.NewsUpdate
|
||||||
|
if err := utils.UnmarshalBody(r, &spec); err != nil {
|
||||||
|
response.ResponseWithErrorCode(
|
||||||
|
ctx,
|
||||||
|
w,
|
||||||
|
err,
|
||||||
|
response.ErrBadRequest.Code,
|
||||||
|
response.ErrBadRequest.HttpCode,
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.ID = newsID
|
||||||
|
|
||||||
|
if err := newsSvc.Update(staff.ID, spec); err != nil {
|
||||||
|
response.ResponseWithErrorCode(
|
||||||
|
ctx,
|
||||||
|
w,
|
||||||
|
err,
|
||||||
|
response.ErrBadRequest.Code,
|
||||||
|
response.ErrBadRequest.HttpCode,
|
||||||
|
err.Error(),
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.RespondJsonSuccess(ctx, w, struct {
|
||||||
|
Message string
|
||||||
|
}{
|
||||||
|
Message: "news updated successfully.",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package subscribehttp
|
||||||
|
|
||||||
|
import "go.uber.org/fx"
|
||||||
|
|
||||||
|
var Module = fx.Module("subscribe", fx.Invoke())
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ package subscribeplanhttp
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
|
||||||
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
|
subscribeplandomain "legalgo-BE-go/internal/domain/subscribe_plan"
|
||||||
subscribeplansvc "legalgo-BE-go/internal/services/subscribe_plan"
|
subscribeplansvc "legalgo-BE-go/internal/services/subscribe_plan"
|
||||||
"legalgo-BE-go/internal/utilities/response"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
@@ -15,9 +16,11 @@ import (
|
|||||||
func CreateSubscribePlan(
|
func CreateSubscribePlan(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
validate *validator.Validate,
|
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()
|
ctx := r.Context()
|
||||||
|
|
||||||
var spec subscribeplandomain.SubscribePlanReq
|
var spec subscribeplandomain.SubscribePlanReq
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
func GetAllPlan(
|
func GetAllPlan(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
subsPlanSvc subscribeplansvc.SubsPlanIntf,
|
subsPlanSvc subscribeplansvc.SubscribePlan,
|
||||||
) {
|
) {
|
||||||
router.Get("/subscribe-plan", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/subscribe-plan", func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package taghttp
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
authmiddleware "legalgo-BE-go/internal/api/http/middleware/auth"
|
||||||
tagdomain "legalgo-BE-go/internal/domain/tag"
|
tagdomain "legalgo-BE-go/internal/domain/tag"
|
||||||
tagsvc "legalgo-BE-go/internal/services/tag"
|
tagsvc "legalgo-BE-go/internal/services/tag"
|
||||||
"legalgo-BE-go/internal/utilities/response"
|
"legalgo-BE-go/internal/utilities/response"
|
||||||
@@ -15,9 +16,11 @@ import (
|
|||||||
func Create(
|
func Create(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
validate *validator.Validate,
|
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()
|
ctx := r.Context()
|
||||||
|
|
||||||
var spec tagdomain.TagReq
|
var spec tagdomain.TagReq
|
||||||
|
|||||||
@@ -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",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
func GetAll(
|
func GetAll(
|
||||||
router chi.Router,
|
router chi.Router,
|
||||||
tagSvc tagsvc.TagIntf,
|
tagSvc tagsvc.Tag,
|
||||||
) {
|
) {
|
||||||
router.Get("/tag", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/tag", func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|||||||
@@ -5,4 +5,6 @@ import "go.uber.org/fx"
|
|||||||
var Module = fx.Module("tag", fx.Invoke(
|
var Module = fx.Module("tag", fx.Invoke(
|
||||||
Create,
|
Create,
|
||||||
GetAll,
|
GetAll,
|
||||||
|
Update,
|
||||||
|
Delete,
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -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",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,31 +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"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
}
|
|
||||||
|
|
||||||
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"`
|
|
||||||
}
|
|
||||||
@@ -3,4 +3,5 @@ package authdomain
|
|||||||
type AuthToken struct {
|
type AuthToken struct {
|
||||||
Email string
|
Email string
|
||||||
SessionID string
|
SessionID string
|
||||||
|
Role string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
package categorydomain
|
package categorydomain
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type Category struct {
|
type Category struct {
|
||||||
ID string `json:"id" gorm:"primaryKey"`
|
ID string `json:"id" gorm:"primaryKey"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CategoryReq struct {
|
type CategoryReq struct {
|
||||||
|
|||||||
@@ -16,17 +16,41 @@ type NewsReq struct {
|
|||||||
LiveAt string `json:"live_at" validate:"required"`
|
LiveAt string `json:"live_at" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type News struct {
|
type Staff struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ProfilePicture string `json:"profile_picture"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type News struct {
|
||||||
|
ID string `json:"id" gorm:"primaryKey"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
FeaturedImage string `json:"featured_image"`
|
FeaturedImage string `json:"featured_image"`
|
||||||
Tags []tagdomain.Tag `json:"tags"`
|
Tags []tagdomain.Tag `gorm:"many2many:news_tags" json:"tags"`
|
||||||
Categories []categorydomain.Category `json:"categories"`
|
Categories []categorydomain.Category `gorm:"many2many:news_categories" json:"categories"`
|
||||||
IsPremium bool `json:"is_premium"`
|
IsPremium bool `json:"is_premium"`
|
||||||
Slug string `json:"slug"`
|
Slug string `json:"slug"`
|
||||||
AuthorID string `json:"author_id"`
|
AuthorID string `json:"author_id"`
|
||||||
LiveAt time.Time `json:"live_at"`
|
LiveAt time.Time `json:"live_at"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
|
|
||||||
|
Author Staff `json:"author"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewsUpdate struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Content string `json:"content"`
|
||||||
|
FeaturedImage string `json:"featured_image"`
|
||||||
|
Tags []string `json:"tags"`
|
||||||
|
Categories []string `json:"categories"`
|
||||||
|
IsPremium bool `json:"is_premium"`
|
||||||
|
LiveAt time.Time `json:"live_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type NewsFilter struct {
|
||||||
|
Tags []string
|
||||||
|
Category []string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package responsedomain
|
||||||
|
|
||||||
|
type Auth struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
}
|
||||||
@@ -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"`
|
||||||
|
}
|
||||||
@@ -1,6 +1,28 @@
|
|||||||
package subscribedomain
|
package subscribedomain
|
||||||
|
|
||||||
type Subscribe struct {
|
import (
|
||||||
|
subscribeplandm "legalgo-BE-go/internal/domain/subscribe_plan_model"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SubscribeDepecrate struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
SubscribePlanID string `json:"subscribe_plan_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"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package subscribeplandm
|
||||||
|
|
||||||
|
// refactored
|
||||||
|
type SubscribePlan struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Code string `json:"code"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package tagdomain
|
package tagdomain
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type TagReq struct {
|
type TagReq struct {
|
||||||
Code string `json:"code" validate:"required"`
|
Code string `json:"code" validate:"required"`
|
||||||
Name string `json:"name" validate:"required"`
|
Name string `json:"name" validate:"required"`
|
||||||
@@ -9,4 +11,6 @@ type Tag struct {
|
|||||||
ID string `json:"id" gorm:"primaryKey"`
|
ID string `json:"id" gorm:"primaryKey"`
|
||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,37 @@
|
|||||||
package authdomain
|
package userdomain
|
||||||
|
|
||||||
type RegisterUserReq struct {
|
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"`
|
Email string `json:"email" validate:"required"`
|
||||||
Password string `json:"password" validate:"required"`
|
Password string `json:"password" validate:"required"`
|
||||||
Phone string `json:"phone" validate:"required"`
|
Phone string `json:"phone" validate:"required"`
|
||||||
SubscribePlanID string `json:"subscribe_plan_id"`
|
SubscribePlanID string `json:"subscribe_plan_id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type User struct {
|
type UserProfile struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
Password string `json:"password"`
|
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
SubscribeID string `json:"subscribe_id"`
|
|
||||||
|
Subscribe subscribedm.Subscribe `gorm:"foreignKey:SubscribeID" json:"subscribe"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegisterStaffReq struct {
|
type UserLogin struct {
|
||||||
Email string `json:"email" validate:"required"`
|
Email string `json:"email" validate:"required"`
|
||||||
Password string `json:"password" validate:"required"`
|
Password string `json:"password" validate:"required"`
|
||||||
Username string `json:"username" validate:"required"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateStaffReq struct {
|
type UserSubsUpdate struct {
|
||||||
Email string `json:"email"`
|
Status string `json:"status"`
|
||||||
Password string `json:"password"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Staff struct {
|
|
||||||
ID string `json:"id"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
Password string `json:"password"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,20 @@
|
|||||||
package authsvc
|
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)
|
staff, err := as.staffRepo.GetStaffByEmail(email)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
profile := &authdomain.StaffProfile{
|
profile := &staffdomain.StaffProfile{
|
||||||
ID: staff.ID,
|
ID: staff.ID,
|
||||||
Username: staff.Username,
|
Name: staff.Name,
|
||||||
Email: staff.Email,
|
Email: staff.Email,
|
||||||
|
ProfilePicture: staff.ProfilePicture,
|
||||||
}
|
}
|
||||||
|
|
||||||
return profile, nil
|
return profile, nil
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user