add warehost-host and working on warehost-ftp
This commit is contained in:
parent
e0c93cc4a5
commit
67ee4a8559
|
@ -2,7 +2,6 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
|
||||||
|
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
@ -18,7 +17,7 @@ func ReadConfigFile(path string) *Config {
|
||||||
file, _ := ioutil.ReadFile(path)
|
file, _ := ioutil.ReadFile(path)
|
||||||
err := yaml.Unmarshal(file, &config)
|
err := yaml.Unmarshal(file, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return config
|
return config
|
||||||
}
|
}
|
|
@ -1,9 +1,8 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"flag"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"database/sql"
|
"database/sql"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
@ -15,41 +14,33 @@ var (
|
||||||
configFile string
|
configFile string
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
execCmd string
|
|
||||||
config *Config
|
config *Config
|
||||||
db *sql.DB
|
db *sql.DB
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
configFile = os.Args[1]
|
flag.StringVar(&configFile, "c", "config.yml", "path of configuration file")
|
||||||
execCmd = os.Args[2]
|
flag.StringVar(&username, "u", "none", "username")
|
||||||
|
flag.StringVar(&password, "p", "none", "password")
|
||||||
pipe := os.NewFile(uintptr(3), "/dev/fd/3")
|
flag.Parse()
|
||||||
defer pipe.Close()
|
|
||||||
in := bufio.NewReader(pipe)
|
|
||||||
data, _ := in.ReadBytes(0)
|
|
||||||
username = string(data[:len(data)-1])
|
|
||||||
data, _ = in.ReadBytes(0)
|
|
||||||
password = string(data[:len(data)-1])
|
|
||||||
|
|
||||||
config = ReadConfigFile(configFile)
|
config = ReadConfigFile(configFile)
|
||||||
|
|
||||||
db, err = sql.Open("postgres", config.Database)
|
db, err = sql.Open("postgres", config.Database)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(111)
|
||||||
}
|
}
|
||||||
defer db.Close()
|
defer db.Close()
|
||||||
|
|
||||||
var realPassword string
|
var realPassword string
|
||||||
err = db.QueryRow("select password from login where mail = $1", username).Scan(&realPassword)
|
err = db.QueryRow("select password from login where mail = $1", username).Scan(&realPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Exit(1)
|
os.Exit(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
output, _ := libpassword.Validate(realPassword, password)
|
output, _ := libpassword.Validate(realPassword, password)
|
||||||
if output {
|
if output {
|
||||||
exec.Command("bash", "-c", execCmd).Run()
|
os.Exit(0)
|
||||||
} else {
|
} else {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
|
||||||
|
liblog "dev.sum7.eu/sum7/warehost/lib/log"
|
||||||
|
libpassword "dev.sum7.eu/sum7/warehost/lib/password"
|
||||||
|
system "dev.sum7.eu/sum7/warehost/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WarehostAuth struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this WarehostAuth) CheckPasswd(user, pass string) (returndata bool, err error) {
|
||||||
|
returndata = false
|
||||||
|
var login = system.Login{Username: user}
|
||||||
|
this.db.Where("mail = ?", user).First(&login)
|
||||||
|
if login.ID <= 0 {
|
||||||
|
liblog.Log.Warn("user not found")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if login.Active {
|
||||||
|
output, _ := libpassword.Validate(login.Password, pass)
|
||||||
|
if output {
|
||||||
|
returndata = true
|
||||||
|
liblog.Log.Info("done")
|
||||||
|
} else {
|
||||||
|
liblog.Log.Warn("wrong password")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
liblog.Log.Warn("not active")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config of warehost webserver
|
||||||
|
type Config struct {
|
||||||
|
Database string `yaml:"database"`
|
||||||
|
Log struct {
|
||||||
|
Path string `yaml:"path"`
|
||||||
|
} `yaml:"log"`
|
||||||
|
DatabaseDebug bool `yaml:"databasedebug"`
|
||||||
|
FTPPath string `yaml:"data"`
|
||||||
|
Host string `yaml:"host"`
|
||||||
|
Web string `yaml:"web"`
|
||||||
|
Port int `yaml:"port"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadConfigFile reads a config models by path to a yml file
|
||||||
|
func ReadConfigFile(path string) *Config {
|
||||||
|
config := &Config{}
|
||||||
|
file, _ := ioutil.ReadFile(path)
|
||||||
|
err := yaml.Unmarshal(file, &config)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
database: "host=localhost user=warehost dbname=warehost password=hallo sslmode=disable"
|
||||||
|
log:
|
||||||
|
path: test.log
|
||||||
|
databasedebug: false
|
||||||
|
port: 2222
|
||||||
|
data: /tmp/ftp/%d/
|
||||||
|
host: /tmp/ftp-domain/%s/
|
||||||
|
web: /tmp/ftp-web/%d/
|
|
@ -0,0 +1,333 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
ftpd "github.com/goftp/server"
|
||||||
|
"github.com/jinzhu/gorm"
|
||||||
|
_ "github.com/jinzhu/gorm/dialects/postgres"
|
||||||
|
|
||||||
|
system "dev.sum7.eu/sum7/warehost/system"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileDriver struct {
|
||||||
|
RootPath string
|
||||||
|
db *gorm.DB
|
||||||
|
Perm ftpd.Perm
|
||||||
|
login system.Login
|
||||||
|
conn *ftpd.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
type FackFileInfo struct {
|
||||||
|
os.FileInfo
|
||||||
|
|
||||||
|
name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FackFileInfo) Mode() os.FileMode {
|
||||||
|
return os.ModeDir
|
||||||
|
}
|
||||||
|
func (f *FackFileInfo) IsDir() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FackFileInfo) Name() string {
|
||||||
|
return f.name
|
||||||
|
}
|
||||||
|
func (f *FackFileInfo) Owner() string {
|
||||||
|
return "warehost"
|
||||||
|
}
|
||||||
|
func (f *FackFileInfo) Size() int64 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func (f *FackFileInfo) ModTime() time.Time {
|
||||||
|
return time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FackFileInfo) Group() string {
|
||||||
|
return "http"
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileInfo struct {
|
||||||
|
os.FileInfo
|
||||||
|
|
||||||
|
mode os.FileMode
|
||||||
|
owner string
|
||||||
|
group string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileInfo) Mode() os.FileMode {
|
||||||
|
return f.mode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileInfo) Owner() string {
|
||||||
|
return f.owner
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FileInfo) Group() string {
|
||||||
|
return f.group
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) chechLogin() {
|
||||||
|
if driver.login.ID <= 0 && driver.conn.IsLogin() {
|
||||||
|
driver.db.Where("mail = ?", driver.conn.LoginUser()).First(&driver.login)
|
||||||
|
fmt.Printf("Connection:%s:%d", driver.conn.LoginUser(), driver.login.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (driver *FileDriver) realPath(path string) (string, bool) {
|
||||||
|
driver.chechLogin()
|
||||||
|
paths := strings.Split(path, "/")
|
||||||
|
root := "/dev/null"
|
||||||
|
real := false
|
||||||
|
if len(paths) > 1 && driver.login.ID > 0 {
|
||||||
|
switch paths[1] {
|
||||||
|
case "data":
|
||||||
|
root = fmt.Sprintf(driver.RootPath, driver.login.ID)
|
||||||
|
paths = append([]string{paths[0]}, paths[2:]...)
|
||||||
|
real = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return filepath.Join(append([]string{root}, paths...)...), real
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) Init(conn *ftpd.Conn) {
|
||||||
|
driver.conn = conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) ChangeDir(path string) error {
|
||||||
|
rPath, real := driver.realPath(path)
|
||||||
|
if !real {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
f, err := os.Lstat(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if f.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("Not a directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) Stat(path string) (ftpd.FileInfo, error) {
|
||||||
|
basepath, real := driver.realPath(path)
|
||||||
|
var f os.FileInfo
|
||||||
|
if real {
|
||||||
|
|
||||||
|
rPath, err := filepath.Abs(basepath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
f, err = os.Lstat(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f = &FackFileInfo{name: path}
|
||||||
|
}
|
||||||
|
mode, err := driver.Perm.GetMode(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if f.IsDir() {
|
||||||
|
mode |= os.ModeDir
|
||||||
|
}
|
||||||
|
owner, err := driver.Perm.GetOwner(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
group, err := driver.Perm.GetGroup(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &FileInfo{f, mode, owner, group}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) ListDir(path string, callback func(ftpd.FileInfo) error) error {
|
||||||
|
basepath, real := driver.realPath(path)
|
||||||
|
if real {
|
||||||
|
filepath.Walk(basepath, func(f string, info os.FileInfo, err error) error {
|
||||||
|
rPath, _ := filepath.Rel(basepath, f)
|
||||||
|
if rPath == info.Name() {
|
||||||
|
mode, err := driver.Perm.GetMode(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.IsDir() {
|
||||||
|
mode |= os.ModeDir
|
||||||
|
}
|
||||||
|
owner, err := driver.Perm.GetOwner(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
group, err := driver.Perm.GetGroup(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = callback(&FileInfo{info, mode, owner, group})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
if path == "/" {
|
||||||
|
for _, i := range []string{"data", "web", "host"} {
|
||||||
|
err := callback(&FackFileInfo{name: i})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New("No path")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) DeleteDir(path string) error {
|
||||||
|
rPath, real := driver.realPath(path)
|
||||||
|
if !real {
|
||||||
|
return errors.New("Warehost folders are not deletable")
|
||||||
|
}
|
||||||
|
f, err := os.Lstat(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if f.IsDir() {
|
||||||
|
return os.Remove(rPath)
|
||||||
|
}
|
||||||
|
return errors.New("Not a directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) DeleteFile(path string) error {
|
||||||
|
rPath, real := driver.realPath(path)
|
||||||
|
if !real {
|
||||||
|
return errors.New("Warehost files are not deletable")
|
||||||
|
}
|
||||||
|
f, err := os.Lstat(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !f.IsDir() {
|
||||||
|
return os.Remove(rPath)
|
||||||
|
}
|
||||||
|
return errors.New("Not a file")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) Rename(fromPath string, toPath string) error {
|
||||||
|
oldPath, realOld := driver.realPath(fromPath)
|
||||||
|
newPath, realNew := driver.realPath(toPath)
|
||||||
|
if !realOld || !realNew {
|
||||||
|
return errors.New("Warehost files/folders are not moveable")
|
||||||
|
}
|
||||||
|
return os.Rename(oldPath, newPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) MakeDir(path string) error {
|
||||||
|
rPath, real := driver.realPath(path)
|
||||||
|
if !real {
|
||||||
|
return errors.New("Warehost folders are not createable")
|
||||||
|
}
|
||||||
|
return os.Mkdir(rPath, os.ModePerm)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) GetFile(path string, offset int64) (int64, io.ReadCloser, error) {
|
||||||
|
rPath, real := driver.realPath(path)
|
||||||
|
if !real {
|
||||||
|
return 0, nil, errors.New("Warehost files are not downloadable")
|
||||||
|
}
|
||||||
|
f, err := os.Open(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return 0, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
f.Seek(offset, os.SEEK_SET)
|
||||||
|
|
||||||
|
return info.Size(), f, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (driver *FileDriver) PutFile(destPath string, data io.Reader, appendData bool) (int64, error) {
|
||||||
|
rPath, real := driver.realPath(destPath)
|
||||||
|
if !real {
|
||||||
|
return 0, errors.New("Warehost files are not replaceable")
|
||||||
|
}
|
||||||
|
var isExist bool
|
||||||
|
f, err := os.Lstat(rPath)
|
||||||
|
if err == nil {
|
||||||
|
isExist = true
|
||||||
|
if f.IsDir() {
|
||||||
|
return 0, errors.New("A dir has the same name")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
isExist = false
|
||||||
|
} else {
|
||||||
|
return 0, errors.New(fmt.Sprintln("Put File error:", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if appendData && !isExist {
|
||||||
|
appendData = false
|
||||||
|
}
|
||||||
|
|
||||||
|
if !appendData {
|
||||||
|
if isExist {
|
||||||
|
err = os.Remove(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f, err := os.Create(rPath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
bytes, err := io.Copy(f, data)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return bytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
of, err := os.OpenFile(rPath, os.O_APPEND|os.O_RDWR, 0660)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
defer of.Close()
|
||||||
|
|
||||||
|
_, err = of.Seek(0, os.SEEK_END)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes, err := io.Copy(of, data)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytes, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileDriverFactory struct {
|
||||||
|
RootPath string
|
||||||
|
db *gorm.DB
|
||||||
|
Perm ftpd.Perm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (factory *FileDriverFactory) NewDriver() (ftpd.Driver, error) {
|
||||||
|
return &FileDriver{RootPath: factory.RootPath, db: factory.db, Perm: factory.Perm}, nil
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"flag"
|
||||||
|
|
||||||
|
ftpd "github.com/goftp/server"
|
||||||
|
"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.Database)
|
||||||
|
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)
|
||||||
|
host.SyncModels(dbconnection)
|
||||||
|
web.SyncModels(dbconnection)
|
||||||
|
|
||||||
|
opt := &ftpd.ServerOpts{
|
||||||
|
Name: "",
|
||||||
|
Factory: &FileDriverFactory{RootPath: config.FTPPath, db: dbconnection, Perm: ftpd.NewSimplePerm("warehost", "http")},
|
||||||
|
Port: config.Port,
|
||||||
|
Auth: WarehostAuth{db: dbconnection},
|
||||||
|
}
|
||||||
|
|
||||||
|
// start ftp server
|
||||||
|
ftpServer := ftpd.NewServer(opt)
|
||||||
|
liblog.Log.Info("warehost-ftp")
|
||||||
|
err = ftpServer.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
liblog.Log.Fatal("Error starting server:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
# ID: {{.ID}} - Domain: {{.Domain.ID}} - Profil: {{.Domain.Profil.ID}}
|
||||||
|
# Login: {{.Domain.Profil.Login.ID}} -> {{.Domain.Profil.Login.Username}}
|
||||||
|
# {{.Subdomain}} - {{.Domain.FQDN}}
|
||||||
|
|
||||||
|
{{ define "domain" }}{{if .Subdomain}}{{.Subdomain}}.{{end}}{{.Domain.FQDN}}{{ end }}
|
||||||
|
{{ define "content"}}
|
||||||
|
{{if not .Redirect}}
|
||||||
|
gzip
|
||||||
|
{{if .Proxy}}
|
||||||
|
proxy / {{.Proxy}}
|
||||||
|
{{else}}
|
||||||
|
root /srv/http/domain/{{template "domain" .}}
|
||||||
|
{{if .PHP}}
|
||||||
|
# php not supported
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
{{else}}
|
||||||
|
redir https://{{.Redirect}}{uri}
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
|
|
||||||
|
{{if .SSL}}
|
||||||
|
{{if .SSLRedirect}}
|
||||||
|
http://{{template "domain".}} {
|
||||||
|
{{if not .Redirect}}
|
||||||
|
redir https://{{template "domain".}}{uri}
|
||||||
|
{{else}}
|
||||||
|
{{template "content" .}}
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
https://{{template "domain".}} {
|
||||||
|
{{template "content" .}}
|
||||||
|
}
|
||||||
|
{{else}}
|
||||||
|
http://{{template "domain" .}},https://{{template "domain".}} {
|
||||||
|
{{template "content" .}}
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
{{else}}
|
||||||
|
http://{{template "domain".}} {
|
||||||
|
{{template "content" .}}
|
||||||
|
}
|
||||||
|
{{end}}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Config of warehost webserver
|
||||||
|
type Config struct {
|
||||||
|
WarehostDatabase string `yaml:"warehostdatabase"`
|
||||||
|
Log struct {
|
||||||
|
Path string `yaml:"path"`
|
||||||
|
} `yaml:"log"`
|
||||||
|
DatabaseDebug bool `yaml:"databasedebug"`
|
||||||
|
Web struct {
|
||||||
|
Enable bool `yaml:"enable"`
|
||||||
|
ConfigurationTemplate string `yaml:"template"`
|
||||||
|
ConfigurationFile string `yaml:"config"`
|
||||||
|
} `yaml:"web"`
|
||||||
|
Database struct {
|
||||||
|
Enable bool `yaml:"enable"`
|
||||||
|
Type string `yaml:"type"`
|
||||||
|
Connection string `yaml:"connection"`
|
||||||
|
Prefix string `yaml:"prefix"`
|
||||||
|
} `yaml:"database"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadConfigFile reads a config models by path to a yml file
|
||||||
|
func ReadConfigFile(path string) *Config {
|
||||||
|
config := &Config{}
|
||||||
|
file, _ := ioutil.ReadFile(path)
|
||||||
|
err := yaml.Unmarshal(file, &config)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return config
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
warehostdatabase: "host=localhost user=warehost dbname=warehost password=hallo sslmode=disable"
|
||||||
|
log:
|
||||||
|
path: test.log
|
||||||
|
databasedebug: false
|
||||||
|
web:
|
||||||
|
enable: true
|
||||||
|
template: caddy
|
||||||
|
config: /tmp/a
|
||||||
|
database:
|
||||||
|
enable: true
|
||||||
|
type: mysql
|
||||||
|
connection: "root:hallo@/mysql?interpolateParams=true"
|
||||||
|
prefix: "warehost_db"
|
|
@ -0,0 +1,153 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"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"
|
||||||
|
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)
|
||||||
|
host.SyncModels(dbconnection)
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
err = tmpl.Execute(file, item)
|
||||||
|
if err != nil {
|
||||||
|
liblog.Log.Warning("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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue