started to fix APIs since adding gpserver

This commit is contained in:
George Shaw 2017-11-15 12:10:21 -06:00
parent 75b65b5e86
commit 92c180e57d
16 changed files with 188 additions and 115 deletions

View file

@ -4,15 +4,15 @@ import (
"log"
"net/http"
"github.com/Ennovar/gPanel/pkg/server"
"github.com/Ennovar/gPanel/pkg/gpserver"
"github.com/gorilla/context"
)
func main() {
gpServer := server.New()
mains := gpserver.New()
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(gpServer))
http.ListenAndServe("localhost:2083", context.ClearHandler(mains))
}

View file

@ -1,50 +0,0 @@
// Package api handles all API calls
package api
import (
"net/http"
"strings"
"github.com/Ennovar/gPanel/pkg/api/log"
"github.com/Ennovar/gPanel/pkg/api/server"
"github.com/Ennovar/gPanel/pkg/api/user"
"github.com/Ennovar/gPanel/pkg/public"
)
// HandleAPI function takes a path and determines if it is an API call, if it is it will
// call the specified API. It returns two booleans, the first being if it is an API call and
// the second is the response of the API call's function.
//
// The path of an API is formatted as such: document_roots/webhost/api/some/thing. The path is split
// by the sequence of characters "api", returning the first half of the URL which is discarded, and the
// second half which will look like /some/thing. The second half is processed to see whether or not it is
// a valid API, and then handled accordingly from there.
func HandleAPI(res http.ResponseWriter, req *http.Request, path string, publicServer *public.Controller) (bool, bool) {
splitUrl := strings.SplitN(path, "api", 2)
suspectApi := strings.ToLower(splitUrl[len(splitUrl)-1])
switch suspectApi {
case "/user/auth":
return true, user.Auth(res, req)
case "/user/register":
return true, user.Register(res, req)
case "/user/logout":
return true, user.Logout(res, req)
case "/server/status":
return true, server.Status(res, req, publicServer)
case "/server/start":
return true, server.Start(res, req, publicServer)
case "/server/shutdown":
return true, server.Shutdown(res, req, publicServer)
case "/server/restart":
return true, server.Restart(res, req, publicServer)
case "/server/maintenance":
return true, server.Maintenance(res, req, publicServer)
case "/log/read":
return true, log.Read(res, req)
case "/log/delete":
return true, log.Delete(res, req)
default:
return false, false
}
}

View file

