add: Environment Var support

This commit is contained in:
$(pass /github/name)
2024-07-17 16:46:29 +02:00
parent 9eef7f7681
commit f4a9166bee
9 changed files with 86 additions and 68 deletions

View File

@@ -2,11 +2,11 @@ package main
import (
"GoMembership/internal/server"
"log"
"GoMembership/pkg/logger"
)
func main() {
log.Println("startup...")
logger.Info.Println("startup...")
server.Run()
}

7
go.mod
View File

@@ -6,19 +6,19 @@ require (
github.com/gin-gonic/gin v1.10.0
github.com/go-playground/validator/v10 v10.22.0
github.com/jbub/banking v0.8.0
github.com/stretchr/testify v1.9.0
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gorm.io/driver/sqlite v1.5.6
gorm.io/gorm v1.25.10
)
require github.com/kelseyhightower/envconfig v1.4.0
require (
github.com/bytedance/sonic v1.11.9 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.4 // in
github.com/gabriel-vasile/mimetype v1.4.4 // indirect; in
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
@@ -33,7 +33,6 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
golang.org/x/arch v0.8.0 // indirect

2
go.sum
View File

@@ -36,6 +36,8 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=

View File

@@ -1,36 +1,39 @@
package config
import (
"GoMembership/internal/utils"
"GoMembership/pkg/logger"
"encoding/json"
"os"
"path/filepath"
"sync"
"github.com/kelseyhightower/envconfig"
"GoMembership/internal/utils"
"GoMembership/pkg/logger"
)
type DatabaseConfig struct {
Path string `json:"Path"`
Path string `json:"Path" envconfig:"DB_PATH"`
}
type AuthenticationConfig struct {
JWTSecret string
CSRFSecret string
APIKEY string `json:"APIKey"`
APIKEY string `json:"APIKey" envconfig:"API_KEY"`
}
type SMTPConfig struct {
Host string `json:"Host"`
User string `json:"User"`
Password string `json:"Password"`
Mailtype string `json:"Mailtype"`
AdminEmail string `json:"AdminEmail"`
Port int `json:"Port"`
Host string `json:"Host" envconfig:"SMTP_HOST"`
User string `json:"User" envconfig:"SMTP_USER"`
Password string `json:"Password" envconfig:"SMTP_PASS"`
Mailtype string `json:"Mailtype" envconfig:"MAIL_TYPE"`
AdminEmail string `json:"AdminEmail" envconfig:"ADMIN_MAIL"`
Port int `json:"Port" envconfig:"SMTP_PORT"`
}
type TemplateConfig struct {
MailDir string `json:"MailDir"`
MailDir string `json:"MailDir" envconfig:"TEMPLATE_DIR"`
}
type Config struct {
Auth AuthenticationConfig `json:"auth"`
DB DatabaseConfig `json:"db"`
@@ -39,46 +42,57 @@ type Config struct {
}
var (
pConfig Config
once sync.Once
loaded bool
CFG Config
Auth AuthenticationConfig
DB DatabaseConfig
Templates TemplateConfig
SMTP SMTPConfig
)
func LoadConfig() *Config {
func LoadConfig() {
readFile(&CFG)
readEnv(&CFG)
csrfSecret, err := utils.GenerateRandomString(32)
if err != nil {
logger.Error.Fatalf("could not generate CSRF secret: %v", err)
}
jwtSecret, err := utils.GenerateRandomString(32)
if err != nil {
logger.Error.Fatalf("could not generate JWT secret: %v", err)
}
CFG.Auth.JWTSecret = jwtSecret
CFG.Auth.CSRFSecret = csrfSecret
Auth = CFG.Auth
DB = CFG.DB
Templates = CFG.Templates
SMTP = CFG.SMTP
}
func readFile(cfg *Config) {
path, err := os.Getwd()
if err != nil {
logger.Error.Fatalf("could not get working directory: %v", err)
}
configFile, err := os.Open(filepath.Join(path, "configs", "config.json"))
// configFile, err := os.Open("config.json")
if err != nil {
logger.Error.Fatalf("could not open config file: %v", err)
}
defer configFile.Close()
decoder := json.NewDecoder(configFile)
// pConfig = &Config{}
err = decoder.Decode(&pConfig)
err = decoder.Decode(cfg)
if err != nil {
logger.Error.Fatalf("could not decode config file: %v", err)
}
if !loaded {
once.Do(
func() {
csrfSecret, err := utils.GenerateRandomString(32)
if err != nil {
logger.Error.Fatalf("could not generate CSRF secret: %v", err)
}
jwtSecret, err := utils.GenerateRandomString(32)
if err != nil {
logger.Error.Fatalf("could not generate JWT secret: %v", err)
}
pConfig.Auth.JWTSecret = jwtSecret
pConfig.Auth.CSRFSecret = csrfSecret
loaded = true
})
}
return &pConfig
}
func readEnv(cfg *Config) {
err := envconfig.Process("", cfg)
if err != nil {
logger.Error.Fatalf("could not decode env variables: %#v", err)
}
}

View File

@@ -28,14 +28,14 @@ func (mc *MembershipController) RegisterSubscription(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": "Couldn't decode subscription data"})
}
logger.Info.Printf("Using API key: %v", config.LoadConfig().Auth.APIKEY)
logger.Info.Printf("Using API key: %v", config.Auth.APIKEY)
if regData.APIKey == "" {
logger.Error.Println("API Key is missing")
c.JSON(http.StatusBadRequest, "API Key is missing")
return
}
if regData.APIKey != config.LoadConfig().Auth.APIKEY {
if regData.APIKey != config.Auth.APIKEY {
logger.Error.Printf("API Key not valid: %v", regData.APIKey)
c.JSON(http.StatusExpectationFailed, "API Key is missing")
return

View File

@@ -42,8 +42,8 @@ func TestUserController(t *testing.T) {
t.Errorf("Failed to create DB: %#v", err)
}
cfg := config.LoadConfig()
emailService := services.NewEmailService(cfg.SMTP.Host, cfg.SMTP.Port, cfg.SMTP.User, cfg.SMTP.Password, cfg.SMTP.AdminEmail)
config.LoadConfig()
emailService := services.NewEmailService(config.SMTP.Host, config.SMTP.Port, config.SMTP.User, config.SMTP.Password, config.SMTP.AdminEmail)
var consentRepo repositories.ConsentRepositoryInterface = &repositories.ConsentRepository{}
consentService := &services.ConsentService{Repo: consentRepo}

View File

@@ -1,14 +1,16 @@
package middlewares
import (
"GoMembership/internal/config"
"GoMembership/internal/utils"
"GoMembership/pkg/logger"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"net/http"
"strings"
"GoMembership/internal/config"
"GoMembership/internal/server"
"GoMembership/internal/utils"
"GoMembership/pkg/logger"
)
// GenerateCSRFToken generates HMAC-signed CSRF token
@@ -46,7 +48,7 @@ func CSRFMiddleware(next http.Handler) http.Handler {
next.ServeHTTP(w, r)
return
}
csrfSecret := config.LoadConfig().Auth.CSRFSecret
csrfSecret := config.Auth.CSRFSecret
// Retrieve CSRF token from request (e.g., from cookie, header, or form data)
csrfToken := r.Header.Get("X-CSRF-Token")
@@ -78,7 +80,7 @@ func GenerateCSRFTokenHandler(w http.ResponseWriter, r *http.Request) {
sessionID := "exampleSessionID123"
// Generate HMAC-signed CSRF token
csrfToken := GenerateCSRFToken(sessionID, config.LoadConfig().Auth.CSRFSecret)
csrfToken := GenerateCSRFToken(sessionID, config.Auth.CSRFSecret)
// Set CSRF token in a cookie (example)
http.SetCookie(w, &http.Cookie{

View File

@@ -17,14 +17,15 @@ import (
)
func Run() {
cfg := config.LoadConfig()
logger.Info.Printf("Config: %+v", cfg)
err := database.InitDB(cfg.DB.Path)
config.LoadConfig()
logger.Info.Printf("Config loaded: %#v", config.CFG)
err := database.InitDB(config.DB.Path)
if err != nil {
logger.Error.Fatalf("Couldn't init database: %v", err)
}
emailService := services.NewEmailService(cfg.SMTP.Host, cfg.SMTP.Port, cfg.SMTP.User, cfg.SMTP.Password, cfg.SMTP.AdminEmail)
emailService := services.NewEmailService(config.SMTP.Host, config.SMTP.Port, config.SMTP.User, config.SMTP.Password, config.SMTP.AdminEmail)
var consentRepo repositories.ConsentRepositoryInterface = &repositories.ConsentRepository{}
consentService := &services.ConsentService{Repo: consentRepo}

View File

@@ -37,7 +37,7 @@ func (s *EmailService) SendEmail(to string, subject string, body string) error {
func ParseTemplate(filename string, data interface{}) (string, error) {
// Read the email template file
templateDir := config.LoadConfig().Templates.MailDir
templateDir := config.Templates.MailDir
tpl, err := template.ParseFiles(templateDir + "/" + filename)
if err != nil {
logger.Error.Printf("Failed to parse email template: %v", err)
@@ -106,20 +106,20 @@ func (s *EmailService) SendWelcomeEmail(user *models.User) error {
func (s *EmailService) NotifyAdminOfNewUser(user *models.User) error {
// Prepare data to be injected into the template
data := struct {
Company string
FirstName string
City string
Email string
LastName string
MembershipModel string
MembershipID int64
MembershipFee float32
RentalFee float32
Address string
ZipCode string
City string
DateOfBirth string
Email string
Phone string
IBAN string
FirstName string
Phone string
DateOfBirth string
Company string
ZipCode string
MembershipID int64
RentalFee float32
MembershipFee float32
}{
Company: *user.Company,
FirstName: user.FirstName,
@@ -143,5 +143,5 @@ func (s *EmailService) NotifyAdminOfNewUser(user *models.User) error {
logger.Error.Print("Couldn't send admin notification mail")
return err
}
return s.SendEmail(config.LoadConfig().SMTP.AdminEmail, subject, body)
return s.SendEmail(config.SMTP.AdminEmail, subject, body)
}