From e97c5c634c9abe841cf338726cdfc33fb62f008a Mon Sep 17 00:00:00 2001 From: George Shaw Date: Wed, 15 Nov 2017 16:00:05 -0600 Subject: [PATCH] creating bundles is done --- .gitignore | 3 + pkg/api/bundle/create.go | 32 +++++++++++ pkg/api/user/auth.go | 2 +- pkg/api/user/get_secret.go | 2 +- pkg/api/user/register.go | 2 +- pkg/database/database.go | 8 ++- pkg/file/dircopy.go | 112 +++++++++++++++++++++++++++++++++++++ pkg/gpaccount/gpaccount.go | 19 ++++--- pkg/gpaccount/toggle.go | 1 + pkg/public/public.go | 26 ++++----- pkg/public/toggle.go | 1 + 11 files changed, 183 insertions(+), 25 deletions(-) create mode 100644 pkg/file/dircopy.go diff --git a/.gitignore b/.gitignore index 83f9dd1..55d4dcd 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ bundles/* # IGNORE .DB FILES **.db + +# IGNORE OSX FINDER FILES +**.DS_Store diff --git a/pkg/api/bundle/create.go b/pkg/api/bundle/create.go index 636a387..e289056 100644 --- a/pkg/api/bundle/create.go +++ b/pkg/api/bundle/create.go @@ -7,6 +7,8 @@ import ( "net/http" "strconv" + "github.com/Ennovar/gPanel/pkg/database" + "github.com/Ennovar/gPanel/pkg/file" "github.com/Ennovar/gPanel/pkg/gpaccount" ) @@ -63,6 +65,36 @@ func Create(res http.ResponseWriter, req *http.Request, bundles map[string]*gpac return false } + newBundle := "bundles/bundle_" + createBundleRequestData.Name + err = file.CopyDir("bundles/default_bundle", newBundle) + if err != nil { + http.Error(res, err.Error(), http.StatusInternalServerError) + return false + } + + ds, err := database.Open(newBundle + "/" + database.DB_MAIN) + if err != nil { + http.Error(res, err.Error(), http.StatusBadRequest) + return false + } + defer ds.Close() + + err = ds.Put(database.BUCKET_PORTS, []byte("account"), createBundleRequestData.AccPort) + if err != nil { + http.Error(res, err.Error(), http.StatusBadRequest) + return false + } + + err = ds.Put(database.BUCKET_PORTS, []byte("public"), createBundleRequestData.PubPort) + if err != nil { + http.Error(res, err.Error(), http.StatusBadRequest) + return false + } + + bundles[createBundleRequestData.Name] = gpaccount.New(newBundle+"/", createBundleRequestData.AccPort, createBundleRequestData.PubPort) + _ = bundles[createBundleRequestData.Name].Start() + _ = bundles[createBundleRequestData.Name].Public.Start() + res.WriteHeader(http.StatusOK) res.Write([]byte(createBundleRequestData.Name)) diff --git a/pkg/api/user/auth.go b/pkg/api/user/auth.go index 69a0afb..e636abe 100644 --- a/pkg/api/user/auth.go +++ b/pkg/api/user/auth.go @@ -33,7 +33,7 @@ func Auth(res http.ResponseWriter, req *http.Request, dir string) bool { return false } - ds, err := database.Open(dir + database.DB_USERS) + ds, err := database.Open(dir + database.DB_MAIN) if err != nil || ds == nil { http.Error(res, err.Error(), http.StatusInternalServerError) return false diff --git a/pkg/api/user/get_secret.go b/pkg/api/user/get_secret.go index 8cc7470..7a4b003 100644 --- a/pkg/api/user/get_secret.go +++ b/pkg/api/user/get_secret.go @@ -7,7 +7,7 @@ import "github.com/Ennovar/gPanel/pkg/database" // only used on the server side to help verify users are who they say they // are. func GetSecret(user string, directory string) (string, error) { - ds, err := database.Open(directory + database.DB_USERS) + ds, err := database.Open(directory + database.DB_MAIN) if err != nil { return "", err } diff --git a/pkg/api/user/register.go b/pkg/api/user/register.go index c8b303f..0fec4b6 100644 --- a/pkg/api/user/register.go +++ b/pkg/api/user/register.go @@ -32,7 +32,7 @@ func Register(res http.ResponseWriter, req *http.Request, dir string) bool { return false } - ds, err := database.Open(dir + database.DB_USERS) + ds, err := database.Open(dir + database.DB_MAIN) if err != nil || ds == nil { http.Error(res, err.Error(), http.StatusInternalServerError) return false diff --git a/pkg/database/database.go b/pkg/database/database.go index 9ab111f..1258827 100644 --- a/pkg/database/database.go +++ b/pkg/database/database.go @@ -11,12 +11,13 @@ import ( // Database constants const ( - DB_USERS = "users.db" + DB_MAIN = "datastore.db" ) // Bucket constants const ( BUCKET_USERS = "users" + BUCKET_PORTS = "ports" ) // Error codes @@ -45,6 +46,11 @@ func Open(filepath string) (*Datastore, error) { err = ds.handle.Update(func(tx *bolt.Tx) error { _, err := tx.CreateBucketIfNotExists([]byte(BUCKET_USERS)) + if err != nil { + return err + } + _, err = tx.CreateBucketIfNotExists([]byte(BUCKET_PORTS)) + if err != nil { return err } diff --git a/pkg/file/dircopy.go b/pkg/file/dircopy.go new file mode 100644 index 0000000..415fa96 --- /dev/null +++ b/pkg/file/dircopy.go @@ -0,0 +1,112 @@ +// Package file handles various file operations +package file + +import ( + "errors" + "io" + "io/ioutil" + "os" + "path/filepath" +) + +// CopyFile copies the contents of the file named src to the file named +// by dst. The file will be created if it does not already exist. If the +// destination file exists, all it's contents will be replaced by the contents +// of the source file. The file mode will be copied from the source and +// the copied data is synced/flushed to stable storage. +func CopyFile(src, dst string) error { + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + + out, err := os.Create(dst) + if err != nil { + return err + } + defer func() { + if e := out.Close(); e != nil { + err = e + } + }() + + _, err = io.Copy(out, in) + if err != nil { + return err + } + + err = out.Sync() + if err != nil { + return err + } + + si, err := os.Stat(src) + if err != nil { + return err + } + err = os.Chmod(dst, si.Mode()) + if err != nil { + return err + } + + return nil +} + +// CopyDir recursively copies a directory tree, attempting to preserve permissions. +// Source directory must exist, destination directory must *not* exist. +// Symlinks are ignored and skipped. +func CopyDir(src string, dst string) error { + src = filepath.Clean(src) + dst = filepath.Clean(dst) + + si, err := os.Stat(src) + if err != nil { + return err + } + if !si.IsDir() { + return errors.New("source is not a directory") + } + + _, err = os.Stat(dst) + if err != nil && !os.IsNotExist(err) { + return err + } + if err == nil { + return errors.New("destination already exists") + } + + err = os.MkdirAll(dst, si.Mode()) + if err != nil { + return err + } + + entries, err := ioutil.ReadDir(src) + if err != nil { + return err + } + + for _, entry := range entries { + srcPath := filepath.Join(src, entry.Name()) + dstPath := filepath.Join(dst, entry.Name()) + + if entry.IsDir() { + err = CopyDir(srcPath, dstPath) + if err != nil { + return err + } + } else { + // Skip symlinks. + if entry.Mode()&os.ModeSymlink != 0 { + continue + } + + err = CopyFile(srcPath, dstPath) + if err != nil { + return err + } + } + } + + return nil +} diff --git a/pkg/gpaccount/gpaccount.go b/pkg/gpaccount/gpaccount.go index 982bf79..7525b06 100644 --- a/pkg/gpaccount/gpaccount.go +++ b/pkg/gpaccount/gpaccount.go @@ -2,13 +2,13 @@ package gpaccount import ( + "fmt" "io" "net/http" "os" "strconv" "time" - "github.com/Ennovar/gPanel/pkg/file" "github.com/Ennovar/gPanel/pkg/public" "github.com/Ennovar/gPanel/pkg/routing" ) @@ -20,7 +20,7 @@ type Controller struct { Public *public.Controller GracefulShutdownTimeout time.Duration Status int - ServerLogger *file.Handler + // ServerLogger *file.Handler } var controller Controller @@ -28,7 +28,7 @@ var httpserver http.Server // New returns a new Controller reference. func New(dir string, accPort int, pubPort int) *Controller { - serverErrorLogger, _ := file.Open(file.LOG_SERVER_ERRORS, true, true) + // serverErrorLogger, _ := file.Open(file.LOG_SERVER_ERRORS, true, true) controller = Controller{ Directory: dir, @@ -37,7 +37,7 @@ func New(dir string, accPort int, pubPort int) *Controller { Public: public.New(dir+"public/", pubPort), GracefulShutdownTimeout: 5 * time.Second, Status: 0, - ServerLogger: serverErrorLogger, + // ServerLogger: serverErrorLogger, } httpserver = http.Server{ @@ -61,9 +61,11 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) { path = (con.Directory + path) } + fmt.Println("acc: " + path) + if reqAuth(path) { if !con.checkAuth(res, req) { - con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusUnauthorized) + "::" + http.StatusText(http.StatusUnauthorized)) + // con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusUnauthorized) + "::" + http.StatusText(http.StatusUnauthorized)) http.Error(res, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized) return } @@ -79,7 +81,8 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) { f, err := os.Open(path) if err != nil { - con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusNotFound) + "::" + err.Error()) + // con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusNotFound) + "::" + err.Error()) + fmt.Println(err.Error()) routing.HttpThrowStatus(http.StatusNotFound, res) return } @@ -87,7 +90,7 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) { contentType, err := routing.GetContentType(path) if err != nil { - con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusUnsupportedMediaType) + "::" + err.Error()) + // con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusUnsupportedMediaType) + "::" + err.Error()) routing.HttpThrowStatus(http.StatusUnsupportedMediaType, res) return } @@ -96,7 +99,7 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) { _, err = io.Copy(res, f) if err != nil { - con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusInternalServerError) + "::" + err.Error()) + // con.ServerLogger.Write(path + "::" + strconv.Itoa(http.StatusInternalServerError) + "::" + err.Error()) routing.HttpThrowStatus(http.StatusInternalServerError, res) return } diff --git a/pkg/gpaccount/toggle.go b/pkg/gpaccount/toggle.go index b96b274..9cdecba 100644 --- a/pkg/gpaccount/toggle.go +++ b/pkg/gpaccount/toggle.go @@ -14,6 +14,7 @@ func (con *Controller) Start() error { con.Status = 1 go httpserver.ListenAndServe() + fmt.Printf("gPanel account server now serving out of %s%s on port %d\n", con.Directory, con.DocumentRoot, con.Port) return nil } diff --git a/pkg/public/public.go b/pkg/public/public.go index f5f6d5a..c3601b6 100644 --- a/pkg/public/public.go +++ b/pkg/public/public.go @@ -6,10 +6,8 @@ import ( "io" "net/http" "os" - "strconv" "time" - "github.com/Ennovar/gPanel/pkg/file" "github.com/Ennovar/gPanel/pkg/routing" ) @@ -18,8 +16,8 @@ type Controller struct { Port int GracefulShutdownTimeout time.Duration Status int - ClientLogger *file.Handler - LoadTimeLogger *file.Handler + // ClientLogger *file.Handler + // LoadTimeLogger *file.Handler } var controller Controller @@ -27,16 +25,16 @@ var server http.Server // New function returns a new PublicWeb type. func New(root string, port int) *Controller { - clientLogHandler, _ := file.Open(file.LOG_CLIENT_ERRORS, true, true) - loadLogHandler, _ := file.Open(file.LOG_LOADTIME, true, true) + // clientLogHandler, _ := file.Open(file.LOG_CLIENT_ERRORS, true, true) + // loadLogHandler, _ := file.Open(file.LOG_LOADTIME, true, true) controller = Controller{ DocumentRoot: root, Port: port, GracefulShutdownTimeout: 5 * time.Second, Status: 0, - ClientLogger: clientLogHandler, - LoadTimeLogger: loadLogHandler, + // ClientLogger: clientLogHandler, + // LoadTimeLogger: loadLogHandler, } server = http.Server{ @@ -53,7 +51,7 @@ func New(root string, port int) *Controller { // ServeHTTP function routes all requests for the public web server. It is used in the main // function inside of the http.ListenAndServe() function for the public host. func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) { - startTime := time.Now() + // startTime := time.Now() switch con.Status { case 0: // This will actually never show because this function won't run if the server is off @@ -76,10 +74,12 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) { path = (con.DocumentRoot + path) } + fmt.Println("pub: " + path) + f, err := os.Open(path) if err != nil { - con.ClientLogger.Write(path + "::" + strconv.Itoa(http.StatusNotFound) + "::" + err.Error()) + // con.ClientLogger.Write(path + "::" + strconv.Itoa(http.StatusNotFound) + "::" + err.Error()) routing.HttpThrowStatus(http.StatusNotFound, res) return } @@ -87,7 +87,7 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) { contentType, err := routing.GetContentType(path) if err != nil { - con.ClientLogger.Write(path + "::" + strconv.Itoa(http.StatusUnsupportedMediaType) + "::" + err.Error()) + // con.ClientLogger.Write(path + "::" + strconv.Itoa(http.StatusUnsupportedMediaType) + "::" + err.Error()) routing.HttpThrowStatus(http.StatusUnsupportedMediaType, res) return } @@ -101,6 +101,6 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) { return } - elapsedTime := time.Since(startTime) - con.LoadTimeLogger.Write(path + " rendered in " + strconv.FormatFloat(elapsedTime.Seconds(), 'f', 6, 64) + " seconds") + // elapsedTime := time.Since(startTime) + // con.LoadTimeLogger.Write(path + " rendered in " + strconv.FormatFloat(elapsedTime.Seconds(), 'f', 6, 64) + " seconds") } diff --git a/pkg/public/toggle.go b/pkg/public/toggle.go index be01957..a6ead45 100644 --- a/pkg/public/toggle.go +++ b/pkg/public/toggle.go @@ -15,6 +15,7 @@ func (con *Controller) Start() error { con.Status = 1 go server.ListenAndServe() + fmt.Printf("Public server now serving out of %s on port %d\n", con.DocumentRoot, con.Port) return nil }