refac: runtime settings are read once at startup and passed in through the composition root; no handler, router or repository reads environment variables

This commit is contained in:
fsylvain committed 2026-09-24 01:30:00 +02:00
1 parent e474f03d91
commit 0b4e614ec9
15 files changed
+722 -66

No files matched your search

@@ -0,0 +1,59 @@
package config
import (
"os"
"strconv"
"strings"
)
type SmtpSettings struct {
Email string
Password string
Host string
Port int
}
type Settings struct {
Environment string
CorsAllowedOrigins []string
PublicURL string
UploadDir string
JWTSecret string
DBFile string
Port string
Smtp SmtpSettings
}
func (s Settings) IsProduction() bool {
return s.Environment == "production"
}
func NewSettingsFromEnv() (Settings, error) {
smtpPort, err := strconv.Atoi(os.Getenv("SMTP_PORT"))
if err != nil {
return Settings{}, err
}
return Settings{
Environment: os.Getenv("ENVIRONMENT"),
CorsAllowedOrigins: parseCorsAllowedOrigins(os.Getenv("CORS_ALLOWED_ORIGINS")),
PublicURL: os.Getenv("PUBLIC_URL"),
UploadDir: os.Getenv("UPLOAD_DIR"),
JWTSecret: os.Getenv("JWT_SECRET"),
DBFile: os.Getenv("DB_FILE"),
Port: os.Getenv("PORT"),
Smtp: SmtpSettings{
Email: os.Getenv("SMTP_EMAIL"),
Password: os.Getenv("SMTP_PASSWORD"),
Host: os.Getenv("SMTP_HOST"),
Port: smtpPort,
},
}, nil
}
func parseCorsAllowedOrigins(raw string) []string {
if raw == "" {
return nil
}
return strings.Split(raw, ";")
}
@@ -2,30 +2,31 @@ package mailer
import (
domain "RenewCMS/internal/domain/mail"
"RenewCMS/internal/infrastructure/config"
"bytes"
"embed"
"html/template"
"log"
"os"
"strconv"
"gopkg.in/gomail.v2"
)
type MailRepository struct{}
type MailRepository struct {
smtp config.SmtpSettings
}
//go:embed templates/*
var mailTemplateFiles embed.FS
func NewMailRepository() *MailRepository {
return &MailRepository{}
func NewMailRepository(smtp config.SmtpSettings) *MailRepository {
return &MailRepository{smtp: smtp}
}
func (m MailRepository) Send(receiverAddress string, templateName string, data any) error {
from := os.Getenv("SMTP_EMAIL")
password := os.Getenv("SMTP_PASSWORD")
smtpHost := os.Getenv("SMTP_HOST")
smtpPort, _ := strconv.Atoi(os.Getenv("SMTP_PORT"))
from := m.smtp.Email
password := m.smtp.Password
smtpHost := m.smtp.Host
smtpPort := m.smtp.Port
d := gomail.NewDialer(smtpHost, smtpPort, from, password)
@@ -13,11 +13,12 @@ import (
)
type ImageRepository struct {
db *gorm.DB
db *gorm.DB
uploadDir string
}
func NewImageRepository(db *gorm.DB) *ImageRepository {
return &ImageRepository{db}
func NewImageRepository(db *gorm.DB, uploadDir string) *ImageRepository {
return &ImageRepository{db, uploadDir}
}
var contentTypeExtensions = map[string]string{
@@ -28,7 +29,7 @@ var contentTypeExtensions = map[string]string{
}
func (i ImageRepository) Create(input domain.ImageInput) (domain.Image, error) {
uploadDir := os.Getenv("UPLOAD_DIR")
uploadDir := i.uploadDir
fileBytes, err := io.ReadAll(input.Content)
if err != nil {
@@ -57,7 +58,7 @@ func (i ImageRepository) Create(input domain.ImageInput) (domain.Image, error) {
}
func (i ImageRepository) Delete(id uint32) error {
uploadDir := os.Getenv("UPLOAD_DIR")
uploadDir := i.uploadDir
var entityImage entity.Image
err := i.db.Model(&entity.Image{}).First(&entityImage, id).Error
if err != nil {