diff --git a/configuration/config.go b/configuration/config.go index 65765ee..18e8fe3 100644 --- a/configuration/config.go +++ b/configuration/config.go @@ -23,9 +23,10 @@ package configuration import ( "flag" - "github.com/zpatrick/go-config" "log" "os" + + "github.com/zpatrick/go-config" ) // Global configuration @@ -50,22 +51,28 @@ func InitConfig() error { port = flag.String("port", "4000", "Port of the backend (default is 4000)") baseHost = flag.String("base-host", "localhost:4000", "The host at which the backend is hosted (default: localhost)") basePath = flag.String("base-path", "/api/v2", "The path at which the API routes are located (default /api/v2)") + adminUser = flag.String("admin-user", "", "Initial admin username") + adminPass = flag.String("admin-pass", "", "Initial admin password") + adminMail = flag.String("admin-mail", "", "Initial admin mail address") ) flag.Parse() static := map[string]string{ - "db.host": *dbHost, - "db.name": *dbName, - "db.user": *dbUser, - "db.pass": *dbPass, - "db.ssl": *dbSSLMode, - "amqp.host": *amqpHost, - "amqp.user": *amqpUser, - "amqp.pass": *amqpPass, - "mode": *mode, - "port": *port, - "base.host": *baseHost, - "base.path": *basePath, + "db.host": *dbHost, + "db.name": *dbName, + "db.user": *dbUser, + "db.pass": *dbPass, + "db.ssl": *dbSSLMode, + "amqp.host": *amqpHost, + "amqp.user": *amqpUser, + "amqp.pass": *amqpPass, + "mode": *mode, + "port": *port, + "base.host": *baseHost, + "base.path": *basePath, + "admin.user": *adminUser, + "admin.pass": *adminPass, + "admin.mail": *adminMail, } mappings := map[string]string{ @@ -81,6 +88,9 @@ func InitConfig() error { "BASE_PATH": "base.path", "MODE": "mode", "PORT": "port", + "ADMIN_USER": "admin.user", + "ADMIN_PASS": "admin.pass", + "ADMIN_MAIL": "admin.mail", } defaults := config.NewStatic(static) @@ -151,5 +161,4 @@ func ConfigureBackend() (string, string, string, string, string, string, string, AMQPpass, _ := GolbalConfig.String("amqp.pass") return mode, baseHost, basePath, port, AMQPhost, AMQPuser, AMQPpass, nil - } diff --git a/helper/test_data.go b/helper/test_data.go index 0d6f304..c04d757 100644 --- a/helper/test_data.go +++ b/helper/test_data.go @@ -24,10 +24,14 @@ package helper import ( "encoding/json" "fmt" + "math/rand" + "strings" + "time" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" "github.com/jinzhu/gorm/dialects/postgres" + "github.com/zpatrick/go-config" "golang.org/x/crypto/bcrypt" - "time" ) // ####################################################################### @@ -321,8 +325,22 @@ var WidgetE = database.Widget{ SignalIDs: []int64{}, } -// add a default admin user to the DB -func DBAddAdminUser() error { +func generatePassword(Len int) string { + rand.Seed(time.Now().UnixNano()) + chars := []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + + "abcdefghijklmnopqrstuvwxyz" + + "0123456789") + + var b strings.Builder + for i := 0; i < Len; i++ { + b.WriteRune(chars[rand.Intn(len(chars))]) + } + + return b.String() +} + +// DBAddAdminUser adds a default admin user to the DB +func DBAddAdminUser(cfg *config.Config) error { database.DBpool.AutoMigrate(&database.User{}) // Check if admin user exists in DB @@ -331,10 +349,31 @@ func DBAddAdminUser() error { if len(users) == 0 { fmt.Println("No admin user found in DB, adding default admin user.") - //create a copy of global test data - user0 := User0 + + name, err := cfg.String("admin.user") + if err != nil || name == "" { + name = "admin" + } + + pw, err := cfg.String("admin.pass") + if err != nil || pw == "" { + pw = generatePassword(16) + fmt.Printf(" Generated admin password: %s\n", pw) + } + + mail, err := cfg.String("admin.mail") + if err == nil || mail == "" { + mail = "admin@example.com" + } + + pwEnc, _ := bcrypt.GenerateFromPassword([]byte(pw), bcryptCost) + + // create a copy of global test data + user := database.User{Username: name, Password: string(pwEnc), + Role: "Admin", Mail: mail, Active: true} + // add admin user to DB - err = database.DBpool.Create(&user0).Error + err = database.DBpool.Create(&user).Error } return err diff --git a/routes/register.go b/routes/register.go index 4cc5983..4d49d79 100644 --- a/routes/register.go +++ b/routes/register.go @@ -25,6 +25,12 @@ package routes import ( "bytes" "fmt" + "io" + "mime/multipart" + "net/http" + "net/http/httptest" + "os" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" "git.rwth-aachen.de/acs/public/villas/web-backend-go/helper" component_configuration "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes/component-configuration" @@ -40,11 +46,7 @@ import ( "github.com/gin-gonic/gin" ginSwagger "github.com/swaggo/gin-swagger" "github.com/swaggo/gin-swagger/swaggerFiles" - "io" - "mime/multipart" - "net/http" - "net/http/httptest" - "os" + "github.com/zpatrick/go-config" ) // register all backend endpoints; to be called after DB is initialized @@ -74,12 +76,18 @@ func RegisterEndpoints(router *gin.Engine, api *gin.RouterGroup) { } // Uses API endpoints to add test data to the backend; All endpoints have to be registered before invoking this function. -func AddTestData(basePath string, router *gin.Engine) (*bytes.Buffer, error) { +func AddTestData(cfg *config.Config, router *gin.Engine) (*bytes.Buffer, error) { + + basePath, err := cfg.String("base.path") + if err != nil { + fmt.Println("error: testdata could not be added to DB: no base path specified") + return nil, err + } database.MigrateModels() // Create entries of each model (data defined in test_data.go) // add Admin user - err := helper.DBAddAdminUser() + err = helper.DBAddAdminUser(cfg) if err != nil { return nil, err } diff --git a/start.go b/start.go index c229163..3b0cf5a 100644 --- a/start.go +++ b/start.go @@ -23,6 +23,8 @@ package main import ( "fmt" + "log" + "git.rwth-aachen.de/acs/public/villas/web-backend-go/amqp" "git.rwth-aachen.de/acs/public/villas/web-backend-go/configuration" "git.rwth-aachen.de/acs/public/villas/web-backend-go/database" @@ -30,23 +32,23 @@ import ( "git.rwth-aachen.de/acs/public/villas/web-backend-go/helper" "git.rwth-aachen.de/acs/public/villas/web-backend-go/routes" "github.com/gin-gonic/gin" - "log" + "github.com/zpatrick/go-config" ) -func addData(router *gin.Engine, mode string, basePath string) error { +func addData(router *gin.Engine, cfg *config.Config) error { - if mode == "test" { + if mode, err := cfg.String("mode"); err == nil && mode == "test" { // test mode: drop all tables and add test data to DB database.DropTables() log.Println("Database tables dropped, using API to add test data") - resp, err := routes.AddTestData(basePath, router) + resp, err := routes.AddTestData(cfg, router) if err != nil { fmt.Println("error: testdata could not be added to DB:", err.Error(), "Response body: ", resp) return err } } else { // release mode: make sure that at least one admin user exists in DB - err := helper.DBAddAdminUser() + err := helper.DBAddAdminUser(cfg) if err != nil { fmt.Println("error: adding admin user failed:", err.Error()) return err @@ -95,7 +97,7 @@ func main() { apidocs.SwaggerInfo.BasePath = basePath // add data to DB (if any) - err = addData(r, mode, basePath) + err = addData(r, configuration.GolbalConfig) if err != nil { panic(err) }