From 9cfa4fd8b19d0d04a2a5b44e62151dd538a5193c Mon Sep 17 00:00:00 2001 From: George Shaw Date: Wed, 15 Nov 2017 15:06:25 -0600 Subject: [PATCH] started development on creating new bundles --- .../js/panelHandlers/{logs => log}/delete.js | 0 .../js/panelHandlers/{logs => log}/view.js | 0 bundles/default_bundle/logs/README.md | 1 + main.go | 4 +- pkg/api/bundle/create.go | 70 +++++++++++++++++ pkg/gpaccount/gpaccount.go | 8 +- pkg/gpserver/apihandler.go | 19 +---- pkg/gpserver/gpserver.go | 4 +- pkg/public/public.go | 78 +------------------ pkg/public/restart.go | 41 ++++++++++ pkg/public/toggle.go | 41 ++++++++++ .../assets/js/panelHandlers/bundles/create.js | 48 ++++++++++++ server/document_root/gPanel.html | 51 ++++++++++-- server/logs/README.md | 9 +++ 14 files changed, 269 insertions(+), 105 deletions(-) rename bundles/default_bundle/account/assets/js/panelHandlers/{logs => log}/delete.js (100%) rename bundles/default_bundle/account/assets/js/panelHandlers/{logs => log}/view.js (100%) create mode 100644 pkg/api/bundle/create.go create mode 100644 pkg/public/restart.go create mode 100644 pkg/public/toggle.go create mode 100644 server/document_root/assets/js/panelHandlers/bundles/create.js create mode 100644 server/logs/README.md diff --git a/bundles/default_bundle/account/assets/js/panelHandlers/logs/delete.js b/bundles/default_bundle/account/assets/js/panelHandlers/log/delete.js similarity index 100% rename from bundles/default_bundle/account/assets/js/panelHandlers/logs/delete.js rename to bundles/default_bundle/account/assets/js/panelHandlers/log/delete.js diff --git a/bundles/default_bundle/account/assets/js/panelHandlers/logs/view.js b/bundles/default_bundle/account/assets/js/panelHandlers/log/view.js similarity index 100% rename from bundles/default_bundle/account/assets/js/panelHandlers/logs/view.js rename to bundles/default_bundle/account/assets/js/panelHandlers/log/view.js diff --git a/bundles/default_bundle/logs/README.md b/bundles/default_bundle/logs/README.md index bc23fc2..9ee4345 100644 --- a/bundles/default_bundle/logs/README.md +++ b/bundles/default_bundle/logs/README.md @@ -4,5 +4,6 @@ The actual log files are ignored by the .gitignore file. They are generated auto Current log files: - client_errors.log +- account_errors.log - server_errors.log - loadtime.log diff --git a/main.go b/main.go index fe750b7..00a1ba8 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,6 @@ func main() { log.Printf("To Exit: CTRL+C") - log.Print("Listening (server) on localhost:2083, serving out of the server/document_root/ directory...") - http.ListenAndServe("localhost:2083", context.ClearHandler(mains)) + log.Print("Listening (server) on localhost:2082, serving out of the server/document_root/ directory...") + http.ListenAndServe("localhost:2082", context.ClearHandler(mains)) } diff --git a/pkg/api/bundle/create.go b/pkg/api/bundle/create.go new file mode 100644 index 0000000..636a387 --- /dev/null +++ b/pkg/api/bundle/create.go @@ -0,0 +1,70 @@ +package bundle + +import ( + "encoding/json" + "errors" + "net" + "net/http" + "strconv" + + "github.com/Ennovar/gPanel/pkg/gpaccount" +) + +func Create(res http.ResponseWriter, req *http.Request, bundles map[string]*gpaccount.Controller) bool { + if req.Method != "POST" { + http.Error(res, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) + return false + } + + var createBundleRequestData struct { + Name string `json:"name"` + AccPort int `json:"account_port"` + PubPort int `json:"public_port"` + } + + err := json.NewDecoder(req.Body).Decode(&createBundleRequestData) + if err != nil { + http.Error(res, err.Error(), http.StatusBadRequest) + return false + } + + check, err := net.Listen("tcp", ":"+strconv.Itoa(createBundleRequestData.AccPort)) + if err != nil { + http.Error(res, "A service is already listening on port "+strconv.Itoa(createBundleRequestData.AccPort), http.StatusInternalServerError) + return false + } + check.Close() + + check, err = net.Listen("tcp", ":"+strconv.Itoa(createBundleRequestData.PubPort)) + if err != nil { + http.Error(res, "A service is already listening on port "+strconv.Itoa(createBundleRequestData.PubPort), http.StatusInternalServerError) + return false + } + check.Close() + + err = nil + for k, v := range bundles { + if k == createBundleRequestData.Name { + err = errors.New("Bundle \"" + k + "\" already exists") + break + } + + if v.Port == createBundleRequestData.AccPort || + v.Port == createBundleRequestData.PubPort || + v.Public.Port == createBundleRequestData.AccPort || + v.Public.Port == createBundleRequestData.PubPort { + err = errors.New("An existing bundle is using the port \"" + strconv.Itoa(v.Port) + "\" already") + break + } + } + + if err != nil { + http.Error(res, err.Error(), http.StatusBadRequest) + return false + } + + res.WriteHeader(http.StatusOK) + res.Write([]byte(createBundleRequestData.Name)) + + return true +} diff --git a/pkg/gpaccount/gpaccount.go b/pkg/gpaccount/gpaccount.go index 8ea1bd7..982bf79 100644 --- a/pkg/gpaccount/gpaccount.go +++ b/pkg/gpaccount/gpaccount.go @@ -27,14 +27,14 @@ var controller Controller var httpserver http.Server // New returns a new Controller reference. -func New(root string) *Controller { +func New(dir string, accPort int, pubPort int) *Controller { serverErrorLogger, _ := file.Open(file.LOG_SERVER_ERRORS, true, true) controller = Controller{ - Directory: root, + Directory: dir, DocumentRoot: "account/", - Port: 2082, - Public: public.New(root + "public/"), + Port: accPort, + Public: public.New(dir+"public/", pubPort), GracefulShutdownTimeout: 5 * time.Second, Status: 0, ServerLogger: serverErrorLogger, diff --git a/pkg/gpserver/apihandler.go b/pkg/gpserver/apihandler.go index 1a10bef..dfdfefa 100644 --- a/pkg/gpserver/apihandler.go +++ b/pkg/gpserver/apihandler.go @@ -5,8 +5,7 @@ import ( "net/http" "strings" - "github.com/Ennovar/gPanel/pkg/api/log" - "github.com/Ennovar/gPanel/pkg/api/server" + "github.com/Ennovar/gPanel/pkg/api/bundle" "github.com/Ennovar/gPanel/pkg/api/user" ) @@ -28,20 +27,8 @@ func (con *Controller) apiHandler(res http.ResponseWriter, req *http.Request, cu return true, user.Register(res, req, con.Directory) case "/user/logout": return true, user.Logout(res, req, con.Directory) - case "/server/status": - return true, server.Status(res, req, con.Bundles[curBundle].Public) - case "/server/start": - return true, server.Start(res, req, con.Bundles[curBundle].Public) - case "/server/shutdown": - return true, server.Shutdown(res, req, con.Bundles[curBundle].Public) - case "/server/restart": - return true, server.Restart(res, req, con.Bundles[curBundle].Public) - case "/server/maintenance": - return true, server.Maintenance(res, req, con.Bundles[curBundle].Public) - case "/log/read": - return true, log.Read(res, req) - case "/log/delete": - return true, log.Delete(res, req) + case "/bundle/create": + return true, bundle.Create(res, req, con.Bundles) default: return false, false } diff --git a/pkg/gpserver/gpserver.go b/pkg/gpserver/gpserver.go index 37ad4eb..18c4289 100644 --- a/pkg/gpserver/gpserver.go +++ b/pkg/gpserver/gpserver.go @@ -13,14 +13,14 @@ import ( type Controller struct { Directory string DocumentRoot string - Bundles []gpaccount.Controller + Bundles map[string]*gpaccount.Controller } func New() *Controller { return &Controller{ Directory: "server/", DocumentRoot: "document_root/", - Bundles: []gpaccount.Controller{}, + Bundles: make(map[string]*gpaccount.Controller), } } diff --git a/pkg/public/public.go b/pkg/public/public.go index 304ebdf..f5f6d5a 100644 --- a/pkg/public/public.go +++ b/pkg/public/public.go @@ -2,8 +2,6 @@ package public import ( - "context" - "errors" "fmt" "io" "net/http" @@ -21,7 +19,6 @@ type Controller struct { GracefulShutdownTimeout time.Duration Status int ClientLogger *file.Handler - ServerLogger *file.Handler LoadTimeLogger *file.Handler } @@ -29,18 +26,16 @@ var controller Controller var server http.Server // New function returns a new PublicWeb type. -func New(root string) *Controller { +func New(root string, port int) *Controller { clientLogHandler, _ := file.Open(file.LOG_CLIENT_ERRORS, true, true) - serverLogHandler, _ := file.Open(file.LOG_CLIENT_ERRORS, true, true) loadLogHandler, _ := file.Open(file.LOG_LOADTIME, true, true) controller = Controller{ DocumentRoot: root, - Port: 3000, + Port: port, GracefulShutdownTimeout: 5 * time.Second, Status: 0, ClientLogger: clientLogHandler, - ServerLogger: serverLogHandler, LoadTimeLogger: loadLogHandler, } @@ -55,73 +50,6 @@ func New(root string) *Controller { return &controller } -// Start function starts listening on the public server -func (con *Controller) Start() error { - if con.Status == 1 { - return errors.New("Public server is already on.") - } - - con.Status = 1 - go server.ListenAndServe() - return nil -} - -// Stop function stops the server gracefully or forceful, depending on the boolean input -func (con *Controller) Stop(graceful bool) error { - if graceful { - context, cancel := context.WithTimeout(context.Background(), con.GracefulShutdownTimeout) - defer cancel() - - err := server.Shutdown(context) - if err == nil { - return nil - } - - fmt.Printf("Graceful shutdown failed attempting forced: %v\n", err) - } - - if err := server.Close(); err != nil { - return err - } - - con.Status = 0 - return nil -} - -// Restart function combines both the start and stop function, using different -// status codes, as it is restarting. -func (con *Controller) Restart(graceful bool) error { - con.Status = 3 - - if graceful { - context, cancel := context.WithTimeout(context.Background(), con.GracefulShutdownTimeout) - defer cancel() - - err := server.Shutdown(context) - if err != nil { - fmt.Printf("Graceful shutdown failed attempting forced: %v\n", err) - - err = server.Close() - if err != nil { - return err - } - } - } - - err := server.Close() - if err != nil { - return err - } - - con.Status = 1 - go server.ListenAndServe() - return nil -} - -func (con *Controller) Maintenance() { - con.Status = 2 -} - // 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) { @@ -168,7 +96,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()) + fmt.Printf("Server error serving files to client: %v\n", err) routing.HttpThrowStatus(http.StatusInternalServerError, res) return } diff --git a/pkg/public/restart.go b/pkg/public/restart.go new file mode 100644 index 0000000..8fbc5f1 --- /dev/null +++ b/pkg/public/restart.go @@ -0,0 +1,41 @@ +// Package public handles the logic of the public facing website +package public + +import ( + "context" + "fmt" +) + +// Restart function combines both the start and stop function, using different +// status codes, as it is restarting. +func (con *Controller) Restart(graceful bool) error { + con.Status = 3 + + if graceful { + context, cancel := context.WithTimeout(context.Background(), con.GracefulShutdownTimeout) + defer cancel() + + err := server.Shutdown(context) + if err != nil { + fmt.Printf("Graceful shutdown failed attempting forced: %v\n", err) + + err = server.Close() + if err != nil { + return err + } + } + } + + err := server.Close() + if err != nil { + return err + } + + con.Status = 1 + go server.ListenAndServe() + return nil +} + +func (con *Controller) Maintenance() { + con.Status = 2 +} diff --git a/pkg/public/toggle.go b/pkg/public/toggle.go new file mode 100644 index 0000000..be01957 --- /dev/null +++ b/pkg/public/toggle.go @@ -0,0 +1,41 @@ +// Package public handles the logic of the public facing website +package public + +import ( + "context" + "errors" + "fmt" +) + +// Start function starts listening on the public server +func (con *Controller) Start() error { + if con.Status == 1 { + return errors.New("Public server is already on.") + } + + con.Status = 1 + go server.ListenAndServe() + return nil +} + +// Stop function stops the server gracefully or forceful, depending on the boolean input +func (con *Controller) Stop(graceful bool) error { + if graceful { + context, cancel := context.WithTimeout(context.Background(), con.GracefulShutdownTimeout) + defer cancel() + + err := server.Shutdown(context) + if err == nil { + return nil + } + + fmt.Printf("Graceful shutdown failed attempting forced: %v\n", err) + } + + if err := server.Close(); err != nil { + return err + } + + con.Status = 0 + return nil +} diff --git a/server/document_root/assets/js/panelHandlers/bundles/create.js b/server/document_root/assets/js/panelHandlers/bundles/create.js new file mode 100644 index 0000000..c51864c --- /dev/null +++ b/server/document_root/assets/js/panelHandlers/bundles/create.js @@ -0,0 +1,48 @@ +newBundleModal = jQuery('.new-bundle-modal'); + +jQuery('._js_bundles-create').on('click', function(e){ + e.preventDefault(); + + newBundleModal.modal('show'); +}); + +jQuery('._js_create-bundle-form').on('submit', function(e){ + e.preventDefault(); + + var formData = {}; + for(var y = 0, yy = this.length; y < yy; y++) { + var input = this[y]; + if(input.name) { + if(input.type == "number") { + formData[input.name] = parseInt(input.value); + } + else { + formData[input.name] = input.value; + } + } + } + + var xhr = new XMLHttpRequest(); + xhr.open(jQuery(this).attr('method'), jQuery(this).attr('action'), true); + xhr.setRequestHeader('Content-Type', 'application/json; charset=UTF-8'); + xhr.send(JSON.stringify(formData)); + + xhr.onloadend = function() { + if(xhr.status == 200) { + if(xhr.response != undefined && xhr.response.length != 0) { + alert("Bundle \"" + xhr.response + "\" successfully created."); + } + else { + alert("Bundle successfully created."); + } + } + else { + if(xhr.response != undefined && xhr.response.length != 0) { + alert("Error: " + xhr.response); + } + else { + alert("An error has occurred. Please try again. If problem persists contact server administrator."); + } + } + } +}); diff --git a/server/document_root/gPanel.html b/server/document_root/gPanel.html index 4df6c16..d9ec059 100644 --- a/server/document_root/gPanel.html +++ b/server/document_root/gPanel.html @@ -27,17 +27,54 @@ + + +
-

Test

-
Test
- -
-
@@ -64,6 +101,8 @@ + + diff --git a/server/logs/README.md b/server/logs/README.md new file mode 100644 index 0000000..9ee4345 --- /dev/null +++ b/server/logs/README.md @@ -0,0 +1,9 @@ +# gPanel Logs + +The actual log files are ignored by the .gitignore file. They are generated automatically upon being needed within the software itself. + +Current log files: +- client_errors.log +- account_errors.log +- server_errors.log +- loadtime.log