Merge branch 'develop' of https://github.com/pterodactyl/wings into develop
This commit is contained in:
commit
83f0d2c953
2
.github/FUNDING.yml
vendored
Normal file
2
.github/FUNDING.yml
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
github: [DaneEveritt]
|
||||||
|
custom: ["https://paypal.me/PterodactylSoftware"]
|
47
.travis.yml
47
.travis.yml
|
@ -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
|
|
|
@ -38,15 +38,16 @@ func (a *Allocations) Bindings() nat.PortMap {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
binding := []nat.PortBinding{
|
binding := nat.PortBinding{
|
||||||
{
|
HostIP: ip,
|
||||||
HostIP: ip,
|
HostPort: strconv.Itoa(port),
|
||||||
HostPort: strconv.Itoa(port),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out[nat.Port(fmt.Sprintf("%d/tcp", port))] = binding
|
tcp := nat.Port(fmt.Sprintf("%d/tcp", port))
|
||||||
out[nat.Port(fmt.Sprintf("%d/udp", port))] = binding
|
udp := nat.Port(fmt.Sprintf("%d/udp", port))
|
||||||
|
|
||||||
|
out[tcp] = append(out[tcp], binding)
|
||||||
|
out[udp] = append(out[udp], binding)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ func Configure() *gin.Engine {
|
||||||
files.POST("/delete", postServerDeleteFiles)
|
files.POST("/delete", postServerDeleteFiles)
|
||||||
files.POST("/compress", postServerCompressFiles)
|
files.POST("/compress", postServerCompressFiles)
|
||||||
files.POST("/decompress", postServerDecompressFiles)
|
files.POST("/decompress", postServerDecompressFiles)
|
||||||
|
files.POST("/chmod", postServerChmodFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
backup := server.Group("/backup")
|
backup := server.Group("/backup")
|
||||||
|
|
|
@ -2,6 +2,7 @@ package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/apex/log"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/pterodactyl/wings/router/tokens"
|
"github.com/pterodactyl/wings/router/tokens"
|
||||||
|
@ -365,6 +366,68 @@ func postServerDecompressFiles(c *gin.Context) {
|
||||||
c.Status(http.StatusNoContent)
|
c.Status(http.StatusNoContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type chmodFile struct {
|
||||||
|
File string `json:"file"`
|
||||||
|
Mode string `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 {
|
||||||
|
log.Debug(err.Error())
|
||||||
|
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:
|
||||||
|
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(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) {
|
func postServerUploadFiles(c *gin.Context) {
|
||||||
token := tokens.UploadPayload{}
|
token := tokens.UploadPayload{}
|
||||||
if err := tokens.ParseToken([]byte(c.Query("token")), &token); err != nil {
|
if err := tokens.ParseToken([]byte(c.Query("token")), &token); err != nil {
|
||||||
|
|
|
@ -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
|
// 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
|
// 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
|
// then try to write "file copy 2.txt" and so on, until reaching 50 loops. At that point we
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/gabriel-vasile/mimetype"
|
"github.com/gabriel-vasile/mimetype"
|
||||||
"os"
|
"os"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,16 +19,19 @@ func (s *Stat) MarshalJSON() ([]byte, error) {
|
||||||
Created string `json:"created"`
|
Created string `json:"created"`
|
||||||
Modified string `json:"modified"`
|
Modified string `json:"modified"`
|
||||||
Mode string `json:"mode"`
|
Mode string `json:"mode"`
|
||||||
|
ModeBits string `json:"mode_bits"`
|
||||||
Size int64 `json:"size"`
|
Size int64 `json:"size"`
|
||||||
Directory bool `json:"directory"`
|
Directory bool `json:"directory"`
|
||||||
File bool `json:"file"`
|
File bool `json:"file"`
|
||||||
Symlink bool `json:"symlink"`
|
Symlink bool `json:"symlink"`
|
||||||
Mime string `json:"mime"`
|
Mime string `json:"mime"`
|
||||||
}{
|
}{
|
||||||
Name: s.Info.Name(),
|
Name: s.Info.Name(),
|
||||||
Created: s.CTime().Format(time.RFC3339),
|
Created: s.CTime().Format(time.RFC3339),
|
||||||
Modified: s.Info.ModTime().Format(time.RFC3339),
|
Modified: s.Info.ModTime().Format(time.RFC3339),
|
||||||
Mode: s.Info.Mode().String(),
|
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(),
|
Size: s.Info.Size(),
|
||||||
Directory: s.Info.IsDir(),
|
Directory: s.Info.IsDir(),
|
||||||
File: !s.Info.IsDir(),
|
File: !s.Info.IsDir(),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user