package main import ( "net/http" "encoding/json" "time" "os" "golang.org/x/crypto/bcrypt" "github.com/azukaar/cosmos-server/src/utils" "github.com/azukaar/cosmos-server/src/docker" ) func waitForDB() { time.Sleep(1 * time.Second) err := utils.DB() if err != nil { utils.Warn("DB Not ready yet") waitForDB() } } type NewInstallJSON struct { MongoDBMode string `json:"mongodbMode"` MongoDB string `json:"mongodb"` HTTPSCertificateMode string `json:"httpsCertificateMode"` TLSCert string `json:"tlsCert"` TLSKey string `json:"tlsKey"` Nickname string `json:"nickname"` Password string `json:"password"` Email string `json:"omitempty,email"` Hostname string `json:"hostname"` Step string `json:"step"` SSLEmail string `json:"sslEmail",validate:"omitempty,email"` UseWildcardCertificate bool `json:"useWildcardCertificate",validate:"omitempty"` DNSChallengeProvider string `json:"dnsChallengeProvider",validate:"omitempty"` DNSChallengeConfig map[string]string } type AdminJSON struct { Nickname string `validate:"required,min=3,max=32,alphanum"` Password string `validate:"required,min=9,max=128,containsany=~!@#$%^&*()_+=-{[}]:;"'<>.?/,containsany=ABCDEFGHIJKLMNOPQRSTUVWXYZ,containsany=abcdefghijklmnopqrstuvwxyz,containsany=0123456789"` } func NewInstallRoute(w http.ResponseWriter, req *http.Request) { if !utils.GetMainConfig().NewInstall { utils.Error("Status: not a new New install", nil) utils.HTTPError(w, "New install", http.StatusForbidden, "NI001") return } if(req.Method == "POST") { var request NewInstallJSON err1 := json.NewDecoder(req.Body).Decode(&request) if err1 != nil { utils.Error("NewInstall: Invalid User Request", err1) utils.HTTPError(w, "New Install: Invalid User Request" + err1.Error(), http.StatusInternalServerError, "NI001") return } errV := utils.Validate.Struct(request) if errV != nil { utils.Error("NewInstall: Invalid User Request", errV) utils.HTTPError(w, "New Install: Invalid User Request " + errV.Error(), http.StatusInternalServerError, "NI001") return } newConfig := utils.GetBaseMainConfig() if(request.Step == "-1") { // remove everythin in /config utils.Log("NewInstall: Step cleanup") utils.Log("NewInstall: Removing config file") configFile := utils.GetConfigFileName() os.Remove(configFile) if(os.Getenv("HOSTNAME") != "") { utils.Log("NewInstall: Emptying /config") os.RemoveAll("/config") os.Mkdir("/config", 0700) } utils.DisconnectDB() LoadConfig() } if(request.Step == "2") { utils.Log("NewInstall: Step Database") // User Management & Mongo DB if(request.MongoDBMode == "DisableUserManagement") { utils.Log("NewInstall: Disable User Management") newConfig.DisableUserManagement = true utils.SaveConfigTofile(newConfig) utils.LoadBaseMainConfig(newConfig) } else if (request.MongoDBMode == "Provided") { utils.Log("NewInstall: DB Provided") newConfig.DisableUserManagement = false newConfig.MongoDB = request.MongoDB utils.SaveConfigTofile(newConfig) utils.LoadBaseMainConfig(newConfig) } else if (request.MongoDBMode == "Create") { utils.Log("NewInstall: Create DB") newConfig.DisableUserManagement = false strco, err := docker.NewDB(w, req) if err != nil { utils.Error("NewInstall: Error creating MongoDB", err) return } newConfig.MongoDB = strco utils.SaveConfigTofile(newConfig) utils.LoadBaseMainConfig(newConfig) utils.Log("NewInstall: MongoDB created, waiting for it to be ready") waitForDB() w.WriteHeader(http.StatusOK) return } else { utils.Log("NewInstall: Invalid MongoDBMode") utils.Error("NewInstall: Invalid MongoDBMode", nil) utils.HTTPError(w, "New Install: Invalid MongoDBMode", http.StatusInternalServerError, "NI001") return } } else if (request.Step == "3") { // HTTPS Certificate Mode & Certs & Let's Encrypt newConfig.HTTPConfig.HTTPSCertificateMode = request.HTTPSCertificateMode newConfig.HTTPConfig.SSLEmail = request.SSLEmail newConfig.HTTPConfig.UseWildcardCertificate = request.UseWildcardCertificate newConfig.HTTPConfig.DNSChallengeProvider = request.DNSChallengeProvider newConfig.HTTPConfig.DNSChallengeConfig = request.DNSChallengeConfig newConfig.HTTPConfig.TLSCert = request.TLSCert newConfig.HTTPConfig.TLSKey = request.TLSKey // Hostname newConfig.HTTPConfig.Hostname = request.Hostname utils.SaveConfigTofile(newConfig) utils.LoadBaseMainConfig(newConfig) } else if (request.Step == "4") { adminObj := AdminJSON{ Nickname: request.Nickname, Password: request.Password, } errV2 := utils.Validate.Struct(adminObj) if errV2 != nil { utils.Error("NewInstall: Invalid User Request", errV2) utils.HTTPError(w, errV2.Error(), http.StatusInternalServerError, "UL001") return } // Admin User c, errCo := utils.GetCollection(utils.GetRootAppId(), "users") if errCo != nil { utils.Error("Database Connect", errCo) utils.HTTPError(w, "Database", http.StatusInternalServerError, "DB001") return } nickname := utils.Sanitize(request.Nickname) hashedPassword, err2 := bcrypt.GenerateFromPassword([]byte(request.Password), 14) if err2 != nil { utils.Error("NewInstall: Error hashing password", err2) utils.HTTPError(w, "New Install: Error hashing password " + err2.Error(), http.StatusInternalServerError, "NI001") return } // pre-remove every users _, err4 := c.DeleteMany(nil, map[string]interface{}{}) if err4 != nil { utils.Error("NewInstall: Error deleting users", err4) utils.HTTPError(w, "New Install: Error deleting users " + err4.Error(), http.StatusInternalServerError, "NI001") return } _, err3 := c.InsertOne(nil, map[string]interface{}{ "Nickname": nickname, "Email": request.Email, "Password": hashedPassword, "Role": utils.ADMIN, "PasswordCycle": 0, "CreatedAt": time.Now(), "RegisteredAt": time.Now(), }) if err3 != nil { utils.Error("NewInstall: Error creating admin user", err3) utils.HTTPError(w, "New Install: Error creating admin user " + err3.Error(), http.StatusInternalServerError, "NI001") return } } else if (request.Step == "5") { newConfig.NewInstall = false utils.SaveConfigTofile(newConfig) os.Exit(0) } json.NewEncoder(w).Encode(map[string]interface{}{ "status": "OK", }) } else { utils.Error("UserList: Method not allowed" + req.Method, nil) utils.HTTPError(w, "Method not allowed", http.StatusMethodNotAllowed, "HTTP001") return } }