started development on creating new bundles

This commit is contained in:
George Shaw 2017-11-15 15:06:25 -06:00
parent dd7bae479d
commit 9cfa4fd8b1
14 changed files with 269 additions and 105 deletions

View file

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

View file

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

70
pkg/api/bundle/create.go Normal file
View file

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

View file

@ -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,

View file

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

View file

@ -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),
}
}

View file

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

41
pkg/public/restart.go Normal file
View file

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

41
pkg/public/toggle.go Normal file
View file

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

View file

@ -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.");
}
}
}
});

View file

@ -27,17 +27,54 @@
</div>
</nav>
<!-- Create New Bundle Modal -->
<div class="modal fade new-bundle-modal" tabindex="-1" role="dialog" aria-labelledby="new-bundle-modal" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Create New Bundle</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form class="_js_create-bundle-form" action="api/bundle/create" method="POST">
<div class="form-group">
<label for="newBundleName">Bundle Name</label>
<input name="name" type="text" class="form-control" id="newBundleName" aria-describedby="newBundleNameHelp" placeholder="Bundle Name">
<small id="newBundleNameHelp" class="form-text text-muted">Bundle name must be unqiue in terms of your current bundle collection.</small>
</div>
<div class="form-group">
<label for="newBundleAccountPort">Bundle Account Port</label>
<input name="account_port" type="number" class="form-control" id="newBundleAccountPort" aria-describedby="newBundleAccountPortHelp" min="2000" max="4000" value="2083">
<small id="newBundleAccountPortHelp" class="form-text text-muted">Bundle account port must be unique in terms of your current bundle collection.</small>
</div>
<div class="form-group">
<label for="newBundlePublicPort">Bundle Public Port</label>
<input name="public_port" type="number" class="form-control" id="newBundlePublicPort" aria-describedby="newBundlePublicPortHelp" min="2000" max="4000" value="2084">
<small id="newBundlePublicPortHelp" class="form-text text-muted">Bundle public port must be unique in terms of your current bundle collection.</small>
</div>
<button type="submit" class="btn btn-primary">Create Bundle</button>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<h4 class="card-title">Test</h4>
<h6 class="card-subtitle mb-4 text-muted">Test</h6>
<button class="btn btn-outline-primary">Test</button>
</div>
<div class="card-footer text-muted text-center">
TEST
<h4 class="card-title">Bundles</h4>
<h6 class="card-subtitle mb-4 text-muted">Create new bundles and update current bundles.</h6>
<div class="btn-group" role="group">
<button class="btn btn-outline-primary _js_bundles-create">Create New Bundle</button>
<button class="btn btn-outline-primary">Manage Current Bundles</button>
</div>
</div>
</div>
</div>
@ -64,6 +101,8 @@
<script type="text/javascript" src="assets/js/formHandlers/search.js"></script>
<script type="text/javascript" src="assets/js/formHandlers/logout.js"></script>
<script type="text/javascript" src="assets/js/panelHandlers/bundles/create.js"></script>
<!-- KEEP AT BOTTOM OF BODY TAGS -->
</body>
</html>

9
server/logs/README.md Normal file
View file

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