Cosmos-Server/src/newInstall.go
2023-07-02 16:12:31 +01:00

209 lines
6.5 KiB
Go

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
}
}