diff --git a/api/api.go b/api/api.go index 366b6e9..448926e 100644 --- a/api/api.go +++ b/api/api.go @@ -28,7 +28,7 @@ func (api *API) Listen() { api.router = gin.Default() - api.router.GET("/", getRoot) + api.registerRoutes() listenString := fmt.Sprintf("%s:%d", config.Get().Web.ListenHost, config.Get().Web.ListenPort) diff --git a/api/auth.go b/api/auth.go index 00768e5..fc67cf9 100644 --- a/api/auth.go +++ b/api/auth.go @@ -70,8 +70,7 @@ func AuthHandler(permission string) gin.HandlerFunc { requestToken := c.Request.Header.Get(accessTokenHeader) requestServer := c.Request.Header.Get(accessServerHeader) var server control.Server - - if requestToken == "" { + if requestToken == "" && permission != "" { log.Debug("Token missing in request.") c.JSON(http.StatusBadRequest, responseError{"Missing required " + accessTokenHeader + " header."}) c.Abort() diff --git a/api/handlers.go b/api/handlers.go new file mode 100644 index 0000000..d47eb9f --- /dev/null +++ b/api/handlers.go @@ -0,0 +1,30 @@ +package api + +import ( + "net/http" + + "github.com/Pterodactyl/wings/constants" + "github.com/gin-gonic/gin" +) + +// handleGetIndex handles GET / +func handleGetIndex(c *gin.Context) { + auth, _ := c.Get(ContextVarAuth) + + if auth := auth.(AuthorizationManager); auth.hasPermission("c:info") { + + } + + c.Header("Content-Type", "text/html") + c.String(http.StatusOK, constants.IndexPage) +} + +// handlePutConfig handles PUT /config +func handlePutConfig(c *gin.Context) { + +} + +// handlePatchConfig handles PATCH /config +func handlePatchConfig(c *gin.Context) { + +} diff --git a/api/handlers_server.go b/api/handlers_server.go new file mode 100644 index 0000000..85b5107 --- /dev/null +++ b/api/handlers_server.go @@ -0,0 +1,59 @@ +package api + +import "github.com/gin-gonic/gin" + +func handleGetServers(c *gin.Context) { + +} + +func handlePostServers(c *gin.Context) { + +} + +func handleDeleteServers(c *gin.Context) { + +} + +func handleGetServer(c *gin.Context) { + +} + +func handlePatchServer(c *gin.Context) { + +} + +func handlePutServer(c *gin.Context) { + +} + +func handlePostServerReinstall(c *gin.Context) { + +} + +func handlePostServerPassword(c *gin.Context) { + +} + +func handlePostServerRebuild(c *gin.Context) { + +} + +func handlePutServerPower(c *gin.Context) { + +} + +func handlePostServerCommand(c *gin.Context) { + +} + +func handleGetServerLog(c *gin.Context) { + +} + +func handlePostServerSuspend(c *gin.Context) { + +} + +func handlePostServerUnsuspend(c *gin.Context) { + +} diff --git a/api/handlers_server_files.go b/api/handlers_server_files.go new file mode 100644 index 0000000..d4c5ae3 --- /dev/null +++ b/api/handlers_server_files.go @@ -0,0 +1,51 @@ +package api + +import "github.com/gin-gonic/gin" + +func handlePostFilesFolder(c *gin.Context) { + +} + +func handleGetDirectory(c *gin.Context) { + +} + +func handlePostFileCopy(c *gin.Context) { + +} + +func handlePostFileMove(c *gin.Context) { + +} + +func handlePostFileDelete(c *gin.Context) { + +} + +func handlePostFileCompress(c *gin.Context) { + +} + +func handlePostFileDecompress(c *gin.Context) { + +} + +func handleGetFileStat(c *gin.Context) { + +} + +func handleGetFile(c *gin.Context) { + +} + +func handlePostFile(c *gin.Context) { + +} + +func handleDeleteFile(c *gin.Context) { + +} + +func handleGetDownloadFile(c *gin.Context) { + +} diff --git a/api/handlers_test.go b/api/handlers_test.go new file mode 100644 index 0000000..16d44ca --- /dev/null +++ b/api/handlers_test.go @@ -0,0 +1,46 @@ +package api + +import ( + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/gin-gonic/gin" + "github.com/stretchr/testify/assert" +) + +func TestHandleGetIndex(t *testing.T) { + router := gin.New() + recorder := httptest.NewRecorder() + req, _ := http.NewRequest("GET", "/", nil) + + router.GET("/", handleGetIndex) + router.ServeHTTP(recorder, req) + + assert.Equal(t, http.StatusOK, recorder.Code) +} + +func TestHandlePutConfig(t *testing.T) { + router := gin.New() + recorder := httptest.NewRecorder() + + req, _ := http.NewRequest("PUT", "/", strings.NewReader("{}")) + + router.PUT("/", handlePutConfig) + router.ServeHTTP(recorder, req) + + assert.Equal(t, http.StatusOK, recorder.Code) +} + +func TestHandlePatchConfig(t *testing.T) { + router := gin.New() + recorder := httptest.NewRecorder() + + req, _ := http.NewRequest("PATCH", "/", strings.NewReader("{}")) + + router.PATCH("/", handlePatchConfig) + router.ServeHTTP(recorder, req) + + assert.Equal(t, http.StatusOK, recorder.Code) +} diff --git a/api/routes.go b/api/routes.go new file mode 100644 index 0000000..f32fd7e --- /dev/null +++ b/api/routes.go @@ -0,0 +1,18 @@ +package api + +import ( + "github.com/gin-gonic/gin" +) + +func (api *API) registerRoutes() { + api.router.GET("/", AuthHandler(""), handleGetIndex) + api.router.PUT("/config", AuthHandler("c:config"), handlePutConfig) + api.router.PATCH("/config", AuthHandler("c:config"), handlePatchConfig) + + api.registerServerRoutes() + api.registerServerFileRoutes() +} + +func handle(c *gin.Context) { + +} diff --git a/api/routes_server.go b/api/routes_server.go new file mode 100644 index 0000000..5708767 --- /dev/null +++ b/api/routes_server.go @@ -0,0 +1,34 @@ +package api + +func (api *API) registerServerRoutes() { + + // Big Picture Actions + api.router.GET("/servers", AuthHandler("c:list"), handleGetServers) + + api.router.POST("/servers", AuthHandler("c:create"), handlePostServers) + + api.router.DELETE("/servers", AuthHandler("g:server:delete"), handleDeleteServers) + + // Server Actions + api.router.GET("/server", AuthHandler("s:get"), handleGetServer) + + api.router.PATCH("/server", AuthHandler("s:config"), handlePatchServer) + + api.router.PUT("/server", AuthHandler("s:config"), handlePutServer) + + api.router.POST("/server/reinstall", AuthHandler("s:install-server"), handlePostServerReinstall) + + api.router.POST("/server/password", AuthHandler(""), handlePostServerPassword) + + api.router.POST("/server/rebuild", AuthHandler("g:server:rebuild"), handlePostServerRebuild) + + api.router.PUT("/server/power", AuthHandler("s:power"), handlePutServerPower) + + api.router.POST("/server/command", AuthHandler("s:command"), handlePostServerCommand) + + api.router.GET("/server/log", AuthHandler("s:console"), handleGetServerLog) + + api.router.POST("/server/suspend", AuthHandler(""), handlePostServerSuspend) + + api.router.POST("/server/unsuspend", AuthHandler(""), handlePostServerUnsuspend) +} diff --git a/api/routes_server_files.go b/api/routes_server_files.go new file mode 100644 index 0000000..2a8d933 --- /dev/null +++ b/api/routes_server_files.go @@ -0,0 +1,29 @@ +package api + +func (api *API) registerServerFileRoutes() { + // TODO: better and more consistent route names. + + api.router.POST("/server/file/folder", AuthHandler("s:files:create"), handlePostFilesFolder) + + api.router.GET("/server/directory/:directory", AuthHandler("s:files:get"), handleGetDirectory) + + api.router.POST("/server/file/copy", AuthHandler("s:files:copy"), handlePostFileCopy) + + api.router.POST("/server/file/{move,rename}", AuthHandler("s:files:move"), handlePostFileMove) + + api.router.POST("/server/file/delete", AuthHandler("s:files:delete"), handlePostFileDelete) + + api.router.POST("/server/file/compress", AuthHandler("s:files:compress"), handlePostFileCompress) + + api.router.POST("/server/file/decompress", AuthHandler("s:files:decompress"), handlePostFileDecompress) + + api.router.GET("/server/file/stat/:file", AuthHandler("s:files:"), handleGetFileStat) + + api.router.GET("/server/file/f/:file", AuthHandler("s:files:read"), handleGetFile) + + api.router.POST("/server/file/save", AuthHandler("s:files:post"), handlePostFile) + + api.router.DELETE("/server/file/f/:file", AuthHandler("s:files:delete"), handleDeleteFile) + + api.router.GET("/server/file/download/:token", handleGetDownloadFile) +} diff --git a/constants/index_page.go b/constants/index_page.go new file mode 100644 index 0000000..b5f75e3 --- /dev/null +++ b/constants/index_page.go @@ -0,0 +1,29 @@ +package constants + +const IndexPage = ` + + + + Pterodactly wings + + +
+                     ____
+__ Pterodactyl _____/___/_______ _______ ______
+\_____\    \/\/    /   /       /  __   /   ___/
+   \___\          /   /   /   /  /_/  /___   /
+        \___/\___/___/___/___/___    /______/
+                            /_______/
+
+ + +`