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
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			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
 | 
			
		||||
			tcp := nat.Port(fmt.Sprintf("%d/tcp", port))
 | 
			
		||||
			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("/compress", postServerCompressFiles)
 | 
			
		||||
			files.POST("/decompress", postServerDecompressFiles)
 | 
			
		||||
			files.POST("/chmod", postServerChmodFile)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		backup := server.Group("/backup")
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			@ -365,6 +366,68 @@ func postServerDecompressFiles(c *gin.Context) {
 | 
			
		|||
	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) {
 | 
			
		||||
	token := tokens.UploadPayload{}
 | 
			
		||||
	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
 | 
			
		||||
// 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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import (
 | 
			
		|||
	"encoding/json"
 | 
			
		||||
	"github.com/gabriel-vasile/mimetype"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18,16 +19,19 @@ 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"`
 | 
			
		||||
		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(),
 | 
			
		||||
		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(),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue
	
	Block a user