mirror of
https://github.com/donl/gPanel.git
synced 2026-06-30 06:12:06 -06:00
started to fix APIs since adding gpserver
This commit is contained in:
parent
75b65b5e86
commit
92c180e57d
16 changed files with 188 additions and 115 deletions
6
main.go
6
main.go
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import (
|
|||
|
||||
// Database constants
|
||||
const (
|
||||
DBLOC_MAIN = "datastore.db"
|
||||
DB_USERS = "users.db"
|
||||
)
|
||||
|
||||
// Bucket constants
|
||||
|
|
|
|||
48
pkg/gpaccount/apihandler.go
Normal file
48
pkg/gpaccount/apihandler.go
Normal 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
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
|
|
@ -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
39
pkg/gpaccount/toggle.go
Normal 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
|
||||
}
|
||||
48
pkg/gpserver/apihandler.go
Normal file
48
pkg/gpserver/apihandler.go
Normal 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
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
package server
|
||||
// Package gpserver handles the logic of the gPanel server
|
||||
package gpserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
|
@ -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 {
|
||||
|
|
@ -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
BIN
server/users.db
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue