Cập nhật cấu hình môi trường production và development

- Thêm file .env.prod với cấu hình chi tiết cho môi trường production
- Cập nhật docker-compose.dev.yml và docker-compose.prod.yml
- Tạo Dockerfile.prod với cấu hình chi tiết cho production
- Bổ sung cấu hình nginx, prometheus, grafana
- Thêm cấu hình backup và monitoring
- Cập nhật README với hướng dẫn chi tiết
This commit is contained in:
koh
2025-03-03 16:31:52 +07:00
parent e2a219cacd
commit 86a60a7861
20 changed files with 572 additions and 509 deletions

View File

@@ -3,11 +3,9 @@ package initialize
import (
"fmt"
"os"
"reflect"
"strings"
"github.com/dungnt11/senflow_app/global"
"github.com/fatih/color"
"github.com/joho/godotenv"
)
@@ -63,57 +61,5 @@ func LoadConfig() error {
global.Config.Logger.Compress = strings.ToLower(compress) == "true"
}
printConfig()
return nil
}
func printConfig() {
// Tạo các đối tượng màu sắc
titleColor := color.New(color.FgHiCyan, color.Bold)
sectionColor := color.New(color.FgHiYellow, color.Bold)
keyColor := color.New(color.FgHiGreen)
valueColor := color.New(color.FgHiWhite)
fmt.Println() // Thêm dòng trống ở đầu
// In tiêu đề
titleColor.Println("✨✨✨ CẤU HÌNH ỨNG DỤNG ✨✨✨")
fmt.Println()
// Sử dụng reflection để tự động in tất cả các cấu hình
configValue := reflect.ValueOf(global.Config)
configType := configValue.Type()
// Duyệt qua tất cả các trường của cấu hình
for i := 0; i < configValue.NumField(); i++ {
sectionName := configType.Field(i).Name
sectionValue := configValue.Field(i)
sectionType := sectionValue.Type()
// In tên section
sectionColor.Printf("[%s]\n", strings.ToUpper(sectionName))
// Duyệt qua tất cả các trường của section
for j := 0; j < sectionValue.NumField(); j++ {
fieldName := sectionType.Field(j).Name
fieldValue := sectionValue.Field(j).Interface()
// Ẩn mật khẩu
displayValue := fmt.Sprintf("%v", fieldValue)
if strings.Contains(strings.ToLower(fieldName), "password") {
displayValue = "******** (ẩn)"
}
// In tên trường và giá trị
keyColor.Printf(" %-15s: ", fieldName)
valueColor.Printf("%s\n", displayValue)
}
fmt.Println() // Thêm dòng trống giữa các section
}
// In thông báo thành công
titleColor.Println("✅ Cấu hình đã được tải thành công!")
fmt.Println() // Thêm dòng trống ở cuối
}

View File

@@ -21,6 +21,7 @@ func checkErrorPanic(err error, errString string) {
// InitMysql khởi tạo kết nối đến cơ sở dữ liệu MySQL và trả về đối tượng *gorm.DB.
func InitMysql() *gorm.DB {
m := global.Config.Database
dsn := "%s:%s@tcp(%s:%v)/%s?charset=utf8mb4&parseTime=True&loc=Local"
s := fmt.Sprintf(dsn, m.Username, m.Password, m.Host, m.Port, m.Database)
db, err := gorm.Open(mysql.Open(s), &gorm.Config{

View File

@@ -39,7 +39,7 @@ func Run() {
}
// Khởi tạo router
r := gin.Default()
r := provideRouter()
// Khởi tạo controllers thông qua wire
controllers, err := wire.InitializeControllers()
@@ -80,3 +80,14 @@ func Run() {
global.Logger.Info("Server đã tắt thành công.")
}
func provideRouter() *gin.Engine {
if global.Config.Server.AppEnv == "local" {
gin.SetMode(gin.DebugMode)
gin.ForceConsoleColor()
return gin.Default()
} else {
gin.SetMode(gin.ReleaseMode)
return gin.New()
}
}

View File

@@ -9,7 +9,7 @@ import (
// User đại diện cho người dùng trong hệ thống
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
Email string `json:"email" gorm:"uniqueIndex;not null"`
Username string `json:"username" gorm:"uniqueIndex;not null"`
Password string `json:"-" gorm:"not null"` // Không trả về password trong JSON
Name string `json:"name"`
CreatedAt time.Time `json:"created_at"`

View File

@@ -6,7 +6,7 @@ import "github.com/dungnt11/senflow_app/internal/models"
type IUserRepository interface {
Create(user *models.User) error
FindByID(id uint) (*models.User, error)
FindByEmail(email string) (*models.User, error)
FindByUsername(username string) (*models.User, error)
Update(user *models.User) error
Delete(id uint) error
}

View File

@@ -32,10 +32,10 @@ func (ur *UserRepository) FindByID(id uint) (*models.User, error) {
return &user, nil
}
// FindByEmail tìm user theo email
func (ur *UserRepository) FindByEmail(email string) (*models.User, error) {
// FindByUsername tìm user theo username
func (ur *UserRepository) FindByUsername(username string) (*models.User, error) {
var user models.User
err := ur.db.Where("email = ?", email).First(&user).Error
err := ur.db.Where("username = ?", username).First(&user).Error
if err != nil {
return nil, err
}

View File

@@ -28,10 +28,10 @@ func (us *UserService) Register(c *gin.Context) (map[string]interface{}, error)
return nil, err
}
// Kiểm tra email đã tồn tại chưa
existingUser, _ := us.userRepo.FindByEmail(user.Email)
// Kiểm tra username đã tồn tại chưa
existingUser, _ := us.userRepo.FindByUsername(user.Username)
if existingUser != nil {
return nil, errors.New("email đã được sử dụng")
return nil, errors.New("username đã được sử dụng")
}
// Lưu vào database thông qua repository
@@ -51,22 +51,22 @@ func (us *UserService) Register(c *gin.Context) (map[string]interface{}, error)
func (us *UserService) Login(c *gin.Context) (map[string]interface{}, error) {
// Đọc dữ liệu từ request
var loginData struct {
Email string `json:"email"`
Username string `json:"username"`
Password string `json:"password"`
}
if err := c.ShouldBindJSON(&loginData); err != nil {
return nil, err
}
// Tìm user theo email
user, err := us.userRepo.FindByEmail(loginData.Email)
// Tìm user theo username
user, err := us.userRepo.FindByUsername(loginData.Username)
if err != nil {
return nil, errors.New("email hoặc mật khẩu không đúng")
return nil, errors.New("username hoặc mật khẩu không đúng")
}
// Kiểm tra mật khẩu (giả định)
if user.Password != loginData.Password {
return nil, errors.New("email hoặc mật khẩu không đúng")
return nil, errors.New("username hoặc mật khẩu không đúng")
}
// Trả về kết quả

View File

@@ -6,7 +6,6 @@ import (
"github.com/dungnt11/senflow_app/internal/controllers"
"github.com/dungnt11/senflow_app/internal/repositories"
"github.com/dungnt11/senflow_app/internal/services"
"github.com/gin-gonic/gin"
"github.com/google/wire"
"gorm.io/gorm"
)
@@ -48,15 +47,3 @@ var AppSet = wire.NewSet(
func ProvideDB() *gorm.DB {
return global.Mdb
}
// ProvideRouter cung cấp instance của *gin.Engine
func ProvideRouter() *gin.Engine {
if global.Config.Server.AppEnv == "local" {
gin.SetMode(gin.DebugMode)
gin.ForceConsoleColor()
return gin.Default()
} else {
gin.SetMode(gin.ReleaseMode)
return gin.New()
}
}