@ -4,6 +4,7 @@ package user
import (
"encoding/json"
"net/http"
"strings"
"time"
"github.com/Ennovar/gPanel/pkg/database"
@ -15,7 +16,7 @@ import (
// Auth function is accessed by an API call from the webhost root
// by accessing /user_auth and sending it a post request with userRequestData
// struct in JSON format.
func Auth(res http.ResponseWriter, req *http.Request) bool {
func Auth(res http.ResponseWriter, req *http.Request, dir string) bool {
if req.Method != "POST" {
http.Error(res, req.Method+" HTTP method is unsupported for this API.", http.StatusMethodNotAllowed)
return false
@ -32,7 +33,7 @@ func Auth(res http.ResponseWriter, req *http.Request) bool {
return false
}
ds, err := database.Open(database.DBLOC_MAIN)
ds, err := database.Open(dir + database.DB_USERS)
if err != nil || ds == nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
return false
@ -80,7 +81,13 @@ func Auth(res http.ResponseWriter, req *http.Request) bool {
return false
}
store := networking.GetStore(networking.ACCOUNT_USER_AUTH)
var store networking.Store
if strings.Contains(dir, "bundles/") {
store = networking.GetStore(networking.ACCOUNT_USER_AUTH)
} else {
store = networking.GetStore(networking.SERVER_USER_AUTH)
}
err = store.Set(res, req, "token", token, (60 * 60 * 24))
err2 := store.Set(res, req, "user", userRequestData.User, (60 * 60 * 24))
if err != nil || err2 != nil {

View file

@ -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.DBLOC_MAIN)
ds, err := database.Open(directory + database.DB_USERS)
if err != nil {
return "", err
}

View file

@ -3,6 +3,7 @@ package user
import (
"net/http"
"strings"
"github.com/Ennovar/gPanel/pkg/networking"
)
@ -10,13 +11,19 @@ import (
// Logout function is accessed by an API call from the webhost root
// by accessing /user_logout and sending it an empty POST request. This function will
// delete the user-auth cookie session store
func Logout(res http.ResponseWriter, req *http.Request) bool {
func Logout(res http.ResponseWriter, req *http.Request, dir string) bool {
if req.Method != "POST" {
http.Error(res, req.Method+" HTTP method is unsupported for this API.", http.StatusMethodNotAllowed)
return false
}
store := networking.GetStore(networking.ACCOUNT_USER_AUTH)
var store networking.Store
if strings.Contains(dir, "bundles/") {
store = networking.GetStore(networking.ACCOUNT_USER_AUTH)
} else {
store = networking.GetStore(networking.SERVER_USER_AUTH)
}
err := store.Delete(res, req)
if err != nil {

View file

@ -12,7 +12,7 @@ import (
// Register function is accessed by an API call from the webhost root
// by accessing /user_register and sending it a post request with userRequestData
// struct in JSON format.
func Register(res http.ResponseWriter, req *http.Request) bool {
func Register(res http.ResponseWriter, req *http.Request, dir string) bool {
if req.Method != "POST" {
http.Error(res, req.Method+" HTTP method is unsupported for this API.", http.StatusMethodNotAllowed)
return false
@ -32,7 +32,7 @@ func Register(res http.ResponseWriter, req *http.Request) bool {
return false
}
ds, err := database.Open(database.DBLOC_MAIN)
ds, err := database.Open(dir + database.DB_USERS)
if err != nil || ds == nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
return false

View file

@ -11,7 +11,7 @@ import (
// Database constants
const (
DBLOC_MAIN = "datastore.db"
DB_USERS = "users.db"
)
// Bucket constants

View file

@ -0,0 +1,48 @@
// Package gpaccount handles the logic of the gPanel account server
package gpaccount
import (
"net/http"
"strings"
"github.com/Ennovar/gPanel/pkg/api/log"
"github.com/Ennovar/gPanel/pkg/api/server"
"github.com/Ennovar/gPanel/pkg/api/user"
)
func (con *Controller) apiHandler(res http.ResponseWriter, req *http.Request) (bool, bool) {
path := req.URL.Path[1:]
if len(path) == 0 {
path = (con.Directory + "index.html")
} else {
path = (con.Directory + path)
}
splitUrl := strings.SplitN(path, "api", 2)
suspectApi := strings.ToLower(splitUrl[len(splitUrl)-1])
switch suspectApi {
case "/user/auth":
return true, user.Auth(res, req, con.Directory)
case "/user/register":
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.Public)
case "/server/start":
return true, server.Start(res, req, con.Public)
case "/server/shutdown":
return true, server.Shutdown(res, req, con.Public)
case "/server/restart":
return true, server.Restart(res, req, con.Public)
case "/server/maintenance":
return true, server.Maintenance(res, req, con.Public)
case "/log/read":
return true, log.Read(res, req)
case "/log/delete":
return true, log.Delete(res, req)
default:
return false, false
}
}

View file

@ -1,5 +1,5 @@
// Package account handles the logic of the gPanel account server
package account
// Package gpaccount handles the logic of the gPanel account server
package gpaccount
import (
"net/http"

View file

@ -1,17 +1,13 @@
// Package account handles the logic of the gPanel account server
package account
// Package gpaccount handles the logic of the gPanel account server
package gpaccount
import (
"context"
"errors"
"fmt"
"io"
"net/http"
"os"
"strconv"
"time"
"github.com/Ennovar/gPanel/pkg/api"
"github.com/Ennovar/gPanel/pkg/file"
"github.com/Ennovar/gPanel/pkg/public"
"github.com/Ennovar/gPanel/pkg/routing"
@ -28,7 +24,7 @@ type Controller struct {
}
var controller Controller
var server http.Server
var httpserver http.Server
// New returns a new Controller reference.
func New(root string) *Controller {
@ -44,7 +40,7 @@ func New(root string) *Controller {
ServerLogger: serverErrorLogger,
}
server = http.Server{
httpserver = http.Server{
Addr: "localhost:" + strconv.Itoa(controller.Port),
Handler: &controller,
ReadTimeout: 30 * time.Second,
@ -55,37 +51,6 @@ func New(root string) *Controller {
return &controller
}
func (con *Controller) Start() error {
if con.Status == 1 {
return errors.New("Account server is already on.")
}
con.Status = 1
go server.ListenAndServe()
return nil
}
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
}
// ServeHTTP function routes all requests for the private webhost server. It is used in the main
// function inside of the http.ListenAndServe() function for the private webhost host.
func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) {
@ -104,7 +69,7 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) {
}
}
isApi, _ := api.HandleAPI(res, req, path, con.Public)
isApi, _ := con.apiHandler(res, req)
if isApi {
// API methods handle HTTP logic from here

39
pkg/gpaccount/toggle.go Normal file
View file

@ -0,0 +1,39 @@
// Package gpaccount handles the logic of the gPanel account server
package gpaccount
import (
"context"
"errors"
"fmt"
)
func (con *Controller) Start() error {
if con.Status == 1 {
return errors.New("Account server is already on.")
}
con.Status = 1
go httpserver.ListenAndServe()
return nil
}
func (con *Controller) Stop(graceful bool) error {
if graceful {
context, cancel := context.WithTimeout(context.Background(), con.GracefulShutdownTimeout)
defer cancel()
err := httpserver.Shutdown(context)
if err == nil {
return nil
}
fmt.Printf("Graceful shutdown failed attempting forced: %v\n", err)
}
if err := httpserver.Close(); err != nil {
return err
}
con.Status = 0
return nil
}

View file

@ -0,0 +1,48 @@
// Package gpserver handles the logic of the gPanel server
package gpserver
import (
"net/http"
"strings"
"github.com/Ennovar/gPanel/pkg/api/log"
"github.com/Ennovar/gPanel/pkg/api/server"
"github.com/Ennovar/gPanel/pkg/api/user"
)
func (con *Controller) apiHandler(res http.ResponseWriter, req *http.Request, curBundle int) (bool, bool) {
path := req.URL.Path[1:]
if len(path) == 0 {
path = (con.Directory + "index.html")
} else {
path = (con.Directory + path)
}
splitUrl := strings.SplitN(path, "api", 2)
suspectApi := strings.ToLower(splitUrl[len(splitUrl)-1])
switch suspectApi {
case "/user/auth":
return true, user.Auth(res, req, con.Directory)
case "/user/register":
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)
default:
return false, false
}
}

View file

@ -1,4 +1,5 @@
package server
// Package gpserver handles the logic of the gPanel server
package gpserver
import (
"net/http"

View file

@ -1,25 +1,26 @@
package server
// Package gpserver handles the logic of the gPanel server
package gpserver
import (
"io"
"net/http"
"os"
"github.com/Ennovar/gPanel/pkg/account"
"github.com/Ennovar/gPanel/pkg/gpaccount"
"github.com/Ennovar/gPanel/pkg/routing"
)
type Controller struct {
Directory string
DocumentRoot string
Bundles []account.Controller
Bundles []gpaccount.Controller
}
func New() *Controller {
return &Controller{
Directory: "server/",
DocumentRoot: "document_root/",
Bundles: []account.Controller{},
Bundles: []gpaccount.Controller{},
}
}
@ -38,6 +39,13 @@ func (con *Controller) ServeHTTP(res http.ResponseWriter, req *http.Request) {
}
}
isApi, _ := con.apiHandler(res, req, 0)
if isApi {
// API methods handle HTTP logic from here
return
}
f, err := os.Open(path)
if err != nil {

View file

@ -15,14 +15,14 @@ const (
SERVER_USER_AUTH = "gpanel-server-user-auth"
)
type store struct {
type Store struct {
handle *sessions.CookieStore
cookieName string
}
// GetStore function takes a name and either creates/grabs a store with that name.
func GetStore(name string) store {
sessionStore := store{
func GetStore(name string) Store {
sessionStore := Store{
handle: sessions.NewCookieStore(key),
cookieName: name,
}
@ -31,7 +31,7 @@ func GetStore(name string) store {
}
// Set function is attached to the store struct and will set a session value inside of the current store.
func (s *store) Set(res http.ResponseWriter, req *http.Request, key string, value interface{}, expire int) error {
func (s *Store) Set(res http.ResponseWriter, req *http.Request, key string, value interface{}, expire int) error {
session, err := s.handle.Get(req, s.cookieName)
if err != nil {
@ -49,7 +49,7 @@ func (s *store) Set(res http.ResponseWriter, req *http.Request, key string, valu
}
// Read function is attached to the store struct and will read a given session value inside of the current store.
func (s *store) Read(res http.ResponseWriter, req *http.Request, key string) (interface{}, error) {
func (s *Store) Read(res http.ResponseWriter, req *http.Request, key string) (interface{}, error) {
session, err := s.handle.Get(req, s.cookieName)
if err != nil {
@ -61,7 +61,7 @@ func (s *store) Read(res http.ResponseWriter, req *http.Request, key string) (in
}
// Delete function is attached to the store struct and will delete a given session value inside of the current store.
func (s *store) Delete(res http.ResponseWriter, req *http.Request) error {
func (s *Store) Delete(res http.ResponseWriter, req *http.Request) error {
session, err := s.handle.Get(req, s.cookieName)
if err != nil {

BIN
server/users.db Normal file

Binary file not shown.