Vikunja now uses viper to handle config

This commit is contained in:
konrad 2018-09-08 13:29:35 +02:00
parent 4f3e016751
commit 427f752990
Signed by untrusted user: konrad
GPG Key ID: F40E70337AB24C9B
13 changed files with 256 additions and 109 deletions

3
.gitignore vendored
View File

@ -1,6 +1,7 @@
.idea/
.idea/*/*
config.ini
config.yml
config.yaml
*.db
Run
vikunja

170
Gopkg.lock generated
View File

@ -2,132 +2,294 @@
[[projects]]
digest = "1:a2c1d0e43bd3baaa071d1b9ed72c27d78169b2b269f71c105ac4ba34b1be4a39"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = "UT"
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
digest = "1:6cb5bf34f3e3bb61e76d976f5bd29d245b567f208e1fd7cb8104b736a5eb649d"
name = "github.com/dgrijalva/jwt-go"
packages = ["."]
pruneopts = "UT"
revision = "a539ee1a749a2b895533f979515ac7e6e0f5b650"
[[projects]]
digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd"
name = "github.com/fsnotify/fsnotify"
packages = ["."]
pruneopts = "UT"
revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9"
version = "v1.4.7"
[[projects]]
digest = "1:fe8a03a8222d5b913f256972933d26d24ad7c8286692a42943bc01633cc8fce3"
name = "github.com/go-ini/ini"
packages = ["."]
pruneopts = "UT"
revision = "358ee7663966325963d4e8b2e1fbd570c5195153"
version = "v1.38.1"
[[projects]]
digest = "1:d2b67246c3fa959edfa1be84b407cf0a0a4cabbace0843814b1729b5af808d9e"
name = "github.com/go-sql-driver/mysql"
packages = ["."]
pruneopts = "UT"
revision = "ee359f95877bdef36cbb602711e49b6f0becfca9"
[[projects]]
digest = "1:3f854136f2da9cde22fa0dd29e74fb7c920c5d79d060847fe9b96f2d3cfab746"
name = "github.com/go-xorm/builder"
packages = ["."]
pruneopts = "UT"
revision = "c8871c857d2555fbfbd8524f895be5386d3d8836"
[[projects]]
digest = "1:ee0b218753df985dd6633b13a894a69f0c1ea385f092f4afa093d407bb165cc5"
name = "github.com/go-xorm/core"
packages = ["."]
pruneopts = "UT"
revision = "f43c33d9a48db006417a7ac4c16b08897e3e1458"
version = "v0.5.8"
[[projects]]
digest = "1:8e0764e74dd6cf539d3c035772d3fd0009b89fff9889a1131139be6d871c90dd"
name = "github.com/go-xorm/xorm"
packages = ["."]
pruneopts = "UT"
revision = "29d4a0330a00b9be468b70e3fb0f74109348c358"
[[projects]]
digest = "1:c0d19ab64b32ce9fe5cf4ddceba78d5bc9807f0016db6b1183599da3dcc24d10"
name = "github.com/hashicorp/hcl"
packages = [
".",
"hcl/ast",
"hcl/parser",
"hcl/printer",
"hcl/scanner",
"hcl/strconv",
"hcl/token",
"json/parser",
"json/scanner",
"json/token",
]
pruneopts = "UT"
revision = "8cb6e5b959231cc1119e43259c4a608f9c51a241"
version = "v1.0.0"
[[projects]]
digest = "1:82c5850e702ccef3976cdfdf737725013587c64e02e5ecae57e86431163b27aa"
name = "github.com/labstack/echo"
packages = [
".",
"middleware"
"middleware",
]
pruneopts = "UT"
revision = "1049c9613cd371b7ea8f219404c9a821734781ed"
version = "v3.1.0"
[[projects]]
digest = "1:ef6158d11f87c8036114cf3d2bf5c50edb4aa0b4aab5deef26716a8bb674a9ad"
name = "github.com/labstack/gommon"
packages = [
"bytes",
"color",
"log",
"random"
"random",
]
pruneopts = "UT"
revision = "57409ada9da0f2afad6664c49502f8c50fbd8476"
version = "0.2.3"
[[projects]]
digest = "1:c568d7727aa262c32bdf8a3f7db83614f7af0ed661474b24588de635c20024c7"
name = "github.com/magiconair/properties"
packages = ["."]
pruneopts = "UT"
revision = "c2353362d570a7bfa228149c62842019201cfb71"
version = "v1.8.0"
[[projects]]
digest = "1:a36a1febe1240bb79a208390ad17e1080555b0031a9ed42a41eae173cca3fd74"
name = "github.com/mattn/go-colorable"
packages = ["."]
pruneopts = "UT"
revision = "ad5389df28cdac544c99bd7b9161a0b5b6ca9d1b"
[[projects]]
digest = "1:d4d17353dbd05cb52a2a52b7fe1771883b682806f68db442b436294926bbfafb"
name = "github.com/mattn/go-isatty"
packages = ["."]
pruneopts = "UT"
revision = "a5cdd64afdee435007ee3e9f6ed4684af949d568"
[[projects]]
digest = "1:3cafc6a5a1b8269605d9df4c6956d43d8011fc57f266ca6b9d04da6c09dee548"
name = "github.com/mattn/go-sqlite3"
packages = ["."]
pruneopts = "UT"
revision = "25ecb14adfc7543176f7d85291ec7dba82c6f7e4"
version = "v1.9.0"
[[projects]]
digest = "1:645110e089152bd0f4a011a2648fbb0e4df5977be73ca605781157ac297f50c4"
name = "github.com/mitchellh/mapstructure"
packages = ["."]
pruneopts = "UT"
revision = "fa473d140ef3c6adf42d6b391fe76707f1f243c8"
version = "v1.0.0"
[[projects]]
digest = "1:95741de3af260a92cc5c7f3f3061e85273f5a81b5db20d4bd68da74bd521675e"
name = "github.com/pelletier/go-toml"
packages = ["."]
pruneopts = "UT"
revision = "c01d1270ff3e442a8a57cddc1c92dc1138598194"
version = "v1.2.0"
[[projects]]
digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe"
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
pruneopts = "UT"
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
digest = "1:6a4a11ba764a56d2758899ec6f3848d24698d48442ebce85ee7a3f63284526cd"
name = "github.com/spf13/afero"
packages = [
".",
"mem",
]
pruneopts = "UT"
revision = "d40851caa0d747393da1ffb28f7f9d8b4eeffebd"
version = "v1.1.2"
[[projects]]
digest = "1:516e71bed754268937f57d4ecb190e01958452336fa73dbac880894164e91c1f"
name = "github.com/spf13/cast"
packages = ["."]
pruneopts = "UT"
revision = "8965335b8c7107321228e3e3702cab9832751bac"
version = "v1.2.0"
[[projects]]
digest = "1:68ea4e23713989dc20b1bded5d9da2c5f9be14ff9885beef481848edd18c26cb"
name = "github.com/spf13/jwalterweatherman"
packages = ["."]
pruneopts = "UT"
revision = "4a4406e478ca629068e7768fc33f3f044173c0a6"
version = "v1.0.0"
[[projects]]
digest = "1:dab83a1bbc7ad3d7a6ba1a1cc1760f25ac38cdf7d96a5cdd55cd915a4f5ceaf9"
name = "github.com/spf13/pflag"
packages = ["."]
pruneopts = "UT"
revision = "9a97c102cda95a86cec2345a6f09f55a939babf5"
version = "v1.0.2"
[[projects]]
digest = "1:6e30a27eac59a148b3f7a32e0ba54706b31dcde5a42f63b22cb47873b62fa343"
name = "github.com/spf13/viper"
packages = ["."]
pruneopts = "UT"
revision = "8fb642006536c8d3760c99d4fa2389f5e2205631"
version = "v1.2.0"
[[projects]]
digest = "1:a7496c8d47f794d15a6e41f8ada426d4a41c038fac9bd75c1abc30faacf469c9"
name = "github.com/stretchr/testify"
packages = ["assert"]
pruneopts = "UT"
revision = "87b1dfb5b2fa649f52695dd9eae19abe404a4308"
[[projects]]
branch = "master"
digest = "1:c468422f334a6b46a19448ad59aaffdfc0a36b08fdcc1c749a0b29b6453d7e59"
name = "github.com/valyala/bytebufferpool"
packages = ["."]
pruneopts = "UT"
revision = "e746df99fe4a3986f4d4f79e13c1e0117ce9c2f7"
[[projects]]
branch = "master"
digest = "1:268b8bce0064e8c057d7b913605459f9a26dcab864c0886a56d196540fbf003f"
name = "github.com/valyala/fasttemplate"
packages = ["."]
pruneopts = "UT"
revision = "dcecefd839c4193db0d35b88ec65b4c12d360ab0"
[[projects]]
digest = "1:456c96b87c9481d98aac8ef9862053a8fc97b981d26f6cd8d63de783dd24acec"
name = "golang.org/x/crypto"
packages = [
"acme",
"acme/autocert",
"bcrypt",
"blowfish"
"blowfish",
]
pruneopts = "UT"
revision = "9419663f5a44be8b34ca85f08abc5fe1be11f8a3"
[[projects]]
digest = "1:f1275b0d1ed7d43eeb7a0464a148258f04e66a4783514d5c790d4e970cc7df6d"
name = "golang.org/x/sys"
packages = ["unix"]
pruneopts = "UT"
revision = "314a259e304ff91bd6985da2a7149bbf91237993"
[[projects]]
digest = "1:8029e9743749d4be5bc9f7d42ea1659471767860f0cdc34d37c3111bd308a295"
name = "golang.org/x/text"
packages = [
"internal/gen",
"internal/triegen",
"internal/ucd",
"transform",
"unicode/cldr",
"unicode/norm",
]
pruneopts = "UT"
revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]]
digest = "1:59c645bd5db5ec4a889a1ac62ce9cb3c4483cc24c66907ea75de2516d6fe4716"
name = "gopkg.in/testfixtures.v2"
packages = ["."]
pruneopts = "UT"
revision = "1d98c34adfb14dbedeef37127968233b5d960f02"
version = "v2.4.5"
[[projects]]
digest = "1:73e6fda93622790d2371344759df06ff5ff2fac64a6b6e8832b792e7402956e7"
name = "gopkg.in/yaml.v2"
packages = ["."]
pruneopts = "UT"
revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4"
version = "v2.0.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "aec97fcf68fb5a8fdc8e80f6aeab7b4301c46eec4f911c8e79d2206a806424bd"
input-imports = [
"github.com/dgrijalva/jwt-go",
"github.com/go-ini/ini",
"github.com/go-sql-driver/mysql",
"github.com/go-xorm/core",
"github.com/go-xorm/xorm",
"github.com/labstack/echo",
"github.com/labstack/echo/middleware",
"github.com/mattn/go-sqlite3",
"github.com/spf13/viper",
"github.com/stretchr/testify/assert",
"golang.org/x/crypto/bcrypt",
"gopkg.in/testfixtures.v2",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@ -48,3 +48,7 @@
[prune]
go-tests = true
unused-packages = true
[[constraint]]
name = "github.com/spf13/viper"
version = "1.2.0"

View File

@ -1,14 +0,0 @@
[General]
JWTSecret = blablaGEHEMIN§)!§
; The interface on which to run the webserver
Interface = :8080
[Database]
Type = mysql
User = root
Password = supersecret
Host = 127.0.0.1
Database = vikunja
ShowQueries = false
; When using sqlite, this is the path where to store the data
; Path = ./vikunja.db

14
config.yml.sample Normal file
View File

@ -0,0 +1,14 @@
service:
JWTSecret: "blablaGEHEMIN§)!§"
# The interface on which to run the webserver
interface: ":8080"
database:
type: "sqlite"
user: "root"
password: "supersecret"
host: "127.0.0.1"
database: "vikunja"
showqueries: "true"
# When using sqlite, this is the path where to store the data
Path: "./vikunja.db"

View File

@ -6,6 +6,7 @@ import (
"context"
"fmt"
"github.com/spf13/viper"
"os"
"os/signal"
"time"
@ -17,7 +18,7 @@ var Version = "0.1"
func main() {
// Init Config
err := models.SetConfig()
err := models.InitConfig()
if err != nil {
fmt.Println(err)
os.Exit(1)
@ -38,7 +39,7 @@ func main() {
routes.RegisterRoutes(e)
// Start server
go func() {
if err := e.Start(models.Config.Interface); err != nil {
if err := e.Start(viper.GetString("service.interface")); err != nil {
e.Logger.Info("shutting down...")
}
}()

View File

@ -1,28 +1,57 @@
package models
import (
"github.com/go-ini/ini"
"crypto/rand"
"fmt"
"github.com/spf13/viper"
"os"
"strings"
)
// ConfigStruct holds the config struct
type ConfigStruct struct {
Database struct {
Type string
Host string
User string
Password string
Database string
Path string
ShowQueries bool
func InitConfig() (err error) {
// Set defaults
// Service config
random, err := random(32)
if err != nil {
return err
}
JWTLoginSecret []byte
Interface string
viper.SetDefault("service.JWTSecret", random)
viper.SetDefault("service.interface", ":3456")
// Database
viper.SetDefault("database.type", "sqlite")
viper.SetDefault("database.host", "localhost")
viper.SetDefault("database.user", "vikunja")
viper.SetDefault("database.password", "")
viper.SetDefault("database.database", "vikunja")
viper.SetDefault("database.path", "./vikunja.db")
viper.SetDefault("database.showqueries", false)
// Init checking for environment variables
viper.SetEnvPrefix("vikunja")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
// Load the config file
viper.AddConfigPath(".")
viper.SetConfigName("config")
err = viper.ReadInConfig()
if err != nil {
return
}
return
}
// Config holds the configuration for the program
var Config = new(ConfigStruct)
func random(length int) (string, error) {
b := make([]byte, length)
if _, err := rand.Read(b); err != nil {
return "", err
}
return fmt.Sprintf("%X", b), nil
}
// SetConfig initianlises the config and publishes it for other functions to use
func SetConfig() (err error) {
@ -33,25 +62,25 @@ func SetConfig() (err error) {
}
// Load the config
cfg, err := ini.Load("config.ini")
//cfg, err := ini.Load("config.ini")
if err != nil {
return err
}
// Map the config to our struct
err = cfg.MapTo(Config)
//err = cfg.MapTo(Config)
if err != nil {
return err
}
// Set default value for interface to listen on
Config.Interface = cfg.Section("General").Key("Interface").String()
/*Config.Interface = cfg.Section("General").Key("Interface").String()
if Config.Interface == "" {
Config.Interface = ":8080"
}
// JWT secret
Config.JWTLoginSecret = []byte(cfg.Section("General").Key("JWTSecret").String())
Config.JWTLoginSecret = []byte(cfg.Section("General").Key("JWTSecret").String())*/
return nil
}

