From da9ace5d9d7e3577524f43c295976543aa7f1284 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sun, 29 Nov 2020 11:58:20 -0800 Subject: [PATCH 01/11] Create FUNDING.yml --- .github/FUNDING.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..985087d --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,2 @@ +github: [DaneEveritt] +custom: ["https://paypal.me/PterodactylSoftware"] From f62f71486375266061acaac63beb6d942f4e08f5 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Sun, 29 Nov 2020 13:07:45 -0700 Subject: [PATCH 02/11] Add chmod endpoint to server files --- router/router.go | 1 + router/router_server_files.go | 56 +++++++++++++++++++++++++++++++++ server/filesystem/filesystem.go | 17 ++++++++++ 3 files changed, 74 insertions(+) diff --git a/router/router.go b/router/router.go index a8bd839..824acfa 100644 --- a/router/router.go +++ b/router/router.go @@ -87,6 +87,7 @@ func Configure() *gin.Engine { files.POST("/delete", postServerDeleteFiles) files.POST("/compress", postServerCompressFiles) files.POST("/decompress", postServerDecompressFiles) + files.POST("/chmod", postServerChmodFile) } backup := server.Group("/backup") diff --git a/router/router_server_files.go b/router/router_server_files.go index db46d23..bf8f183 100644 --- a/router/router_server_files.go +++ b/router/router_server_files.go @@ -365,6 +365,62 @@ func postServerDecompressFiles(c *gin.Context) { c.Status(http.StatusNoContent) } +type chmodFile struct { + File string `json:"file"` + Mode os.FileMode `json:"mode"` +} + +func postServerChmodFile(c *gin.Context) { + s := GetServer(c.Param("server")) + + var data struct { + Root string `json:"root"` + Files []chmodFile `json:"files"` + } + + if err := c.BindJSON(&data); err != nil { + return + } + + if len(data.Files) == 0 { + c.AbortWithStatusJSON(http.StatusUnprocessableEntity, gin.H{ + "error": "No files to chmod were provided.", + }) + return + } + + g, ctx := errgroup.WithContext(context.Background()) + + // Loop over the array of files passed in and perform the move or rename action against each. + for _, p := range data.Files { + g.Go(func() error { + select { + case <-ctx.Done(): + return ctx.Err() + default: + if err := s.Filesystem().Chmod(path.Join(data.Root, p.File), p.Mode); err != nil { + // Return nil if the error is an is not exists. + // NOTE: os.IsNotExist() does not work if the error is wrapped. + if errors.Is(err, os.ErrNotExist) { + return nil + } + + return err + } + + return nil + } + }) + } + + if err := g.Wait(); err != nil { + TrackedServerError(err, s).AbortFilesystemError(c) + return + } + + c.Status(http.StatusNoContent) +} + func postServerUploadFiles(c *gin.Context) { token := tokens.UploadPayload{} if err := tokens.ParseToken([]byte(c.Query("token")), &token); err != nil { diff --git a/server/filesystem/filesystem.go b/server/filesystem/filesystem.go index d9b8d06..f04a7f2 100644 --- a/server/filesystem/filesystem.go +++ b/server/filesystem/filesystem.go @@ -227,6 +227,23 @@ func (fs *Filesystem) Chown(path string) error { }) } +func (fs *Filesystem) Chmod(path string, mode os.FileMode) error { + cleaned, err := fs.SafePath(path) + if err != nil { + return err + } + + if fs.isTest { + return nil + } + + if err := os.Chmod(cleaned, mode); err != nil { + return err + } + + return nil +} + // Begin looping up to 50 times to try and create a unique copy file name. This will take // an input of "file.txt" and generate "file copy.txt". If that name is already taken, it will // then try to write "file copy 2.txt" and so on, until reaching 50 loops. At that point we From c6e28890755c89f30ea941c7c16a8f334bc58603 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Sun, 29 Nov 2020 13:44:28 -0700 Subject: [PATCH 03/11] Fix chmod endpoint --- router/router_server_files.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/router/router_server_files.go b/router/router_server_files.go index bf8f183..b044784 100644 --- a/router/router_server_files.go +++ b/router/router_server_files.go @@ -2,6 +2,7 @@ package router import ( "context" + "github.com/apex/log" "github.com/gin-gonic/gin" "github.com/pkg/errors" "github.com/pterodactyl/wings/router/tokens" @@ -366,8 +367,8 @@ func postServerDecompressFiles(c *gin.Context) { } type chmodFile struct { - File string `json:"file"` - Mode os.FileMode `json:"mode"` + File string `json:"file"` + Mode string `json:"mode"` } func postServerChmodFile(c *gin.Context) { @@ -379,6 +380,7 @@ func postServerChmodFile(c *gin.Context) { } if err := c.BindJSON(&data); err != nil { + log.Debug(err.Error()) return } @@ -398,7 +400,12 @@ func postServerChmodFile(c *gin.Context) { case <-ctx.Done(): return ctx.Err() default: - if err := s.Filesystem().Chmod(path.Join(data.Root, p.File), p.Mode); err != nil { + mode, err := strconv.ParseUint(p.Mode, 10, 32) + if err != nil { + return err + } + + if err := s.Filesystem().Chmod(path.Join(data.Root, p.File), os.FileMode(uint32(mode))); err != nil { // Return nil if the error is an is not exists. // NOTE: os.IsNotExist() does not work if the error is wrapped. if errors.Is(err, os.ErrNotExist) { From 169e8b8f8bafaa617ee2fb7333e05c99ce335f2b Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Sun, 29 Nov 2020 13:48:15 -0700 Subject: [PATCH 04/11] Fix chmod endpoint mode value --- router/router_server_files.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/router/router_server_files.go b/router/router_server_files.go index b044784..419e66b 100644 --- a/router/router_server_files.go +++ b/router/router_server_files.go @@ -400,12 +400,12 @@ func postServerChmodFile(c *gin.Context) { case <-ctx.Done(): return ctx.Err() default: - mode, err := strconv.ParseUint(p.Mode, 10, 32) + mode, err := strconv.ParseUint(p.Mode, 8, 32) if err != nil { return err } - if err := s.Filesystem().Chmod(path.Join(data.Root, p.File), os.FileMode(uint32(mode))); err != nil { + if err := s.Filesystem().Chmod(path.Join(data.Root, p.File), os.FileMode(mode)); err != nil { // Return nil if the error is an is not exists. // NOTE: os.IsNotExist() does not work if the error is wrapped. if errors.Is(err, os.ErrNotExist) { From 068f41393d80481cfac9bdf7571a992ebf239cf7 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Sun, 29 Nov 2020 14:20:24 -0700 Subject: [PATCH 05/11] Return mode_bits when listing files in a directory --- server/filesystem/stat.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/filesystem/stat.go b/server/filesystem/stat.go index 7896f9f..a7465c8 100644 --- a/server/filesystem/stat.go +++ b/server/filesystem/stat.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/gabriel-vasile/mimetype" "os" + "strconv" "time" ) @@ -18,6 +19,7 @@ func (s *Stat) MarshalJSON() ([]byte, error) { Created string `json:"created"` Modified string `json:"modified"` Mode string `json:"mode"` + ModeBits string `json:"mode_bits"` Size int64 `json:"size"` Directory bool `json:"directory"` File bool `json:"file"` @@ -28,6 +30,7 @@ func (s *Stat) MarshalJSON() ([]byte, error) { Created: s.CTime().Format(time.RFC3339), Modified: s.Info.ModTime().Format(time.RFC3339), Mode: s.Info.Mode().String(), + ModeBits: strconv.FormatUint(uint64(s.Info.Mode()), 8), Size: s.Info.Size(), Directory: s.Info.IsDir(), File: !s.Info.IsDir(), From ba0a1a651eebcaf588ec713ed0fa63a085309b75 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Sun, 29 Nov 2020 16:13:07 -0700 Subject: [PATCH 06/11] Only use the permission bits for ModeBits --- server/filesystem/stat.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/server/filesystem/stat.go b/server/filesystem/stat.go index a7465c8..a6c014d 100644 --- a/server/filesystem/stat.go +++ b/server/filesystem/stat.go @@ -26,11 +26,12 @@ func (s *Stat) MarshalJSON() ([]byte, error) { Symlink bool `json:"symlink"` Mime string `json:"mime"` }{ - Name: s.Info.Name(), - Created: s.CTime().Format(time.RFC3339), - Modified: s.Info.ModTime().Format(time.RFC3339), - Mode: s.Info.Mode().String(), - ModeBits: strconv.FormatUint(uint64(s.Info.Mode()), 8), + Name: s.Info.Name(), + Created: s.CTime().Format(time.RFC3339), + Modified: s.Info.ModTime().Format(time.RFC3339), + Mode: s.Info.Mode().String(), + // Using `&os.ModePerm` on the file's mode will cause the mode to only have the permission values, and nothing else. + ModeBits: strconv.FormatUint(uint64(s.Info.Mode()&os.ModePerm), 8), Size: s.Info.Size(), Directory: s.Info.IsDir(), File: !s.Info.IsDir(), From 4a7510d36f0dc03791e1070bfdd83cf35eac7f52 Mon Sep 17 00:00:00 2001 From: Tortle Date: Tue, 1 Dec 2020 20:43:40 +0100 Subject: [PATCH 07/11] Allow multiple publishing on multiple interfaces on same port. Fixes the issue where you cannot have multiple ip addresses on the same port for a server. --- environment/allocations.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/environment/allocations.go b/environment/allocations.go index b48e294..6e25f69 100644 --- a/environment/allocations.go +++ b/environment/allocations.go @@ -38,15 +38,26 @@ func (a *Allocations) Bindings() nat.PortMap { continue } - binding := []nat.PortBinding{ - { - HostIP: ip, - HostPort: strconv.Itoa(port), - }, + binding := nat.PortBinding{ + HostIP: ip, + HostPort: strconv.Itoa(port), } - out[nat.Port(fmt.Sprintf("%d/tcp", port))] = binding - out[nat.Port(fmt.Sprintf("%d/udp", port))] = binding + tcpPort, ok := out[nat.Port(fmt.Sprintf("%d/tcp", port))] + + if !ok { + out[nat.Port(fmt.Sprintf("%d/tcp", port))] = []nat.PortBinding{binding} + } else { + out[nat.Port(fmt.Sprintf("%d/tcp", port))] = append(tcpPort, binding) + } + + udpPort, ok := out[nat.Port(fmt.Sprintf("%d/udp", port))] + + if !ok { + out[nat.Port(fmt.Sprintf("%d/udp", port))] = []nat.PortBinding{binding} + } else { + out[nat.Port(fmt.Sprintf("%d/udp", port))] = append(udpPort, binding) + } } } From 51aa4c73cdd577d96f7cf99278d22bab5d07eff5 Mon Sep 17 00:00:00 2001 From: Tortle Date: Tue, 1 Dec 2020 21:20:01 +0100 Subject: [PATCH 08/11] Update allocations.go --- environment/allocations.go | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/environment/allocations.go b/environment/allocations.go index 6e25f69..cb8aad7 100644 --- a/environment/allocations.go +++ b/environment/allocations.go @@ -43,17 +43,13 @@ func (a *Allocations) Bindings() nat.PortMap { HostPort: strconv.Itoa(port), } - tcpPort, ok := out[nat.Port(fmt.Sprintf("%d/tcp", port))] - - if !ok { + if tcpPort, ok := out[nat.Port(fmt.Sprintf("%d/tcp", port))]; !ok { out[nat.Port(fmt.Sprintf("%d/tcp", port))] = []nat.PortBinding{binding} } else { out[nat.Port(fmt.Sprintf("%d/tcp", port))] = append(tcpPort, binding) } - udpPort, ok := out[nat.Port(fmt.Sprintf("%d/udp", port))] - - if !ok { + if udpPort, ok := out[nat.Port(fmt.Sprintf("%d/udp", port))]; !ok { out[nat.Port(fmt.Sprintf("%d/udp", port))] = []nat.PortBinding{binding} } else { out[nat.Port(fmt.Sprintf("%d/udp", port))] = append(udpPort, binding) From e7d93a5248c6a815b25358d07374075df8073863 Mon Sep 17 00:00:00 2001 From: Tortle Date: Tue, 1 Dec 2020 23:03:05 +0100 Subject: [PATCH 09/11] Update allocations.go --- environment/allocations.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/environment/allocations.go b/environment/allocations.go index cb8aad7..d301e30 100644 --- a/environment/allocations.go +++ b/environment/allocations.go @@ -43,16 +43,16 @@ func (a *Allocations) Bindings() nat.PortMap { HostPort: strconv.Itoa(port), } - if tcpPort, ok := out[nat.Port(fmt.Sprintf("%d/tcp", port))]; !ok { - out[nat.Port(fmt.Sprintf("%d/tcp", port))] = []nat.PortBinding{binding} + if v, ok := out[nat.Port(fmt.Sprintf("%d/tcp", port))]; ok { + out[nat.Port(fmt.Sprintf("%d/tcp", port))] = append(v, binding) } else { - out[nat.Port(fmt.Sprintf("%d/tcp", port))] = append(tcpPort, binding) + out[nat.Port(fmt.Sprintf("%d/tcp", port))] = []nat.PortBinding{binding} } - if udpPort, ok := out[nat.Port(fmt.Sprintf("%d/udp", port))]; !ok { - out[nat.Port(fmt.Sprintf("%d/udp", port))] = []nat.PortBinding{binding} + if v, ok := out[nat.Port(fmt.Sprintf("%d/udp", port))]; ok { + out[nat.Port(fmt.Sprintf("%d/udp", port))] = append(v, binding) } else { - out[nat.Port(fmt.Sprintf("%d/udp", port))] = append(udpPort, binding) + out[nat.Port(fmt.Sprintf("%d/udp", port))] = []nat.PortBinding{binding} } } } From da4c542724604c082d6d76115ada83ea607d77b2 Mon Sep 17 00:00:00 2001 From: TortleWortle Date: Wed, 2 Dec 2020 14:27:37 +0100 Subject: [PATCH 10/11] Update allocations.go --- environment/allocations.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/environment/allocations.go b/environment/allocations.go index d301e30..b741f8a 100644 --- a/environment/allocations.go +++ b/environment/allocations.go @@ -43,17 +43,11 @@ func (a *Allocations) Bindings() nat.PortMap { HostPort: strconv.Itoa(port), } - if v, ok := out[nat.Port(fmt.Sprintf("%d/tcp", port))]; ok { - out[nat.Port(fmt.Sprintf("%d/tcp", port))] = append(v, binding) - } else { - out[nat.Port(fmt.Sprintf("%d/tcp", port))] = []nat.PortBinding{binding} - } + tcp := nat.Port(fmt.Sprintf("%d/tcp", port)) + udp := nat.Port(fmt.Sprintf("%d/udp", port)) - if v, ok := out[nat.Port(fmt.Sprintf("%d/udp", port))]; ok { - out[nat.Port(fmt.Sprintf("%d/udp", port))] = append(v, binding) - } else { - out[nat.Port(fmt.Sprintf("%d/udp", port))] = []nat.PortBinding{binding} - } + out[tcp] = append(out[tcp], binding) + out[udp] = append(out[udp], binding) } } From ca6dc2c964237a354c5f2ec7689590c8bb0c9f1e Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Thu, 3 Dec 2020 18:32:59 -0700 Subject: [PATCH 11/11] Remove .travis.yml --- .travis.yml | 47 ----------------------------------------------- 1 file changed, 47 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index cce78ee..0000000 --- a/.travis.yml +++ /dev/null @@ -1,47 +0,0 @@ -os: linux -dist: xenial -language: go - -go: -- 1.13.x - -go_import_path: "github.com/pterodactyl/wings" - -services: -- docker - -install: -- mkdir -p $GOPATH/bin - -# Install used tools -- go get github.com/mitchellh/gox -- go get github.com/haya14busa/goverage -- go get github.com/schrej/godacov - -- go mod download - -script: -- make cross-build -- goverage -v -coverprofile=coverage.out ./... -- godacov -t $CODACY_TOKEN -r ./coverage.out -c $TRAVIS_COMMIT - -deploy: - provider: releases - api_key: - secure: HQ8AvnSsOW2aDUKv25sU83SswK9rReGeFi68SotLGPdWyFBWJbp/JEHhw9swSqvhLPykx5QqLnRPG4nomOp2i5dVTXgM/7C3wQ2ULymkJDZqDJEAxjm1IuNsjXgcFqp0zcNXL3g0moaorHS2XZpzbgaewlCyYoEb+3SZUGzOCPIjSFvoIBaAYx6kRn+pyWo1I0mQChno2i7SGvAoZwh/hZIO6L5FZe5PcpBs/SxkZ+/shsGMk7CIyNMhG6CQTE1tlr+ZenluXjtliZfc4XwkHG/9MICNl8ihUrnN6YfdvJZXLQvolZQ0QJ5Eyb04jQd1yzKR1hcLx2S42IAWxaWTy5QxSN8QyG5wBRNg567ib5FEqY4M1nyQnWQbUbaiYloYBp14aR1L9DQw8+xmXnlgnTUPq1w+cOpQLeY/RENCalgHe7NoI3lClC2b7/c1j+O7RA68yYUFUod0y7ZXcCwsJkbRk7xgyDEAGs+rq8wLknj6f8y8cfNm179lRARwblnmo9uA43Tlee8DBSziSvJy/mYMzdIQeb+PHuznXjr4fze7x+zvronkiD/JH8MjJl3SWaE7DGtc5jz4+aRxU3rMbHwToEOY6u5pIsvz5PRFYWBvKX2+VoxmdR+m1qhAxsg0wtbA0CTnqgHNGMIFDWVTDQSy8LvJt+usUn1RtrYyyiI= - file_glob: true - file: build/* - on: - tags: true - branch: master - -notifications: - email: false - webhooks: - urls: - - https://misc.schrej.net/travistodiscord/pterodev.php - on_success: change - on_failure: always - on_error: always - on_cancel: always - on_start: never