Re-work loading of configuration, introduce a loader for start up & and custom logging wrapper.
This commit is contained in:
30
bootstrap/loader.go
Normal file
30
bootstrap/loader.go
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package bootstrap
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"synlotto-website/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AppState struct {
|
||||||
|
Config *models.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadAppState(configPath string) (*AppState, error) {
|
||||||
|
file, err := os.Open(configPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("open config: %w", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
var config models.Config
|
||||||
|
if err := json.NewDecoder(file).Decode(&config); err != nil {
|
||||||
|
return nil, fmt.Errorf("decode config: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &AppState{
|
||||||
|
Config: &config,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
22
config/config.go
Normal file
22
config/config.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"synlotto-website/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
appConfig *models.Config
|
||||||
|
once sync.Once
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init(config *models.Config) {
|
||||||
|
once.Do(func() {
|
||||||
|
appConfig = config
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func Get() *models.Config {
|
||||||
|
return appConfig
|
||||||
|
}
|
||||||
24
logging/config.go
Normal file
24
logging/config.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"synlotto-website/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LogConfig(config *models.Config) {
|
||||||
|
safeConfig := *config
|
||||||
|
safeConfig.CSRF.CSRFKey = "[REDACTED]"
|
||||||
|
safeConfig.Session.SessionAuthKey = "[REDACTED]"
|
||||||
|
safeConfig.Session.SessionEncryptionKey = "[REDACTED]"
|
||||||
|
|
||||||
|
cfg, err := json.MarshalIndent(safeConfig, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Failed to log config:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("App starting with config:")
|
||||||
|
log.Println(string(cfg))
|
||||||
|
}
|
||||||
13
logging/messages.go
Normal file
13
logging/messages.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package logging
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Info(msg string, args ...any) {
|
||||||
|
log.Printf("[INFO] "+msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Error(msg string, args ...any) {
|
||||||
|
log.Printf("[ERROR] "+msg, args...)
|
||||||
|
}
|
||||||
14
main.go
14
main.go
@@ -3,8 +3,11 @@ package main
|
|||||||
import (
|
import (
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"synlotto-website/bootstrap"
|
||||||
|
"synlotto-website/config"
|
||||||
"synlotto-website/handlers"
|
"synlotto-website/handlers"
|
||||||
"synlotto-website/helpers"
|
"synlotto-website/helpers"
|
||||||
|
"synlotto-website/logging"
|
||||||
"synlotto-website/middleware"
|
"synlotto-website/middleware"
|
||||||
"synlotto-website/models"
|
"synlotto-website/models"
|
||||||
"synlotto-website/routes"
|
"synlotto-website/routes"
|
||||||
@@ -14,11 +17,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
appState, err := bootstrap.LoadAppState("config/config.json")
|
||||||
|
if err != nil {
|
||||||
|
logging.Error("Failed to load app state: %v", err)
|
||||||
|
}
|
||||||
|
config.Init(appState.Config)
|
||||||
|
logging.LogConfig(appState.Config)
|
||||||
|
|
||||||
db := storage.InitDB("synlotto.db")
|
db := storage.InitDB("synlotto.db")
|
||||||
models.SetDB(db) // Should be in storage not models.
|
models.SetDB(db) // Should be in storage not models.
|
||||||
|
|
||||||
var isProduction = false
|
|
||||||
|
|
||||||
csrfMiddleware := csrf.Protect(
|
csrfMiddleware := csrf.Protect(
|
||||||
[]byte("abcdefghijklmnopqrstuvwx12345678"), // TodO: Make Global
|
[]byte("abcdefghijklmnopqrstuvwx12345678"), // TodO: Make Global
|
||||||
csrf.Secure(true),
|
csrf.Secure(true),
|
||||||
@@ -35,7 +43,7 @@ func main() {
|
|||||||
mux.HandleFunc("/", handlers.Home(db))
|
mux.HandleFunc("/", handlers.Home(db))
|
||||||
|
|
||||||
wrapped := helpers.RateLimit(csrfMiddleware(mux))
|
wrapped := helpers.RateLimit(csrfMiddleware(mux))
|
||||||
wrapped = middleware.EnforceHTTPS(wrapped, isProduction)
|
wrapped = middleware.EnforceHTTPS(wrapped, appState.Config.HttpServer.ProductionMode)
|
||||||
wrapped = middleware.SecureHeaders(wrapped)
|
wrapped = middleware.SecureHeaders(wrapped)
|
||||||
wrapped = middleware.Recover(wrapped)
|
wrapped = middleware.Recover(wrapped)
|
||||||
|
|
||||||
|
|||||||
19
models/config.go
Normal file
19
models/config.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package models
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
HttpServer struct {
|
||||||
|
Port int `json:"port"`
|
||||||
|
Address string `json:"address"`
|
||||||
|
ProductionMode bool `json:"productionMode"`
|
||||||
|
} `json:"httpServer"`
|
||||||
|
|
||||||
|
CSRF struct {
|
||||||
|
CSRFKey string `json:"csrfKey"`
|
||||||
|
} `json:"csrf"`
|
||||||
|
|
||||||
|
Session struct {
|
||||||
|
SessionAuthKey string `json:"authKey"`
|
||||||
|
SessionEncryptionKey string `json:"encryptionKey"`
|
||||||
|
SessionName string `json:"sessionName"`
|
||||||
|
} `json:"session"`
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user