View File

@ -1,61 +0,0 @@
package models
import (
"github.com/stretchr/testify/assert"
"io/ioutil"
"os"
"testing"
)
func TestSetConfig(t *testing.T) {
// Create test database
assert.NoError(t, PrepareTestDatabase())
// This should fail as it is looking for a nonexistent config
err := SetConfig()
assert.Error(t, err)
// Write an invalid config
configString := `[General
JWTSecret = Supersecret
Interface = ; This should make it automatically to :8080
[Database
Type = sqlite
Path = ./library.db`
err = ioutil.WriteFile("config.ini", []byte(configString), 0644)
assert.NoError(t, err)
// Test setConfig (should fail as we're trying to parse an invalid config)
err = SetConfig()
assert.Error(t, err)
// Delete the invalid file
err = os.Remove("config.ini")
assert.NoError(t, err)
// Write a fake config
configString = `[General]
JWTSecret = Supersecret
Interface = ; This should make it automatically to :8080
[Database]
Type = sqlite
Path = ./library.db`
err = ioutil.WriteFile("config.ini", []byte(configString), 0644)
assert.NoError(t, err)
// Test setConfig
err = SetConfig()
assert.NoError(t, err)
// Check for the values
assert.Equal(t, []byte("Supersecret"), Config.JWTLoginSecret)
assert.Equal(t, string(":8080"), Config.Interface)
assert.Equal(t, string("sqlite"), Config.Database.Type)
assert.Equal(t, string("./library.db"), Config.Database.Path)
// Remove the dummy config
err = os.Remove("config.ini")
assert.NoError(t, err)
}

