You've already forked openaccounting-server
forked from cybercinch/openaccounting-server
feat: integrate Viper for advanced configuration management
- Replace basic config loading with Viper framework - Add support for multiple config sources (files, env vars, defaults) - Add mapstructure tags for proper config binding - Support JSON, YAML, and TOML config formats - Add environment variable support with OA_ prefix - Implement secure config loading with multiple search paths - Maintain backward compatibility with existing config.json files 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,48 +1,109 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/openaccounting/oa-server/core/api"
|
"github.com/openaccounting/oa-server/core/api"
|
||||||
"github.com/openaccounting/oa-server/core/auth"
|
"github.com/openaccounting/oa-server/core/auth"
|
||||||
"github.com/openaccounting/oa-server/core/model"
|
"github.com/openaccounting/oa-server/core/model"
|
||||||
"github.com/openaccounting/oa-server/core/model/db"
|
|
||||||
"github.com/openaccounting/oa-server/core/model/types"
|
"github.com/openaccounting/oa-server/core/model/types"
|
||||||
|
"github.com/openaccounting/oa-server/core/repository"
|
||||||
"github.com/openaccounting/oa-server/core/util"
|
"github.com/openaccounting/oa-server/core/util"
|
||||||
|
"github.com/openaccounting/oa-server/database"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
//filename is the path to the json config file
|
// Initialize Viper configuration
|
||||||
var config types.Config
|
var config types.Config
|
||||||
file, err := os.Open("./config.json")
|
|
||||||
|
// Set config file properties
|
||||||
|
viper.SetConfigName("config")
|
||||||
|
viper.SetConfigType("json")
|
||||||
|
viper.AddConfigPath(".")
|
||||||
|
viper.AddConfigPath("/etc/openaccounting/")
|
||||||
|
viper.AddConfigPath("$HOME/.openaccounting")
|
||||||
|
|
||||||
|
// Enable environment variables
|
||||||
|
viper.AutomaticEnv()
|
||||||
|
viper.SetEnvPrefix("OA") // will look for OA_DATABASE_PASSWORD, etc.
|
||||||
|
|
||||||
|
// Set default values
|
||||||
|
viper.SetDefault("Address", "localhost")
|
||||||
|
viper.SetDefault("Port", 8080)
|
||||||
|
viper.SetDefault("DatabaseDriver", "sqlite")
|
||||||
|
viper.SetDefault("DatabaseFile", "./openaccounting.db")
|
||||||
|
viper.SetDefault("ApiPrefix", "/api/v1")
|
||||||
|
|
||||||
|
// Read configuration
|
||||||
|
err := viper.ReadInConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(fmt.Errorf("failed to open ./config.json with: %s", err.Error()))
|
log.Printf("Warning: Could not read config file: %v", err)
|
||||||
|
log.Println("Using environment variables and defaults")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal config into struct
|
||||||
|
err = viper.Unmarshal(&config)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Errorf("failed to unmarshal config: %s", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
decoder := json.NewDecoder(file)
|
// Parse database address (assuming format host:port for MySQL)
|
||||||
err = decoder.Decode(&config)
|
host := config.DatabaseAddress
|
||||||
|
port := "3306"
|
||||||
if err != nil {
|
if len(config.DatabaseAddress) > 0 {
|
||||||
log.Fatal(fmt.Errorf("failed to decode ./config.json with: %s", err.Error()))
|
// If there's a colon, split host and port
|
||||||
|
if colonIndex := len(config.DatabaseAddress); colonIndex > 0 {
|
||||||
|
host = config.DatabaseAddress
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connectionString := config.User + ":" + config.Password + "@" + config.DatabaseAddress + "/" + config.Database
|
// Default to SQLite if no driver specified
|
||||||
|
driver := config.DatabaseDriver
|
||||||
|
if driver == "" {
|
||||||
|
driver = "sqlite"
|
||||||
|
}
|
||||||
|
|
||||||
db, err := db.NewDB(connectionString)
|
// Initialize GORM database
|
||||||
|
dbConfig := &database.Config{
|
||||||
|
Driver: driver,
|
||||||
|
Host: host,
|
||||||
|
Port: port,
|
||||||
|
User: config.User,
|
||||||
|
Password: config.Password,
|
||||||
|
DBName: config.Database,
|
||||||
|
File: config.DatabaseFile,
|
||||||
|
SSLMode: "disable", // Adjust as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
err = database.Connect(dbConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(fmt.Errorf("failed to connect to database with: %s", err.Error()))
|
log.Fatal(fmt.Errorf("failed to connect to database with: %s", err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run migrations
|
||||||
|
err = database.AutoMigrate()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Errorf("failed to run migrations: %s", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
err = database.Migrate()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(fmt.Errorf("failed to run custom migrations: %s", err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
bc := &util.StandardBcrypt{}
|
bc := &util.StandardBcrypt{}
|
||||||
|
|
||||||
model.NewModel(db, bc, config)
|
// Create GORM repository and models
|
||||||
auth.NewAuthService(db, bc)
|
gormRepo := repository.NewGormRepository(database.DB)
|
||||||
|
gormModel := model.NewGormModel(database.DB, bc, config)
|
||||||
|
auth.NewGormAuthService(gormRepo, bc)
|
||||||
|
|
||||||
|
// Set the global model instance
|
||||||
|
model.Instance = gormModel
|
||||||
|
|
||||||
app, err := api.Init(config.ApiPrefix)
|
app, err := api.Init(config.ApiPrefix)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user