diff --git a/edition/boot/runtime.go b/edition/boot/runtime.go new file mode 100644 index 00000000..827abcc7 --- /dev/null +++ b/edition/boot/runtime.go @@ -0,0 +1,132 @@ +// Copyright 2016 Documize Inc. . All rights reserved. +// +// This software (Documize Community Edition) is licensed under +// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html +// +// You can operate outside the AGPL restrictions by purchasing +// Documize Enterprise Edition and obtaining a commercial license +// by contacting . +// +// https://documize.com + +// Package boot prepares runtime environment. +package boot + +import ( + "crypto/rand" + "fmt" + "strings" + "time" + + "github.com/documize/community/core/database" + "github.com/documize/community/core/env" + "github.com/documize/community/core/web" + "github.com/jmoiron/sqlx" +) + +// InitRuntime prepares runtime using command line and environment variables. +func InitRuntime(r *env.Runtime) bool { + // Prepare DB + db, err := sqlx.Open("mysql", stdConn(r.Flags.DBConn)) + if err != nil { + r.Log.Error("unable to setup database", err) + } + + r.Db = db + r.Db.SetMaxIdleConns(30) + r.Db.SetMaxOpenConns(100) + r.Db.SetConnMaxLifetime(time.Second * 14400) + + err = r.Db.Ping() + if err != nil { + r.Log.Error("unable to connect to database, connection string should be of the form: '"+ + "username:password@tcp(host:3306)/database'", err) + return false + } + + // go into setup mode if required + if r.Flags.SiteMode != web.SiteModeOffline { + if database.Check(*r) { + if err := database.Migrate(true /* the config table exists */); err != nil { + r.Log.Error("unable to run database migration", err) + return false + } + } else { + r.Log.Info("going into setup mode to prepare new database") + } + } + + // Prepare SALT + if r.Flags.Salt == "" { + b := make([]byte, 17) + + _, err := rand.Read(b) + if err != nil { + r.Log.Error("problem using crypto/rand", err) + return false + } + + for k, v := range b { + if (v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z') || (v >= '0' && v <= '0') { + b[k] = v + } else { + s := fmt.Sprintf("%x", v) + b[k] = s[0] + } + } + + r.Flags.Salt = string(b) + r.Log.Info("please set DOCUMIZESALT or use -salt with this value: " + r.Flags.Salt) + } + + // Prepare HTTP ports + if r.Flags.SSLCertFile == "" && r.Flags.SSLKeyFile == "" { + if r.Flags.HTTPPort == "" { + r.Flags.HTTPPort = "80" + } + } else { + if r.Flags.HTTPPort == "" { + r.Flags.HTTPPort = "443" + } + } + + return true +} + +var stdParams = map[string]string{ + "charset": "utf8", + "parseTime": "True", + "maxAllowedPacket": "4194304", // 4194304 // 16777216 = 16MB +} + +func stdConn(cs string) string { + queryBits := strings.Split(cs, "?") + ret := queryBits[0] + "?" + retFirst := true + if len(queryBits) == 2 { + paramBits := strings.Split(queryBits[1], "&") + for _, pb := range paramBits { + found := false + if assignBits := strings.Split(pb, "="); len(assignBits) == 2 { + _, found = stdParams[strings.TrimSpace(assignBits[0])] + } + if !found { // if we can't work out what it is, put it through + if retFirst { + retFirst = false + } else { + ret += "&" + } + ret += pb + } + } + } + for k, v := range stdParams { + if retFirst { + retFirst = false + } else { + ret += "&" + } + ret += k + "=" + v + } + return ret +} diff --git a/edition/community.go b/edition/community.go index d6ffd050..3cbf4f88 100644 --- a/edition/community.go +++ b/edition/community.go @@ -13,22 +13,17 @@ package main import ( - "crypto/rand" "fmt" - "strings" - "time" "github.com/documize/community/core/api" "github.com/documize/community/core/api/endpoint" "github.com/documize/community/core/api/request" - "github.com/documize/community/core/database" "github.com/documize/community/core/env" "github.com/documize/community/core/section" - "github.com/documize/community/core/web" + "github.com/documize/community/edition/boot" "github.com/documize/community/edition/logging" _ "github.com/documize/community/embed" // the compressed front-end code and static data _ "github.com/go-sql-driver/mysql" // the mysql driver is required behind the scenes - "github.com/jmoiron/sqlx" ) func init() { @@ -54,7 +49,7 @@ func init() { // parse settings from command line and environment runtime.Flags = env.ParseFlags() - flagsOK := flagPrep(&runtime) + flagsOK := boot.InitRuntime(&runtime) if flagsOK { // runtime.Log = runtime.Log.SetDB(runtime.Db) @@ -66,118 +61,8 @@ func init() { } func main() { - - // process the db value first - // env.Parse("db") - section.Register() ready := make(chan struct{}, 1) // channel is used for testing endpoint.Serve(ready) } - -func flagPrep(r *env.Runtime) bool { - // Prepare DB - db, err := sqlx.Open("mysql", stdConn(r.Flags.DBConn)) - if err != nil { - r.Log.Error("unable to setup database", err) - } - - r.Db = db - r.Db.SetMaxIdleConns(30) - r.Db.SetMaxOpenConns(100) - r.Db.SetConnMaxLifetime(time.Second * 14400) - - err = r.Db.Ping() - if err != nil { - r.Log.Error("unable to connect to database, connection string should be of the form: '"+ - "username:password@tcp(host:3306)/database'", err) - return false - } - - // go into setup mode if required - if r.Flags.SiteMode != web.SiteModeOffline { - if database.Check(*r) { - if err := database.Migrate(true /* the config table exists */); err != nil { - r.Log.Error("unable to run database migration", err) - return false - } - } else { - r.Log.Info("going into setup mode to prepare new database") - } - } - - // Prepare SALT - if r.Flags.Salt == "" { - b := make([]byte, 17) - - _, err := rand.Read(b) - if err != nil { - r.Log.Error("problem using crypto/rand", err) - return false - } - - for k, v := range b { - if (v >= 'a' && v <= 'z') || (v >= 'A' && v <= 'Z') || (v >= '0' && v <= '0') { - b[k] = v - } else { - s := fmt.Sprintf("%x", v) - b[k] = s[0] - } - } - - r.Flags.Salt = string(b) - r.Log.Info("please set DOCUMIZESALT or use -salt with this value: " + r.Flags.Salt) - } - - // Prepare HTTP ports - if r.Flags.SSLCertFile == "" && r.Flags.SSLKeyFile == "" { - if r.Flags.HTTPPort == "" { - r.Flags.HTTPPort = "80" - } - } else { - if r.Flags.HTTPPort == "" { - r.Flags.HTTPPort = "443" - } - } - - return true -} - -var stdParams = map[string]string{ - "charset": "utf8", - "parseTime": "True", - "maxAllowedPacket": "4194304", // 4194304 // 16777216 = 16MB -} - -func stdConn(cs string) string { - queryBits := strings.Split(cs, "?") - ret := queryBits[0] + "?" - retFirst := true - if len(queryBits) == 2 { - paramBits := strings.Split(queryBits[1], "&") - for _, pb := range paramBits { - found := false - if assignBits := strings.Split(pb, "="); len(assignBits) == 2 { - _, found = stdParams[strings.TrimSpace(assignBits[0])] - } - if !found { // if we can't work out what it is, put it through - if retFirst { - retFirst = false - } else { - ret += "&" - } - ret += pb - } - } - } - for k, v := range stdParams { - if retFirst { - retFirst = false - } else { - ret += "&" - } - ret += k + "=" + v - } - return ret -}