package main import ( "database/sql" "flag" "fmt" "os" "os/user" "strconv" "strings" "text/template" _ "github.com/go-sql-driver/mysql" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/postgres" liblog "dev.sum7.eu/sum7/warehost/lib/log" host "dev.sum7.eu/sum7/warehost/modul/host" web "dev.sum7.eu/sum7/warehost/modul/web" system "dev.sum7.eu/sum7/warehost/system" ) var ( configFile string dbconnection *gorm.DB dbDB *sql.DB config *Config ) func main() { var err error flag.StringVar(&configFile, "c", "config.yml", "path of configuration file") flag.Parse() config = ReadConfigFile(configFile) liblog.NewLogger(config.Log.Path) // Main Databaseconnection dbconnection, err = gorm.Open("postgres", config.WarehostDatabase) if err != nil { liblog.Log.Fatal("database connection: ", err) } defer dbconnection.Close() dbconnection.Callback().Create().Remove("gorm:update_time_stamp") dbconnection.Callback().Update().Remove("gorm:update_time_stamp") dbconnection.SingularTable(true) dbconnection.LogMode(config.DatabaseDebug) //load system Models to database system.SyncModels(dbconnection) web.SyncModels(dbconnection) host.SyncModels(dbconnection) u, _ := user.Lookup(config.PathUser) userid, _ := strconv.Atoi(u.Uid) g, _ := user.LookupGroup(config.PathGroup) groupid, _ := strconv.Atoi(g.Gid) if config.FTP.Enable { var logins []*system.Login dbconnection.Joins("LEFT JOIN host_profil profil ON profil.login=login.id").Where("profil.id IS NOT NULL").Find(&logins) for _, login := range logins { path := fmt.Sprintf(config.FTP.PathID, login.ID) err = os.Mkdir(path, 0770) if err != nil && !strings.Contains(err.Error(), "file exists") { liblog.Log.Warn("ftp folder: ", err) } else { os.Chown(path, userid, groupid) liblog.Log.Info("ftp folder: ", path) } } } if config.WebModul.Enable { var sites []*web.Website dbconnection.Find(&sites) for _, site := range sites { path := fmt.Sprintf(config.WebModul.PathID, site.ID) err = os.Mkdir(path, 0770) if err != nil && !strings.Contains(err.Error(), "file exists") { liblog.Log.Warn("web modul folder: ", err) } else { os.Chown(path, userid, groupid) liblog.Log.Info("web modul folder: ", path) } } } // Configurate Webserver if config.Web.Enable { tmpl, err := template.ParseFiles(config.Web.ConfigurationTemplate) if err != nil { liblog.Log.Warning("load template: ", err) } file, err := os.OpenFile(config.Web.ConfigurationFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0660) defer file.Close() if err != nil { liblog.Log.Warning("open configfile: ", err) } var web []*host.Web dbconnection.Preload("Domain.Profil.Login").Order("length(subdomain) asc").Find(&web) for _, item := range web { if item.Domain.Active && item.Domain.Web && item.Domain.Profil.Login.Active { path := config.Web.PathDomain if len(item.Subdomain) > 0 { path = fmt.Sprintf("%s/%s.%s", path, item.Subdomain, item.Domain.FQDN) } else { path = fmt.Sprintf("%s/%s", path, item.Domain.FQDN) } err = os.Mkdir(path, 0770) if err != nil && !strings.Contains(err.Error(), "file exists") { liblog.Log.Warn("domain folder: ", err) } else { os.Chown(path, userid, groupid) } err = tmpl.Execute(file, item) if err != nil { liblog.Log.Warn("write config: ", err) } } } } // Configurate Database if config.Database.Enable { dbDB, err = sql.Open(config.Database.Type, config.Database.Connection) if err != nil { liblog.Log.Fatal("connection to mgmt db: ", err) } q, err := dbDB.Query(fmt.Sprintf("show databases LIKE \"%s%%\";", config.Database.Prefix)) if err != nil { liblog.Log.Fatal("list current dbs in mgmt db: ", err) } defer q.Close() var dbName string currentDBS := map[int64]struct{}{} for q.Next() { q.Scan(&dbName) dbName = strings.TrimPrefix(dbName, config.Database.Prefix) i, err := strconv.ParseInt(dbName, 10, 64) if err != nil { liblog.Log.Warning("listed current dbs to id in mgmt db: ", err) } else { currentDBS[i] = struct{}{} } } var dbs []*host.Database if dbconnection.Find(&dbs).Error != nil { liblog.Log.Warning("list in mgmt db: ", err) } else { liblog.Log.Info("count of mgmt db: ", len(dbs)) } shouldDB := map[int64]*host.Database{} for _, i := range dbs { name := fmt.Sprintf("%s%d", config.Database.Prefix, i.ID) shouldDB[i.ID] = i _, err = dbDB.Exec("CREATE USER IF NOT EXISTS ?@'localhost' IDENTIFIED BY ?;", name, i.Password) if err != nil { liblog.Log.Warning("configurate user of mgmt db: ", err) continue } _, err = dbDB.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", name)) if err != nil { liblog.Log.Warning("configurate db of mgmt db: ", err) continue } _, err = dbDB.Exec(fmt.Sprintf("GRANT ALL ON %s.* TO ?@'localhost' WITH GRANT OPTION;", name), name) if err != nil { liblog.Log.Warning("configurate permission db of mgmt db: ", err) continue } if len(i.Password) > 1 { _, err = dbDB.Exec("SET PASSWORD FOR ?@'localhost'=PASSWORD(?);", name, i.Password) if err != nil { liblog.Log.Info("configurate new password of mgmt db: ", name) continue } else { i.Password = "" dbconnection.Save(i) } } liblog.Log.Info("configurate of mgmt db: ", name) } for id := range currentDBS { if ok := shouldDB[id]; ok == nil { name := fmt.Sprintf("%s%d", config.Database.Prefix, id) _, err = dbDB.Exec(fmt.Sprintf("DROP USER IF EXISTS %s@'localhost';", name)) if err != nil { liblog.Log.Info("drop of mgmt db: ", name, err) } else { liblog.Log.Warning("count of mgmt db: ", name) dbDB.Query(fmt.Sprintf("DROP DATABASE IF EXISTS %s;", name)) } } } } }