View File

@ -6,6 +6,7 @@ import (
"github.com/go-xorm/core"
"github.com/go-xorm/xorm"
_ "github.com/mattn/go-sqlite3" // Because.
"github.com/spf13/viper"
)
var (
@ -16,14 +17,18 @@ var (
func getEngine() (*xorm.Engine, error) {
// Use Mysql if set
if Config.Database.Type == "mysql" {
connStr := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=true",
Config.Database.User, Config.Database.Password, Config.Database.Host, Config.Database.Database)
if viper.GetString("database.type") == "mysql" {
connStr := fmt.Sprintf(
"%s:%s@tcp(%s)/%s?charset=utf8&parseTime=true",
viper.GetString("database.user"),
viper.GetString("database.password"),
viper.GetString("database.host"),
viper.GetString("database.database"))
return xorm.NewEngine("mysql", connStr)
}
// Otherwise use sqlite
path := Config.Database.Path
path := viper.GetString("database.path")
if path == "" {
path = "./db.db"
}
@ -63,7 +68,7 @@ func SetEngine() (err error) {
return fmt.Errorf("sync database struct error: %v", err)
}
x.ShowSQL(Config.Database.ShowQueries)
x.ShowSQL(viper.GetBool("database.showqueries"))
return nil
}

View File

@ -1,12 +1,13 @@
package models
import (
"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"testing"
)
func TestSetEngine(t *testing.T) {
Config.Database.Path = "file::memory:?cache=shared"
viper.Set("database.path", "file::memory:?cache=shared")
err := SetEngine()
assert.NoError(t, err)
}

View File

@ -19,6 +19,9 @@ func MainTest(m *testing.M, pathToRoot string) {
os.Exit(1)
}
// Create test database
PrepareTestDatabase()
os.Exit(m.Run())
}

View File

@ -6,6 +6,7 @@ import (
"encoding/hex"
"github.com/dgrijalva/jwt-go"
"github.com/labstack/echo"
"github.com/spf13/viper"
"net/http"
"time"
)
@ -57,7 +58,7 @@ func Login(c echo.Context) error {
claims["avatar"] = hex.EncodeToString(avatar[:])
// Generate encoded token and send it as response.
t, err := token.SignedString(models.Config.JWTLoginSecret)
t, err := token.SignedString([]byte(viper.GetString("service.JWTSecret")))
if err != nil {
return err
}

View File

@ -34,6 +34,7 @@ import (
apiv1 "code.vikunja.io/api/routes/api/v1"
_ "code.vikunja.io/api/routes/api/v1/swagger" // for docs generation
"code.vikunja.io/api/routes/crud"
"github.com/spf13/viper"
)
// NewEcho registers a new Echo instance
@ -67,7 +68,7 @@ func RegisterRoutes(e *echo.Echo) {
// ===== Routes with Authetification =====
// Authetification
a.Use(middleware.JWT(models.Config.JWTLoginSecret))
a.Use(middleware.JWT([]byte(viper.GetString("service.JWTSecret"))))
a.POST("/tokenTest", apiv1.CheckToken)
listHandler := &crud.WebHandler{