mirror of
https://github.com/MrUnknownDE/panel.git
synced 2026-04-19 23:03:45 +02:00
Merge branch 'develop'
This commit is contained in:
12
.babel-plugin-macrosrc.js
Normal file
12
.babel-plugin-macrosrc.js
Normal file
@@ -0,0 +1,12 @@
|
||||
module.exports = {
|
||||
twin: {
|
||||
preset: 'styled-components',
|
||||
autoCssProp: true,
|
||||
config: './tailwind.config.js',
|
||||
},
|
||||
styledComponents: {
|
||||
pure: true,
|
||||
displayName: false,
|
||||
fileName: false,
|
||||
},
|
||||
};
|
||||
8
.babelrc
8
.babelrc
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"presets": ["es2015"],
|
||||
"compact": true,
|
||||
"minified": true,
|
||||
"only": "public/themes/pterodactyl/js/frontend/files/src/*.js",
|
||||
"sourceMaps": "inline",
|
||||
"comments": false
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
APP_ENV=develop
|
||||
APP_DEBUG=true
|
||||
APP_KEY=SomeRandomString3232RandomString
|
||||
APP_THEME=pterodactyl
|
||||
APP_TIMEZONE=UTC
|
||||
APP_CLEAR_TASKLOG=720
|
||||
APP_DELETE_MINUTES=10
|
||||
APP_URL=http://192.168.50.2/
|
||||
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=panel
|
||||
DB_USERNAME=pterodactyl
|
||||
DB_PASSWORD=pterodactyl
|
||||
|
||||
CACHE_DRIVER=memcached
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
SESSION_DRIVER=database
|
||||
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=127.0.0.1
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=
|
||||
MAIL_PASSWORD=
|
||||
MAIL_ENCRYPTION=
|
||||
MAIL_FROM=support@pterodactyl.io
|
||||
|
||||
API_PREFIX=api
|
||||
API_VERSION=v1
|
||||
API_DEBUG=true
|
||||
|
||||
QUEUE_DRIVER=database
|
||||
QUEUE_HIGH=high
|
||||
QUEUE_STANDARD=standard
|
||||
QUEUE_LOW=low
|
||||
|
||||
SQS_KEY=aws-public
|
||||
SQS_SECRET=aws-secret
|
||||
SQS_QUEUE_PREFIX=aws-queue-prefix
|
||||
@@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=Mailhog
|
||||
|
||||
[Service]
|
||||
# On some systems the user and group might be different.
|
||||
# Some systems use `apache` as the user and group.
|
||||
User=www-data
|
||||
Group=www-data
|
||||
Restart=on-failure
|
||||
ExecStart=/usr/bin/mailhog
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,189 +0,0 @@
|
||||
# MariaDB database server configuration file.
|
||||
#
|
||||
# You can copy this file to one of:
|
||||
# - "/etc/mysql/my.cnf" to set global options,
|
||||
# - "~/.my.cnf" to set user-specific options.
|
||||
#
|
||||
# One can use all long options that the program supports.
|
||||
# Run program with --help to get a list of available options and with
|
||||
# --print-defaults to see which it would actually understand and use.
|
||||
#
|
||||
# For explanations see
|
||||
# http://dev.mysql.com/doc/mysql/en/server-system-variables.html
|
||||
|
||||
# This will be passed to all mysql clients
|
||||
# It has been reported that passwords should be enclosed with ticks/quotes
|
||||
# escpecially if they contain "#" chars...
|
||||
# Remember to edit /etc/mysql/debian.cnf when changing the socket location.
|
||||
[client]
|
||||
port = 3306
|
||||
socket = /var/run/mysqld/mysqld.sock
|
||||
|
||||
# Here is entries for some specific programs
|
||||
# The following values assume you have at least 32M ram
|
||||
|
||||
# This was formally known as [safe_mysqld]. Both versions are currently parsed.
|
||||
[mysqld_safe]
|
||||
socket = /var/run/mysqld/mysqld.sock
|
||||
nice = 0
|
||||
|
||||
[mysqld]
|
||||
#
|
||||
# * Basic Settings
|
||||
#
|
||||
user = mysql
|
||||
pid-file = /var/run/mysqld/mysqld.pid
|
||||
socket = /var/run/mysqld/mysqld.sock
|
||||
port = 3306
|
||||
basedir = /usr
|
||||
datadir = /var/lib/mysql
|
||||
tmpdir = /tmp
|
||||
lc_messages_dir = /usr/share/mysql
|
||||
lc_messages = en_US
|
||||
skip-external-locking
|
||||
#
|
||||
# Instead of skip-networking the default is now to listen only on
|
||||
# localhost which is more compatible and is not less secure.
|
||||
bind-address = 0.0.0.0
|
||||
#
|
||||
# * Fine Tuning
|
||||
#
|
||||
max_connections = 100
|
||||
connect_timeout = 5
|
||||
wait_timeout = 600
|
||||
max_allowed_packet = 16M
|
||||
thread_cache_size = 128
|
||||
sort_buffer_size = 4M
|
||||
bulk_insert_buffer_size = 16M
|
||||
tmp_table_size = 32M
|
||||
max_heap_table_size = 32M
|
||||
#
|
||||
# * MyISAM
|
||||
#
|
||||
# This replaces the startup script and checks MyISAM tables if needed
|
||||
# the first time they are touched. On error, make copy and try a repair.
|
||||
myisam_recover_options = BACKUP
|
||||
key_buffer_size = 128M
|
||||
#open-files-limit = 2000
|
||||
table_open_cache = 400
|
||||
myisam_sort_buffer_size = 512M
|
||||
concurrent_insert = 2
|
||||
read_buffer_size = 2M
|
||||
read_rnd_buffer_size = 1M
|
||||
#
|
||||
# * Query Cache Configuration
|
||||
#
|
||||
# Cache only tiny result sets, so we can fit more in the query cache.
|
||||
query_cache_limit = 128K
|
||||
query_cache_size = 64M
|
||||
# for more write intensive setups, set to DEMAND or OFF
|
||||
#query_cache_type = DEMAND
|
||||
#
|
||||
# * Logging and Replication
|
||||
#
|
||||
# Both location gets rotated by the cronjob.
|
||||
# Be aware that this log type is a performance killer.
|
||||
# As of 5.1 you can enable the log at runtime!
|
||||
#general_log_file = /var/log/mysql/mysql.log
|
||||
#general_log = 1
|
||||
#
|
||||
# Error logging goes to syslog due to /etc/mysql/conf.d/mysqld_safe_syslog.cnf.
|
||||
#
|
||||
# we do want to know about network errors and such
|
||||
log_warnings = 2
|
||||
#
|
||||
# Enable the slow query log to see queries with especially long duration
|
||||
#slow_query_log[={0|1}]
|
||||
slow_query_log_file = /var/log/mysql/mariadb-slow.log
|
||||
long_query_time = 10
|
||||
#log_slow_rate_limit = 1000
|
||||
log_slow_verbosity = query_plan
|
||||
|
||||
#log-queries-not-using-indexes
|
||||
#log_slow_admin_statements
|
||||
#
|
||||
# The following can be used as easy to replay backup logs or for replication.
|
||||
# note: if you are setting up a replication slave, see README.Debian about
|
||||
# other settings you may need to change.
|
||||
#server-id = 1
|
||||
#report_host = master1
|
||||
#auto_increment_increment = 2
|
||||
#auto_increment_offset = 1
|
||||
log_bin = /var/log/mysql/mariadb-bin
|
||||
log_bin_index = /var/log/mysql/mariadb-bin.index
|
||||
# not fab for performance, but safer
|
||||
#sync_binlog = 1
|
||||
expire_logs_days = 10
|
||||
max_binlog_size = 100M
|
||||
# slaves
|
||||
#relay_log = /var/log/mysql/relay-bin
|
||||
#relay_log_index = /var/log/mysql/relay-bin.index
|
||||
#relay_log_info_file = /var/log/mysql/relay-bin.info
|
||||
#log_slave_updates
|
||||
#read_only
|
||||
#
|
||||
# If applications support it, this stricter sql_mode prevents some
|
||||
# mistakes like inserting invalid dates etc.
|
||||
#sql_mode = NO_ENGINE_SUBSTITUTION,TRADITIONAL
|
||||
#
|
||||
# * InnoDB
|
||||
#
|
||||
# InnoDB is enabled by default with a 10MB datafile in /var/lib/mysql/.
|
||||
# Read the manual for more InnoDB related options. There are many!
|
||||
default_storage_engine = InnoDB
|
||||
# you can't just change log file size, requires special procedure
|
||||
#innodb_log_file_size = 50M
|
||||
innodb_buffer_pool_size = 256M
|
||||
innodb_log_buffer_size = 8M
|
||||
innodb_file_per_table = 1
|
||||
innodb_open_files = 400
|
||||
innodb_io_capacity = 400
|
||||
innodb_flush_method = O_DIRECT
|
||||
#
|
||||
# * Security Features
|
||||
#
|
||||
# Read the manual, too, if you want chroot!
|
||||
# chroot = /var/lib/mysql/
|
||||
#
|
||||
# For generating SSL certificates I recommend the OpenSSL GUI "tinyca".
|
||||
#
|
||||
# ssl-ca=/etc/mysql/cacert.pem
|
||||
# ssl-cert=/etc/mysql/server-cert.pem
|
||||
# ssl-key=/etc/mysql/server-key.pem
|
||||
|
||||
#
|
||||
# * Galera-related settings
|
||||
#
|
||||
[galera]
|
||||
# Mandatory settings
|
||||
#wsrep_on=ON
|
||||
#wsrep_provider=
|
||||
#wsrep_cluster_address=
|
||||
#binlog_format=row
|
||||
#default_storage_engine=InnoDB
|
||||
#innodb_autoinc_lock_mode=2
|
||||
#
|
||||
# Allow server to accept connections on all interfaces.
|
||||
#
|
||||
#bind-address=0.0.0.0
|
||||
#
|
||||
# Optional setting
|
||||
#wsrep_slave_threads=1
|
||||
#innodb_flush_log_at_trx_commit=0
|
||||
|
||||
[mysqldump]
|
||||
quick
|
||||
quote-names
|
||||
max_allowed_packet = 16M
|
||||
|
||||
[mysql]
|
||||
#no-auto-rehash # faster start of mysql but no tab completion
|
||||
|
||||
[isamchk]
|
||||
key_buffer = 16M
|
||||
|
||||
#
|
||||
# * IMPORTANT: Additional settings that can override those from this file!
|
||||
# The files must end with '.cnf', otherwise they'll be ignored.
|
||||
#
|
||||
!includedir /etc/mysql/conf.d/
|
||||
@@ -1,17 +0,0 @@
|
||||
#####################################################
|
||||
Pterodactyl Panel Vagrant VM
|
||||
|
||||
Install: /var/www/html/pterodactyl
|
||||
Ports:
|
||||
Panel: 80 (50080 on host)
|
||||
MailHog: 8025 (58025 on host)
|
||||
MySQL: 3306 (53306 on host)
|
||||
|
||||
Default panel users:
|
||||
user: admin passwd: Ptero123 (admin user)
|
||||
user: user passwd: Ptero123 (standard user)
|
||||
|
||||
MySQL is accessible using root/pterodactyl or pterodactyl/pterodactyl
|
||||
|
||||
Service for pteroq and mailhog are running
|
||||
#####################################################
|
||||
@@ -1,84 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Provisioning development environment for Pterodactyl Panel."
|
||||
cp /var/www/html/pterodactyl/.dev/vagrant/motd.txt /etc/motd
|
||||
chmod -x /etc/update-motd.d/10-help-text /etc/update-motd.d/51-cloudguest
|
||||
|
||||
apt-get install -y software-properties-common > /dev/null
|
||||
|
||||
echo "Add the ondrej/php ppa repository"
|
||||
add-apt-repository -y ppa:ondrej/php > /dev/null
|
||||
echo "Add the mariadb repository"
|
||||
curl -sS https://downloads.mariadb.com/MariaDB/mariadb_repo_setup | bash > /dev/null
|
||||
|
||||
apt-get update > /dev/null
|
||||
|
||||
echo "Install the dependencies"
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
# set the mariadb root password because mariadb asks for it
|
||||
debconf-set-selections <<< 'mariadb-server-5.5 mysql-server/root_password password pterodactyl'
|
||||
debconf-set-selections <<< 'mariadb-server-5.5 mysql-server/root_password_again password pterodactyl'
|
||||
# actually install
|
||||
apt-get install -y php7.2 php7.2-cli php7.2-gd php7.2-mysql php7.2-pdo php7.2-mbstring php7.2-tokenizer php7.2-bcmath php7.2-xml php7.2-fpm php7.2-memcached php7.2-curl php7.2-zip php-xdebug mariadb-server nginx curl tar unzip git memcached > /dev/null
|
||||
|
||||
echo "Install composer"
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
echo "Install and run mailhog"
|
||||
curl -sL -o /usr/bin/mailhog https://github.com/mailhog/MailHog/releases/download/v1.0.0/MailHog_linux_amd64
|
||||
chmod +x /usr/bin/mailhog
|
||||
cp /var/www/html/pterodactyl/.dev/vagrant/mailhog.service /etc/systemd/system/
|
||||
systemctl enable mailhog.service
|
||||
systemctl start mailhog
|
||||
|
||||
echo "Configure xDebug"
|
||||
cp /var/www/html/pterodactyl/.dev/vagrant/xdebug.ini /etc/php/7.2/mods-available/
|
||||
systemctl restart php7.2-fpm
|
||||
|
||||
echo "Configure nginx"
|
||||
cp /var/www/html/pterodactyl/.dev/vagrant/pterodactyl.conf /etc/nginx/sites-available/
|
||||
rm /etc/nginx/sites-available/default
|
||||
ln -s /etc/nginx/sites-available/pterodactyl.conf /etc/nginx/sites-enabled/pterodactyl.conf
|
||||
systemctl restart nginx
|
||||
|
||||
echo "Setup database"
|
||||
# Replace default config with custom one to bind mysql to 0.0.0.0 to make it accessible from the host
|
||||
cp /var/www/html/pterodactyl/.dev/vagrant/mariadb.cnf /etc/mysql/my.cnf
|
||||
systemctl restart mariadb
|
||||
mysql -u root -ppterodactyl << SQL
|
||||
CREATE DATABASE panel;
|
||||
GRANT ALL PRIVILEGES ON panel.* TO 'pterodactyl'@'%' IDENTIFIED BY 'pterodactyl' WITH GRANT OPTION;
|
||||
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'pterodactyl' WITH GRANT OPTION;
|
||||
FLUSH PRIVILEGES;
|
||||
SQL
|
||||
|
||||
echo "Setup pterodactyl queue worker service"
|
||||
cp /var/www/html/pterodactyl/.dev/vagrant/pteroq.service /etc/systemd/system/
|
||||
systemctl enable pteroq.service
|
||||
|
||||
|
||||
echo "Setup panel with base settings"
|
||||
cp /var/www/html/pterodactyl/.dev/vagrant/.env.vagrant /var/www/html/pterodactyl/.env
|
||||
cd /var/www/html/pterodactyl
|
||||
chmod -R 755 storage/* bootstrap/cache
|
||||
composer install --no-progress
|
||||
php artisan key:generate --force
|
||||
php artisan migrate
|
||||
php artisan db:seed
|
||||
php artisan p:user:make --name-first Test --name-last Admin --username admin --email testadmin@pterodactyl.io --password Ptero123 --admin 1
|
||||
php artisan p:user:make --name-first Test --name-last User --username user --email testuser@pterodactyl.io --password Ptero123 --admin 0
|
||||
|
||||
echo "Add queue cronjob and start queue worker"
|
||||
(crontab -l 2>/dev/null; echo "* * * * * php /var/www/html/pterodactyl/artisan schedule:run >> /dev/null 2>&1") | crontab -
|
||||
systemctl start pteroq
|
||||
|
||||
echo " ----------------"
|
||||
echo "Provisioning is completed."
|
||||
echo "The panel should be available at http://localhost:50080/"
|
||||
echo "You may use the default admin user to login: admin/Ptero123"
|
||||
echo "A normal user has also been created: user/Ptero123"
|
||||
echo "MailHog is available at http://localhost:58025/"
|
||||
echo "Connect to the database using root/pterodactyl or pterodactyl/pterodactyl on localhost:53306"
|
||||
echo "If you want to access the panel using http://pterodactyl.app you can use the vagrant-dns plugin"
|
||||
echo "Install it with 'vagrant plugin install vagrant-dns', then run 'vagrant dns --install' once"
|
||||
echo "On first use you'll have to manually start vagrant-dns with 'vagrant dns --start'"
|
||||
@@ -1,51 +0,0 @@
|
||||
# If using Ubuntu this file should be placed in:
|
||||
# /etc/nginx/sites-available/
|
||||
#
|
||||
# If using CentOS this file should be placed in:
|
||||
# /etc/nginx/conf.d/
|
||||
#
|
||||
server {
|
||||
listen 80;
|
||||
server_name 0.0.0.0;
|
||||
|
||||
root /var/www/html/pterodactyl/public;
|
||||
index index.html index.htm index.php;
|
||||
charset utf-8;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$query_string;
|
||||
}
|
||||
|
||||
location = /favicon.ico { access_log off; log_not_found off; }
|
||||
location = /robots.txt { access_log off; log_not_found off; }
|
||||
|
||||
access_log off;
|
||||
error_log /var/log/nginx/pterodactyl.app-error.log error;
|
||||
|
||||
# allow larger file uploads and longer script runtimes
|
||||
client_max_body_size 100m;
|
||||
client_body_timeout 120s;
|
||||
|
||||
sendfile off;
|
||||
|
||||
location ~ \.php$ {
|
||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
||||
# the fastcgi_pass path needs to be changed accordingly when using CentOS
|
||||
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
|
||||
fastcgi_index index.php;
|
||||
include fastcgi_params;
|
||||
fastcgi_param PHP_VALUE "upload_max_filesize = 100M \n post_max_size=100M";
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param HTTP_PROXY "";
|
||||
fastcgi_intercept_errors off;
|
||||
fastcgi_buffer_size 16k;
|
||||
fastcgi_buffers 4 16k;
|
||||
fastcgi_connect_timeout 300;
|
||||
fastcgi_send_timeout 300;
|
||||
fastcgi_read_timeout 300;
|
||||
}
|
||||
|
||||
location ~ /\.ht {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
# Pterodactyl Queue Worker File
|
||||
# ----------------------------------
|
||||
# File should be placed in:
|
||||
# /etc/systemd/system
|
||||
#
|
||||
# nano /etc/systemd/system/pteroq.service
|
||||
|
||||
[Unit]
|
||||
Description=Pterodactyl Queue Worker
|
||||
|
||||
[Service]
|
||||
# On some systems the user and group might be different.
|
||||
# Some systems use `apache` as the user and group.
|
||||
User=www-data
|
||||
Group=www-data
|
||||
Restart=on-failure
|
||||
ExecStart=/usr/bin/php /var/www/html/pterodactyl/artisan queue:work database --queue=high,standard,low --sleep=3 --tries=3
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -1,10 +0,0 @@
|
||||
zend_extension=xdebug.so
|
||||
|
||||
xdebug.remote_enable=1
|
||||
xdebug.remote_connect_back=1
|
||||
xdebug.remote_port=9000
|
||||
xdebug.scream=0
|
||||
xdebug.show_local_vars=1
|
||||
xdebug.idekey=PHPSTORM
|
||||
|
||||
xdebug.remote_log=/tmp/xdebug.log
|
||||
@@ -8,5 +8,8 @@ indent_size = 4
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[.*yml]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
@@ -2,13 +2,13 @@ APP_ENV=testing
|
||||
APP_DEBUG=true
|
||||
APP_KEY=SomeRandomString3232RandomString
|
||||
APP_THEME=pterodactyl
|
||||
APP_TIMEZONE=UTC
|
||||
APP_TIMEZONE=America/Los_Angeles
|
||||
APP_URL=http://localhost/
|
||||
|
||||
TESTING_DB_HOST=127.0.0.1
|
||||
TESTING_DB_DATABASE=travis
|
||||
TESTING_DB_DATABASE=panel_test
|
||||
TESTING_DB_USERNAME=root
|
||||
TESTING_DB_PASSWORD=""
|
||||
TESTING_DB_PASSWORD=
|
||||
|
||||
CACHE_DRIVER=array
|
||||
SESSION_DRIVER=array
|
||||
26
.env.dusk
Normal file
26
.env.dusk
Normal file
@@ -0,0 +1,26 @@
|
||||
APP_ENV=local
|
||||
APP_DEBUG=false
|
||||
APP_KEY=NDWgIKKi9ovNK1PXZpzfNVSBdfCXGb5i
|
||||
APP_JWT_KEY=test1234
|
||||
APP_TIMEZONE=America/Los_Angeles
|
||||
APP_URL=http://pterodactyl.local
|
||||
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
|
||||
HASHIDS_SALT=IqRr0g82tCTeuyxGs8RV
|
||||
HASHIDS_LENGTH=8
|
||||
|
||||
MAIL_DRIVER=log
|
||||
MAIL_FROM=support@pterodactyl.io
|
||||
QUEUE_DRIVER=array
|
||||
|
||||
APP_SERVICE_AUTHOR=testing@pterodactyl.io
|
||||
MAIL_FROM_NAME="Pterodactyl Panel"
|
||||
RECAPTCHA_ENABLED=false
|
||||
|
||||
DB_CONNECTION=testing
|
||||
TESTING_DB_HOST=192.168.1.202
|
||||
TESTING_DB_DATABASE=panel_test
|
||||
TESTING_DB_USERNAME=panel_test
|
||||
TESTING_DB_PASSWORD=Test1234
|
||||
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"]
|
||||
87
.github/workflows/release.yml
vendored
Normal file
87
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
name: "Release"
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12'
|
||||
|
||||
- name: Create release branch and bump version
|
||||
env:
|
||||
REF: ${{ github.ref }}
|
||||
run: |
|
||||
BRANCH=release/${REF:10}
|
||||
git config --local user.email "ci@pterodactyl.io"
|
||||
git config --local user.name "Pterodactyl CI"
|
||||
git checkout -b $BRANCH
|
||||
git push -u origin $BRANCH
|
||||
sed -i "s/ 'version' => 'canary',/ 'version' => '${REF:11}',/" config/app.php
|
||||
git add config/app.php
|
||||
git commit -m "bump version for release"
|
||||
git push
|
||||
|
||||
- name: Build assets
|
||||
run: |
|
||||
yarn install
|
||||
yarn run build:production
|
||||
|
||||
- name: Create release archive
|
||||
run: |
|
||||
rm -rf node_modules/ test/ codecov.yml CODE_OF_CONDUCT.md CONTRIBUTING.md phpunit.dusk.xml phpunit.xml Vagrantfile
|
||||
tar -czf panel.tar.gz * .env.example
|
||||
|
||||
- name: Extract changelog
|
||||
id: extract_changelog
|
||||
env:
|
||||
REF: ${{ github.ref }}
|
||||
run: |
|
||||
sed -n "/^## ${REF:10}/,/^## /{/^## /b;p}" CHANGELOG.md > ./RELEASE_CHANGELOG
|
||||
echo ::set-output name=version_name::`sed -nr "s/^## (${REF:10} .*)$/\1/p" CHANGELOG.md`
|
||||
|
||||
- name: Create checksum and add to changelog
|
||||
run: |
|
||||
SUM=`sha256sum panel.tar.gz`
|
||||
echo -e "\n#### SHA256 Checksum\n\n\`\`\`\n$SUM\n\`\`\`\n" >> ./RELEASE_CHANGELOG
|
||||
echo $SUM > checksum.txt
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: ${{ steps.extract_changelog.outputs.version_name }}
|
||||
body_path: ./RELEASE_CHANGELOG
|
||||
draft: true
|
||||
prerelease: ${{ contains(github.ref, 'beta') || contains(github.ref, 'alpha') }}
|
||||
|
||||
- name: Upload binary
|
||||
id: upload-release-archive
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: panel.tar.gz
|
||||
asset_name: panel.tar.gz
|
||||
asset_content_type: application/gzip
|
||||
|
||||
- name: Upload checksum
|
||||
id: upload-release-checksum
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ./checksum.txt
|
||||
asset_name: checksum.txt
|
||||
asset_content_type: text/plain
|
||||
67
.github/workflows/tests.yml
vendored
Normal file
67
.github/workflows/tests.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
name: tests
|
||||
on:
|
||||
push:
|
||||
branch-ignore:
|
||||
- 'master'
|
||||
- 'release/**'
|
||||
pull_request:
|
||||
jobs:
|
||||
integration_tests:
|
||||
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]')"
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: panel_test
|
||||
ports:
|
||||
- 3306
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
php: [7.3, 7.4]
|
||||
name: PHP ${{ matrix.php }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: get cache directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "::set-output name=dir::$(composer config cache-files-dir)"
|
||||
- name: cache dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.php_cs.cache
|
||||
${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-cache-${{ matrix.php }}-${{ hashFiles('**.composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-cache-${{ matrix.php }}-
|
||||
- name: setup
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: cli, openssl, gd, mysql, pdo, mbstring, tokenizer, bcmath, xml, curl, zip
|
||||
tools: composer:v1
|
||||
coverage: none
|
||||
- name: configure
|
||||
run: cp .env.ci .env
|
||||
- name: install dependencies
|
||||
run: composer install --prefer-dist --no-interaction --no-progress
|
||||
- name: run cs-fixer
|
||||
run: vendor/bin/php-cs-fixer fix --dry-run --diff --diff-format=udiff
|
||||
continue-on-error: true
|
||||
- name: execute unit tests
|
||||
run: vendor/bin/phpunit --bootstrap bootstrap/app.php tests/Unit
|
||||
if: ${{ always() }}
|
||||
env:
|
||||
DB_CONNECTION: testing
|
||||
TESTING_DB_HOST: UNIT_NO_DB
|
||||
- name: execute integration tests
|
||||
run: vendor/bin/phpunit tests/Integration
|
||||
if: ${{ always() }}
|
||||
env:
|
||||
TESTING_DB_PORT: ${{ job.services.mysql.ports[3306] }}
|
||||
TESTING_DB_USERNAME: root
|
||||
15
.gitignore
vendored
15
.gitignore
vendored
@@ -7,15 +7,12 @@ storage/framework/*
|
||||
/.idea
|
||||
/nbproject
|
||||
|
||||
package-lock.json
|
||||
composer.lock
|
||||
node_modules
|
||||
|
||||
_ide_helper_models.php
|
||||
*.log
|
||||
_ide_helper.php
|
||||
|
||||
sami.phar
|
||||
/.sami
|
||||
.phpstorm.meta.php
|
||||
.php_cs.cache
|
||||
public/assets/manifest.json
|
||||
|
||||
# For local development with docker
|
||||
# Remove if we ever put the Dockerfile in the repo
|
||||
@@ -32,3 +29,7 @@ coverage.xml
|
||||
|
||||
# Vagrant
|
||||
*.log
|
||||
resources/lang/locales.js
|
||||
resources/assets/pterodactyl/scripts/helpers/ziggy.js
|
||||
resources/assets/scripts/helpers/ziggy.js
|
||||
.phpunit.result.cache
|
||||
|
||||
5
.php_cs
5
.php_cs
@@ -33,18 +33,21 @@ return PhpCsFixer\Config::create()
|
||||
'new_with_braces' => false,
|
||||
'no_alias_functions' => true,
|
||||
'no_multiline_whitespace_before_semicolons' => true,
|
||||
'no_superfluous_phpdoc_tags' => false,
|
||||
'no_unreachable_default_argument_value' => true,
|
||||
'no_useless_return' => true,
|
||||
'not_operator_with_successor_space' => true,
|
||||
'ordered_imports' => [
|
||||
'sortAlgorithm' => 'length',
|
||||
],
|
||||
'phpdoc_align' => ['tags' => ['param']],
|
||||
'phpdoc_align' => false,
|
||||
'phpdoc_separation' => false,
|
||||
'protected_to_private' => false,
|
||||
'psr0' => ['dir' => 'app'],
|
||||
'psr4' => true,
|
||||
'random_api_migration' => true,
|
||||
'single_line_throw' => false,
|
||||
'single_trait_insert_per_statement' => false,
|
||||
'standardize_not_equals' => true,
|
||||
'ternary_to_null_coalescing' => true,
|
||||
'yoda_style' => [
|
||||
|
||||
10
.travis.yml
10
.travis.yml
@@ -13,7 +13,7 @@ env:
|
||||
- TEST_SUITE=Coverage
|
||||
- TEST_SUITE=Integration
|
||||
php:
|
||||
- 7.2
|
||||
- 7.4
|
||||
sudo: false
|
||||
cache:
|
||||
directories:
|
||||
@@ -32,13 +32,5 @@ script:
|
||||
- if [ "$TEST_SUITE" = "Integration" ]; then vendor/bin/phpunit tests/Integration; fi;
|
||||
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
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
1
.yarnclean
Normal file
1
.yarnclean
Normal file
@@ -0,0 +1 @@
|
||||
@types/react-native
|
||||
57
BUILDING.md
Normal file
57
BUILDING.md
Normal file
@@ -0,0 +1,57 @@
|
||||
# Local Development
|
||||
Pterodactyl is now powered by Vuejs and Tailwindcss and uses webpack at its core to generate compiled assets. Release
|
||||
versions of Pterodactyl will include pre-compiled, minified, and hashed assets ready-to-go.
|
||||
|
||||
However, if you are interested in running custom themes or making modifications to the Vue files you'll need a build
|
||||
system in place to generate these compiled assets. To get your environment setup, you'll first need to install at least Nodejs
|
||||
`8`, and it is _highly_ recommended that you also install [Yarn](https://yarnpkg.com) to manage your `node_modules`.
|
||||
|
||||
### Install Dependencies
|
||||
```bash
|
||||
yarn install
|
||||
```
|
||||
|
||||
The command above will download all of the dependencies necessary to get Pterodactyl assets building. After that, its as
|
||||
simple as running the command below to generate assets while you're developing.
|
||||
|
||||
```bash
|
||||
# build the compiled assets for development
|
||||
yarn run build
|
||||
|
||||
# build the assets automatically when files are modified
|
||||
yarn run watch
|
||||
```
|
||||
|
||||
|
||||
### Hot Module Reloading
|
||||
For more advanced users, we also support 'Hot Module Reloading', allowing you to quickly see changes you're making
|
||||
to the Vue template files without having to reload the page you're on. To Get started with this, you just need
|
||||
to run the command below.
|
||||
|
||||
```bash
|
||||
PUBLIC_PATH=http://192.168.1.1:8080 yarn run serve --host 192.168.1.1
|
||||
```
|
||||
|
||||
There are two _very important_ parts of this command to take note of and change for your specific environment. The first
|
||||
is the `--host` flag, which is required and should point to the machine where the `webpack-serve` server will be running.
|
||||
The second is the `PUBLIC_PATH` environment variable which is the URL pointing to the HMR server and is appended to all of
|
||||
the asset URLs used in Pterodactyl.
|
||||
|
||||
#### Vagrant
|
||||
If you want to use HMR with our Vagrant image, you can use `yarn run v:serve` as a shortcut for the correct parameters.
|
||||
In order to have proper file change detection you can use the [`vagrant-notify-forwarder`](https://github.com/mhallin/vagrant-notify-forwarder) to notify file events from the host to the VM.
|
||||
```sh
|
||||
vagrant plugin install vagrant-notify-forwarder
|
||||
vagrant reload
|
||||
```
|
||||
|
||||
### Building for Production
|
||||
Once you have your files squared away and ready for the live server, you'll be needing to generate compiled, minified, and
|
||||
hashed assets to push live. To do so, run the command below:
|
||||
|
||||
```bash
|
||||
yarn run build:production
|
||||
```
|
||||
|
||||
This will generate a production ready `bundle.js` and `bundle.css` as well as a `manifest.json` and store them in
|
||||
the `/public/assets` directory where they can then be access by clients, and read by the Panel.
|
||||
43
CHANGELOG.md
43
CHANGELOG.md
@@ -3,6 +3,49 @@ This file is a running track of new features and fixes to each version of the pa
|
||||
|
||||
This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||
|
||||
## v1.0.0
|
||||
Pterodactyl 1.0 represents the culmination of over two years of work, almost 2,000 commits, endless bug and feature requests, and a dream that
|
||||
has been in the making since 2013. 🎉
|
||||
|
||||
Due to the sheer size and timeline of this release I've massively truncated the listing below. There are numerous smaller
|
||||
bug fixes and changes that would simply be too difficult to keep track of here. Please feel free to browse through the releases
|
||||
tab for this repository to see more specific changes that have been made.
|
||||
|
||||
### Added
|
||||
* Adds a new client-facing API allowing a user to control all aspects of their individual servers, or servers
|
||||
which they have been granted access to as a subuser.
|
||||
* Adds the ability for backups to be created for a server both manually and via a scheduled task.
|
||||
* Adds the ability for users to modify their server allocations on the fly and include notes for each allocation.
|
||||
* Adds the ability for users to generate recovery tokens for 2FA protected logins which can be used in place of
|
||||
a code should their device be inaccessible.
|
||||
* Adds support for transfering servers between Nodes via the Panel.
|
||||
* Adds the ability to assign specific CPU cores to a server (CPU Pinning) process.
|
||||
* Server owners can now reinstall their assigned server egg automatically with a button on the frontend.
|
||||
|
||||
### Changed
|
||||
* The entire user frontend has been replaced with a responsive, React backed design implemented using Tailwind CSS.
|
||||
* Replaces a large amount of complex daemon authentication logic by funneling most API calls through the Panel, and using
|
||||
JSON Web Tokens where necessary to handle one-time direct authentication with Wings.
|
||||
* Frontend server listing now includes a toggle to show or hide servers which an administrator has access to, rather
|
||||
than always showing all servers on the system when logged into an admin account.
|
||||
* We've replaced Ace Editor on the frontend with a better solution to allow lighter builds and more end-user functionality.
|
||||
* Server permissions have been overhauled to be both easier to understand in the codebase, and allows plugins to better
|
||||
hook into the permission system.
|
||||
|
||||
### Removed
|
||||
* Removes large swaths of code complexity and confusing interface designs that caused a lot of pain to new developers
|
||||
trying to jump into the codebase. We've simplified this to stick to more established Laravel design standards to make
|
||||
it easy to parse through the project and make contributions.
|
||||
|
||||
## v0.7.19 (Derelict Dermodactylus)
|
||||
### Fixed
|
||||
* **[Security]** Fixes XSS in the admin area's server owner selection.
|
||||
|
||||
## v0.7.18 (Derelict Dermodactylus)
|
||||
### Fixed
|
||||
* **[Security]** Re-addressed missed endpoint that would not properly limit a user account to 5 API keys.
|
||||
* **[Security]** Addresses a Client API vulnerability that would allow a user to list all servers on the system ([`GHSA-6888-7f3w-92jx`](https://github.com/pterodactyl/panel/security/advisories/GHSA-6888-7f3w-92jx))
|
||||
|
||||
## v0.7.17 (Derelict Dermodactylus)
|
||||
### Fixed
|
||||
* Limited accounts to 5 API keys at a time.
|
||||
|
||||
26
Dockerfile
26
Dockerfile
@@ -1,9 +1,18 @@
|
||||
FROM alpine:3.8
|
||||
FROM php:7.4-fpm-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
RUN apk add --no-cache --update ca-certificates certbot nginx dcron curl tini php7 php7-bcmath php7-common php7-dom php7-fpm php7-gd php7-mbstring php7-openssl php7-zip php7-pdo php7-phar php7-json php7-pdo_mysql php7-session php7-ctype php7-tokenizer php7-zlib php7-simplexml php7-fileinfo supervisor \
|
||||
&& curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
RUN apk add --no-cache --update ca-certificates dcron curl git supervisor tar unzip nginx libpng-dev libxml2-dev libzip-dev certbot yarn; \
|
||||
docker-php-ext-install bcmath; \
|
||||
docker-php-ext-install gd; \
|
||||
docker-php-ext-install mbstring; \
|
||||
docker-php-ext-install pdo; \
|
||||
docker-php-ext-install pdo_mysql; \
|
||||
docker-php-ext-install tokenizer; \
|
||||
docker-php-ext-install xml; \
|
||||
docker-php-ext-configure zip --with-libzip=/usr/include; \
|
||||
docker-php-ext-install zip; \
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
||||
|
||||
COPY . ./
|
||||
|
||||
@@ -12,15 +21,16 @@ RUN cp .env.example .env \
|
||||
&& rm .env \
|
||||
&& chown -R nginx:nginx . && chmod -R 777 storage/* bootstrap/cache
|
||||
|
||||
RUN cp .dev/docker/default.conf /etc/nginx/conf.d/default.conf \
|
||||
&& cp .dev/docker/www.conf /etc/php7/php-fpm.d/www.conf \
|
||||
&& cat .dev/docker/supervisord.conf > /etc/supervisord.conf \
|
||||
&& echo "* * * * * /usr/bin/php /app/artisan schedule:run >> /dev/null 2>&1" >> /var/spool/cron/crontabs/root \
|
||||
RUN cp docker/default.conf /etc/nginx/conf.d/default.conf \
|
||||
&& cat docker/www.conf > /usr/local/etc/php-fpm.d/www.conf \
|
||||
&& rm /usr/local/etc/php-fpm.d/www.conf.default \
|
||||
&& cat docker/supervisord.conf > /etc/supervisord.conf \
|
||||
&& echo "* * * * * /usr/local/bin/php /app/artisan schedule:run >> /dev/null 2>&1" >> /var/spool/cron/crontabs/root \
|
||||
&& sed -i s/ssl_session_cache/#ssl_session_cache/g /etc/nginx/nginx.conf \
|
||||
&& mkdir -p /var/run/php /var/run/nginx
|
||||
|
||||
EXPOSE 80 443
|
||||
|
||||
ENTRYPOINT ["/bin/ash", ".dev/docker/entrypoint.sh"]
|
||||
ENTRYPOINT ["/bin/ash", "docker/entrypoint.sh"]
|
||||
|
||||
CMD [ "supervisord", "-n", "-c", "/etc/supervisord.conf" ]
|
||||
66
README.md
66
README.md
@@ -1,26 +1,47 @@
|
||||
[](https://pterodactyl.io)
|
||||
|
||||
[](https://travis-ci.org/pterodactyl/panel)
|
||||
[](https://styleci.io/repos/47508644)
|
||||
[](https://codecov.io/gh/Pterodactyl/Panel)
|
||||
[](https://pterodactyl.io/discord)
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
# Pterodactyl Panel
|
||||
Pterodactyl is an open-source game server management panel built with PHP 7, React, and Go. Designed with security
|
||||
in mind, Pterodactyl runs all game servers in isolated Docker container while exposing a beautiful and intuitive
|
||||
UI to end users.
|
||||
|
||||
Pterodactyl is the open-source game server management panel built with PHP7, Nodejs, and Go. Designed with security in mind, Pterodactyl runs all game servers in isolated Docker containers while exposing a beautiful and intuitive UI to administrators and users.
|
||||
What more are you waiting for? Make game servers a first class citizen on your platform today.
|
||||
Stop settling for less. Make game servers a first class citizen on your platform.
|
||||
|
||||

|
||||

|
||||
|
||||
## Support & Documentation
|
||||
Support for using Pterodactyl can be found on our [Documentation Website](https://pterodactyl.io/project/introduction.html), [Guides Website](https://guides.pterodactyl.io), or via our [Discord Chat](https://discord.gg/QRDZvVm).
|
||||
## Sponsors
|
||||
I would like to extend my sincere thanks to the following sponsors for helping find Pterodactyl's developement.
|
||||
[Interested in becoming a sponsor?](https://github.com/sponsors/DaneEveritt)
|
||||
|
||||
| Company | About |
|
||||
| ------- | ----- |
|
||||
| [**Bloom.host**](https://bloom.host) | Bloom.host offers dedicated core VPS and Minecraft hosting with Ryzen 9 processors. With owned-hardware, we offer truly unbeatable prices on high-performance hosting. |
|
||||
| [**VersatileNode**](https://versatilenode.com/) | Looking to host a minecraft server, vps, or a website? VersatileNode is one of the most affordable hosting providers to provide quality yet cheap services with incredible support. |
|
||||
| [**MineStrator**](https://minestrator.com/) | Looking for a French highend hosting company for you minecraft server? More than 14,000 members on our discord, trust us. |
|
||||
| [**DedicatedMC**](https://dedicatedmc.io/) | DedicatedMC provides Raw Power hosting at affordable pricing, making sure to never compromise on your performance and giving you the best performance money can buy. |
|
||||
| [**Skynode**](https://www.skynode.pro/) | Skynode provides blazing fast game servers along with a top-notch user experience. Whatever our clients are looking for, we're able to provide it! |
|
||||
| [**XCORE-SERVER.de**](https://xcore-server.de/) | XCORE-SERVER.de offers High-End Servers for hosting and gaming since 2012. Fast, excellent and well-known for eSports Gaming. |
|
||||
| [**RoyaleHosting**](https://royalehosting.net/) | Build your dreams and deploy them with RoyaleHosting’s reliable servers and network. Easy to use, provisioned in a couple of minutes. |
|
||||
|
||||
## Documentation
|
||||
* [Panel Documentation](https://pterodactyl.io/panel/1.0/getting_started.html)
|
||||
* [Wings Documentation](https://pterodactyl.io/wings/1.0/installing.html)
|
||||
* [Community Guides](https://pterodactyl.io/community/about.html)
|
||||
* Or, get additional help [via Discord](https://discord.gg/pterodactyl)
|
||||
|
||||
### Supported Games
|
||||
We support a huge variety of games by utilizing Docker containers to isolate each instance, giving you the power to host your games across the world without having to bloat each physical machine with additional dependencies.
|
||||
We support a huge variety of games by utilizing Docker containers to isolate each instance, giving you the power to
|
||||
host your games across the world without having to bloat each physical machine with additional dependencies.
|
||||
|
||||
Some of our core supported games include:
|
||||
|
||||
* Minecraft — including Spigot, Sponge, Bungeecord, Waterfall, and more
|
||||
* Minecraft — including Paper, Sponge, Bungeecord, Waterfall, and more
|
||||
* Rust
|
||||
* Terraria
|
||||
* Teamspeak
|
||||
@@ -30,7 +51,8 @@ Some of our core supported games include:
|
||||
* Garry's Mod
|
||||
* ARK: Survival Evolved
|
||||
|
||||
In addition to our standard nest of supported games, our community is constantly pushing the limits of this software and there are plenty more games available provided by the community. Some of these games include:
|
||||
In addition to our standard nest of supported games, our community is constantly pushing the limits of this software
|
||||
and there are plenty more games available provided by the community. Some of these games include:
|
||||
|
||||
* Factorio
|
||||
* San Andreas: MP
|
||||
@@ -38,22 +60,13 @@ In addition to our standard nest of supported games, our community is constantly
|
||||
* Squad
|
||||
* FiveM
|
||||
* Xonotic
|
||||
* Discord ATLBot
|
||||
|
||||
## Credits
|
||||
This software would not be possible without the work of other open-source authors who provide tools such as:
|
||||
|
||||
[Ace Editor](https://ace.c9.io), [AdminLTE](https://almsaeedstudio.com), [Animate.css](http://daneden.github.io/animate.css/), [AnsiUp](https://github.com/drudru/ansi_up), [Async.js](https://github.com/caolan/async),
|
||||
[Bootstrap](http://getbootstrap.com), [Bootstrap Notify](http://bootstrap-notify.remabledesigns.com), [Chart.js](http://www.chartjs.org), [FontAwesome](http://fontawesome.io),
|
||||
[FontAwesome Animations](https://github.com/l-lin/font-awesome-animation), [jQuery](http://jquery.com), [Laravel](https://laravel.com), [Lodash](https://lodash.com),
|
||||
[Select2](https://select2.github.io), [Socket.io](http://socket.io), [Socket.io File Upload](https://github.com/vote539/socketio-file-upload), [SweetAlert](http://t4t5.github.io/sweetalert),
|
||||
[Typeahead](https://github.com/bassjobsen/Bootstrap-3-Typeahead), and [Particles.js](http://vincentgarreau.com/particles.js).
|
||||
|
||||
Some Javascript and CSS used within the panel is licensed under a `MIT` or `Apache 2.0` license. Please check their respective header files for more information.
|
||||
* Starmade
|
||||
* Discord ATLBot, and most other Node.js/Python discord bots
|
||||
* [and many more...](https://github.com/parkervcp/eggs)
|
||||
|
||||
## License
|
||||
```
|
||||
Copyright (c) 2015 - 2018 Dane Everitt <dane@daneeveritt.com>.
|
||||
Copyright (c) 2015 - 2020 Dane Everitt <dane@daneeveritt.com> & Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -73,3 +86,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
Some Javascript and CSS used within the panel are licensed under a `MIT` or `Apache 2.0` license. Please check their
|
||||
respective header files for more information.
|
||||
|
||||
19
SECURITY.md
Normal file
19
SECURITY.md
Normal file
@@ -0,0 +1,19 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
The following versions of Pterodactyl are receiving active support and maintenance. Any security vulnerabilities discovered must be reproducible in supported versions.
|
||||
|
||||
| Panel | Daemon | Supported |
|
||||
| ----- | ------------ | ------------------ |
|
||||
| 1.0.x | wings@1.0.x | :white_check_mark: |
|
||||
| 0.7.x | daemon@0.6.x | :white_check_mark: |
|
||||
| 0.6.x | daemon@0.5.x | :x: |
|
||||
| 0.5.x | daemon@0.4.x | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please reach out directly to any project team member on Discord when reporting a security vulnerability, or you can send an email to `dane [ät] pterodactyl.io`.
|
||||
|
||||
We make every effort to respond as soon as possible, although it may take a day or two for us to sync internally and determine the severity of the report and its impact. Please, _do not_ use a public facing channel or GitHub issues to report sensitive security issues.
|
||||
|
||||
As part of our process, we will create a security advisory for the affected versions and disclose it publicly, usually two to four weeks after a releasing a version that addresses it.
|
||||
@@ -68,7 +68,7 @@ class AppSettingsCommand extends Command
|
||||
{--redis-host= : Redis host to use for connections.}
|
||||
{--redis-pass= : Password used to connect to redis.}
|
||||
{--redis-port= : Port to connect to redis over.}
|
||||
{--disable-settings-ui}';
|
||||
{--settings-ui= : Enable or disable the settings UI.}';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
@@ -138,8 +138,8 @@ class AppSettingsCommand extends Command
|
||||
array_key_exists($selected, self::ALLOWED_QUEUE_DRIVERS) ? $selected : null
|
||||
);
|
||||
|
||||
if ($this->option('disable-settings-ui')) {
|
||||
$this->variables['APP_ENVIRONMENT_ONLY'] = 'true';
|
||||
if (! is_null($this->option('settings-ui'))) {
|
||||
$this->variables['APP_ENVIRONMENT_ONLY'] = $this->option('settings-ui') == 'true' ? 'false' : 'true';
|
||||
} else {
|
||||
$this->variables['APP_ENVIRONMENT_ONLY'] = $this->confirm(trans('command/messages.environment.app.settings'), true) ? 'false' : 'true';
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ class EmailSettingsCommand extends Command
|
||||
|
||||
/**
|
||||
* Handle command execution.
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\PterodactylException
|
||||
*/
|
||||
public function handle()
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Console\Commands\Maintenance;
|
||||
|
||||
use Carbon\CarbonImmutable;
|
||||
use InvalidArgumentException;
|
||||
use Illuminate\Console\Command;
|
||||
use Pterodactyl\Repositories\Eloquent\BackupRepository;
|
||||
|
||||
class PruneOrphanedBackupsCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'p:maintenance:prune-backups {--since-minutes=30}';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Marks all backups that have not completed in the last "n" minutes as being failed.';
|
||||
|
||||
/**
|
||||
* @param \Pterodactyl\Repositories\Eloquent\BackupRepository $repository
|
||||
*/
|
||||
public function handle(BackupRepository $repository)
|
||||
{
|
||||
$since = $this->option('since-minutes');
|
||||
if (! is_digit($since)) {
|
||||
throw new InvalidArgumentException('The --since-minutes option must be a valid numeric digit.');
|
||||
}
|
||||
|
||||
$query = $repository->getBuilder()
|
||||
->whereNull('completed_at')
|
||||
->whereDate('created_at', '<=', CarbonImmutable::now()->subMinutes($since));
|
||||
|
||||
$count = $query->count();
|
||||
if (! $count) {
|
||||
$this->info('There are no orphaned backups to be marked as failed.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->warn("Marking {$count} backups that have not been marked as completed in the last {$since} minutes as failed.");
|
||||
|
||||
$query->update([
|
||||
'is_successful' => false,
|
||||
'completed_at' => CarbonImmutable::now(),
|
||||
'updated_at' => CarbonImmutable::now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ class CleanOrphanedApiKeysCommand extends Command
|
||||
/**
|
||||
* Delete all orphaned API keys from the database when upgrading from 0.6 to 0.7.
|
||||
*
|
||||
* @return null|void
|
||||
* @return void|null
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
@@ -6,13 +6,13 @@ use Illuminate\Console\Command;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Validation\Factory as ValidatorFactory;
|
||||
use Pterodactyl\Repositories\Wings\DaemonPowerRepository;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\Daemon\PowerRepositoryInterface;
|
||||
|
||||
class BulkPowerActionCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\Daemon\PowerRepositoryInterface
|
||||
* @var \Pterodactyl\Repositories\Wings\DaemonPowerRepository
|
||||
*/
|
||||
private $powerRepository;
|
||||
|
||||
@@ -42,27 +42,26 @@ class BulkPowerActionCommand extends Command
|
||||
/**
|
||||
* BulkPowerActionCommand constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Contracts\Repository\Daemon\PowerRepositoryInterface $powerRepository
|
||||
* @param \Pterodactyl\Repositories\Wings\DaemonPowerRepository $powerRepository
|
||||
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
|
||||
* @param \Illuminate\Validation\Factory $validator
|
||||
*/
|
||||
public function __construct(
|
||||
PowerRepositoryInterface $powerRepository,
|
||||
DaemonPowerRepository $powerRepository,
|
||||
ServerRepositoryInterface $repository,
|
||||
ValidatorFactory $validator
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->powerRepository = $powerRepository;
|
||||
$this->repository = $repository;
|
||||
$this->validator = $validator;
|
||||
$this->powerRepository = $powerRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the bulk power request.
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\Daemon\InvalidPowerSignalException
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
@@ -91,21 +90,21 @@ class BulkPowerActionCommand extends Command
|
||||
}
|
||||
|
||||
$count = $this->repository->getServersForPowerActionCount($servers, $nodes);
|
||||
if (! $this->confirm(trans('command/messages.server.power.confirm', ['action' => $action, 'count' => $count]))) {
|
||||
if (! $this->confirm(trans('command/messages.server.power.confirm', ['action' => $action, 'count' => $count])) && $this->input->isInteractive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bar = $this->output->createProgressBar($count);
|
||||
$servers = $this->repository->getServersForPowerAction($servers, $nodes);
|
||||
|
||||
foreach ($servers as $server) {
|
||||
$servers->each(function ($server) use ($action, &$bar) {
|
||||
$bar->clear();
|
||||
|
||||
try {
|
||||
$this->powerRepository
|
||||
->setNode($server->node)
|
||||
->setServer($server)
|
||||
->sendSignal($action);
|
||||
->send($action);
|
||||
} catch (RequestException $exception) {
|
||||
$this->output->error(trans('command/messages.server.power.action_failed', [
|
||||
'name' => $server->name,
|
||||
@@ -117,7 +116,7 @@ class BulkPowerActionCommand extends Command
|
||||
|
||||
$bar->advance();
|
||||
$bar->display();
|
||||
}
|
||||
});
|
||||
|
||||
$this->line('');
|
||||
}
|
||||
|
||||
@@ -12,50 +12,50 @@ namespace Pterodactyl\Console\Commands\Server;
|
||||
use Webmozart\Assert\Assert;
|
||||
use Illuminate\Console\Command;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
|
||||
use Pterodactyl\Services\Servers\ServerConfigurationStructureService;
|
||||
use Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface as DaemonServerRepositoryInterface;
|
||||
|
||||
class RebuildServerCommand extends Command
|
||||
class BulkReinstallActionCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\ServerConfigurationStructureService
|
||||
*/
|
||||
protected $configurationStructureService;
|
||||
private $configurationStructureService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface
|
||||
* @var \Pterodactyl\Repositories\Wings\DaemonServerRepository
|
||||
*/
|
||||
protected $daemonRepository;
|
||||
private $daemonRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\ServerRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Rebuild a single server, all servers on a node, or all servers on the panel.';
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
protected $description = 'Reinstall a single server, all servers on a node, or all servers on the panel.';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'p:server:rebuild
|
||||
{server? : The ID of the server to rebuild.}
|
||||
{--node= : ID of the node to rebuild all servers on. Ignored if server is passed.}';
|
||||
protected $signature = 'p:server:reinstall
|
||||
{server? : The ID of the server to reinstall.}
|
||||
{--node= : ID of the node to reinstall all servers on. Ignored if server is passed.}';
|
||||
|
||||
/**
|
||||
* RebuildServerCommand constructor.
|
||||
* BulkReinstallActionCommand constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface $daemonRepository
|
||||
* @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonRepository
|
||||
* @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $configurationStructureService
|
||||
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository
|
||||
*/
|
||||
public function __construct(
|
||||
DaemonServerRepositoryInterface $daemonRepository,
|
||||
DaemonServerRepository $daemonRepository,
|
||||
ServerConfigurationStructureService $configurationStructureService,
|
||||
ServerRepositoryInterface $repository
|
||||
ServerRepository $repository
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
@@ -70,16 +70,20 @@ class RebuildServerCommand extends Command
|
||||
public function handle()
|
||||
{
|
||||
$servers = $this->getServersToProcess();
|
||||
|
||||
if (! $this->confirm(trans('command/messages.server.reinstall.confirm')) && $this->input->isInteractive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$bar = $this->output->createProgressBar(count($servers));
|
||||
|
||||
$servers->each(function ($server) use ($bar) {
|
||||
$bar->clear();
|
||||
$json = array_merge($this->configurationStructureService->handle($server), ['rebuild' => true]);
|
||||
|
||||
try {
|
||||
$this->daemonRepository->setServer($server)->update($json);
|
||||
$this->daemonRepository->setServer($server)->reinstall();
|
||||
} catch (RequestException $exception) {
|
||||
$this->output->error(trans('command/messages.server.rebuild_failed', [
|
||||
$this->output->error(trans('command/messages.server.reinstall.failed', [
|
||||
'name' => $server->name,
|
||||
'id' => $server->id,
|
||||
'node' => $server->node->name,
|
||||
@@ -95,15 +99,15 @@ class RebuildServerCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the servers to be rebuilt.
|
||||
* Return the servers to be reinstalled.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
private function getServersToProcess()
|
||||
{
|
||||
Assert::nullOrIntegerish($this->argument('server'), 'Value passed in server argument must be null or an integer, received %s.');
|
||||
Assert::nullOrIntegerish($this->option('node'), 'Value passed in node option must be null or integer, received %s.');
|
||||
|
||||
return $this->repository->getDataForRebuild($this->argument('server'), $this->option('node'));
|
||||
return $this->repository->getDataForReinstall($this->argument('server'), $this->option('node'));
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
namespace Pterodactyl\Console\Commands\User;
|
||||
|
||||
use Webmozart\Assert\Assert;
|
||||
use Pterodactyl\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Pterodactyl\Services\Users\UserDeletionService;
|
||||
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
|
||||
@@ -40,16 +41,11 @@ class DeleteUserCommand extends Command
|
||||
* DeleteUserCommand constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Services\Users\UserDeletionService $deletionService
|
||||
* @param \Pterodactyl\Contracts\Repository\UserRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(
|
||||
UserDeletionService $deletionService,
|
||||
UserRepositoryInterface $repository
|
||||
) {
|
||||
public function __construct(UserDeletionService $deletionService) {
|
||||
parent::__construct();
|
||||
|
||||
$this->deletionService = $deletionService;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,9 +55,13 @@ class DeleteUserCommand extends Command
|
||||
public function handle()
|
||||
{
|
||||
$search = $this->option('user') ?? $this->ask(trans('command/messages.user.search_users'));
|
||||
Assert::notEmpty($search, 'Search term must be a non-null value, received %s.');
|
||||
Assert::notEmpty($search, 'Search term should be an email address, got: %s.');
|
||||
|
||||
$results = User::query()
|
||||
->where('email', 'LIKE', "$search%")
|
||||
->where('username', 'LIKE', "$search%")
|
||||
->get();
|
||||
|
||||
$results = $this->repository->setSearchTerm($search)->all();
|
||||
if (count($results) < 1) {
|
||||
$this->error(trans('command/messages.user.no_users_found'));
|
||||
if ($this->input->isInteractive()) {
|
||||
@@ -95,5 +95,7 @@ class DeleteUserCommand extends Command
|
||||
$this->deletionService->handle($deleteUser);
|
||||
$this->info(trans('command/messages.user.deleted'));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,16 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
// Execute scheduled commands for servers every minute, as if there was a normal cron running.
|
||||
$schedule->command('p:schedule:process')->everyMinute()->withoutOverlapping();
|
||||
|
||||
// Every 30 minutes, run the backup pruning command so that any abandoned backups can be removed
|
||||
// from the UI view for the server.
|
||||
$schedule->command('p:maintenance:prune-backups', [
|
||||
'--since-minutes' => '30',
|
||||
])->everyThirtyMinutes();
|
||||
|
||||
// Every day cleanup any internal backups of service files.
|
||||
$schedule->command('p:maintenance:clean-service-backups')->daily();
|
||||
}
|
||||
}
|
||||
|
||||
15
app/Contracts/Http/ClientPermissionsRequest.php
Normal file
15
app/Contracts/Http/ClientPermissionsRequest.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Http;
|
||||
|
||||
interface ClientPermissionsRequest
|
||||
{
|
||||
/**
|
||||
* Returns the permissions string indicating which permission should be used to
|
||||
* validate that the authenticated user has permission to perform this action aganist
|
||||
* the given resource (server).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function permission(): string;
|
||||
}
|
||||
@@ -3,44 +3,9 @@
|
||||
namespace Pterodactyl\Contracts\Repository;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
|
||||
interface AllocationRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Set an array of allocation IDs to be assigned to a specific server.
|
||||
*
|
||||
* @param int|null $server
|
||||
* @param array $ids
|
||||
* @return int
|
||||
*/
|
||||
public function assignAllocationsToServer(int $server = null, array $ids): int;
|
||||
|
||||
/**
|
||||
* Return all of the allocations for a specific node.
|
||||
*
|
||||
* @param int $node
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getAllocationsForNode(int $node): Collection;
|
||||
|
||||
/**
|
||||
* Return all of the allocations for a node in a paginated format.
|
||||
*
|
||||
* @param int $node
|
||||
* @param int $perPage
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
public function getPaginatedAllocationsForNode(int $node, int $perPage = 100): LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* Return all of the unique IPs that exist for a given node.
|
||||
*
|
||||
* @param int $node
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getUniqueAllocationIpsForNode(int $node): Collection;
|
||||
|
||||
/**
|
||||
* Return all of the allocations that exist for a node that are not currently
|
||||
* allocated.
|
||||
@@ -50,27 +15,6 @@ interface AllocationRepositoryInterface extends RepositoryInterface
|
||||
*/
|
||||
public function getUnassignedAllocationIds(int $node): array;
|
||||
|
||||
/**
|
||||
* Get an array of all allocations that are currently assigned to a given server.
|
||||
*
|
||||
* @param int $server
|
||||
* @return array
|
||||
*/
|
||||
public function getAssignedAllocationIds(int $server): array;
|
||||
|
||||
/**
|
||||
* Return a concatenated result set of node ips that already have at least one
|
||||
* server assigned to that IP. This allows for filtering out sets for
|
||||
* dedicated allocation IPs.
|
||||
*
|
||||
* If an array of nodes is passed the results will be limited to allocations
|
||||
* in those nodes.
|
||||
*
|
||||
* @param array $nodes
|
||||
* @return array
|
||||
*/
|
||||
public function getDiscardableDedicatedAllocations(array $nodes = []): array;
|
||||
|
||||
/**
|
||||
* Return a single allocation from those meeting the requirements.
|
||||
*
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository\Attributes;
|
||||
|
||||
interface SearchableInterface
|
||||
{
|
||||
/**
|
||||
* Set the search term.
|
||||
*
|
||||
* @param string|null $term
|
||||
* @return $this
|
||||
* @deprecated
|
||||
*/
|
||||
public function search($term);
|
||||
|
||||
/**
|
||||
* Set the search term to use when requesting all records from
|
||||
* the model.
|
||||
*
|
||||
* @param string|null $term
|
||||
* @return $this
|
||||
*/
|
||||
public function setSearchTerm(string $term = null);
|
||||
|
||||
/**
|
||||
* Determine if a valid search term is set on this repository.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasSearchTerm(): bool;
|
||||
|
||||
/**
|
||||
* Return the search term.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getSearchTerm();
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository\Daemon;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Pterodactyl\Models\Server;
|
||||
|
||||
interface BaseRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Set the node model to be used for this daemon connection.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return $this
|
||||
*/
|
||||
public function setNode(Node $node);
|
||||
|
||||
/**
|
||||
* Return the node model being used.
|
||||
*
|
||||
* @return \Pterodactyl\Models\Node|null
|
||||
*/
|
||||
public function getNode();
|
||||
|
||||
/**
|
||||
* Set the Server model to use when requesting information from the Daemon.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return $this
|
||||
*/
|
||||
public function setServer(Server $server);
|
||||
|
||||
/**
|
||||
* Return the Server model.
|
||||
*
|
||||
* @return \Pterodactyl\Models\Server|null
|
||||
*/
|
||||
public function getServer();
|
||||
|
||||
/**
|
||||
* Set the token to be used in the X-Access-Token header for requests to the daemon.
|
||||
*
|
||||
* @param string $token
|
||||
* @return $this
|
||||
*/
|
||||
public function setToken(string $token);
|
||||
|
||||
/**
|
||||
* Return the access token being used for requests.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getToken();
|
||||
|
||||
/**
|
||||
* Return an instance of the Guzzle HTTP Client to be used for requests.
|
||||
*
|
||||
* @param array $headers
|
||||
* @return \GuzzleHttp\Client
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function getHttpClient(array $headers = []): Client;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository\Daemon;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
interface CommandRepositoryInterface extends BaseRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Send a command to a server.
|
||||
*
|
||||
* @param string $command
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function send(string $command): ResponseInterface;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository\Daemon;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
interface ConfigurationRepositoryInterface extends BaseRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Update the configuration details for the specified node using data from the database.
|
||||
*
|
||||
* @param array $overrides
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function update(array $overrides = []): ResponseInterface;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository\Daemon;
|
||||
|
||||
use stdClass;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
interface FileRepositoryInterface extends BaseRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Return stat information for a given file.
|
||||
*
|
||||
* @param string $path
|
||||
* @return \stdClass
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
*/
|
||||
public function getFileStat(string $path): stdClass;
|
||||
|
||||
/**
|
||||
* Return the contents of a given file if it can be edited in the Panel.
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
*/
|
||||
public function getContent(string $path): string;
|
||||
|
||||
/**
|
||||
* Save new contents to a given file.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $content
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
*/
|
||||
public function putContent(string $path, string $content): ResponseInterface;
|
||||
|
||||
/**
|
||||
* Return a directory listing for a given path.
|
||||
*
|
||||
* @param string $path
|
||||
* @return array
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
*/
|
||||
public function getDirectory(string $path): array;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository\Daemon;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
interface PowerRepositoryInterface extends BaseRepositoryInterface
|
||||
{
|
||||
const SIGNAL_START = 'start';
|
||||
const SIGNAL_STOP = 'stop';
|
||||
const SIGNAL_RESTART = 'restart';
|
||||
const SIGNAL_KILL = 'kill';
|
||||
|
||||
/**
|
||||
* Send a power signal to a server.
|
||||
*
|
||||
* @param string $signal
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\Daemon\InvalidPowerSignalException
|
||||
*/
|
||||
public function sendSignal(string $signal): ResponseInterface;
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository\Daemon;
|
||||
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
interface ServerRepositoryInterface extends BaseRepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Create a new server on the daemon for the panel.
|
||||
*
|
||||
* @param array $structure
|
||||
* @param array $overrides
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
*/
|
||||
public function create(array $structure, array $overrides = []): ResponseInterface;
|
||||
|
||||
/**
|
||||
* Update server details on the daemon.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function update(array $data): ResponseInterface;
|
||||
|
||||
/**
|
||||
* Mark a server to be reinstalled on the system.
|
||||
*
|
||||
* @param array|null $data
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function reinstall(array $data = null): ResponseInterface;
|
||||
|
||||
/**
|
||||
* Mark a server as needing a container rebuild the next time the server is booted.
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function rebuild(): ResponseInterface;
|
||||
|
||||
/**
|
||||
* Suspend a server on the daemon.
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function suspend(): ResponseInterface;
|
||||
|
||||
/**
|
||||
* Un-suspend a server on the daemon.
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function unsuspend(): ResponseInterface;
|
||||
|
||||
/**
|
||||
* Delete a server on the daemon.
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function delete(): ResponseInterface;
|
||||
|
||||
/**
|
||||
* Return details on a specific server.
|
||||
*
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*/
|
||||
public function details(): ResponseInterface;
|
||||
|
||||
/**
|
||||
* Revoke an access key on the daemon before the time is expired.
|
||||
*
|
||||
* @param string|array $key
|
||||
* @return \Psr\Http\Message\ResponseInterface
|
||||
*
|
||||
* @throws \GuzzleHttp\Exception\RequestException
|
||||
*/
|
||||
public function revokeAccessKey($key): ResponseInterface;
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository;
|
||||
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\DaemonKey;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
interface DaemonKeyRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* String prepended to keys to identify that they are managed internally and not part of the user API.
|
||||
*/
|
||||
const INTERNAL_KEY_IDENTIFIER = 'i_';
|
||||
|
||||
/**
|
||||
* Load the server and user relations onto a key model.
|
||||
*
|
||||
* @param \Pterodactyl\Models\DaemonKey $key
|
||||
* @param bool $refresh
|
||||
* @return \Pterodactyl\Models\DaemonKey
|
||||
*/
|
||||
public function loadServerAndUserRelations(DaemonKey $key, bool $refresh = false): DaemonKey;
|
||||
|
||||
/**
|
||||
* Return a daemon key with the associated server relation attached.
|
||||
*
|
||||
* @param string $key
|
||||
* @return \Pterodactyl\Models\DaemonKey
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function getKeyWithServer(string $key): DaemonKey;
|
||||
|
||||
/**
|
||||
* Get all of the keys for a specific user including the information needed
|
||||
* from their server relation for revocation on the daemon.
|
||||
*
|
||||
* @param \Pterodactyl\Models\User $user
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getKeysForRevocation(User $user): Collection;
|
||||
|
||||
/**
|
||||
* Delete an array of daemon keys from the database. Used primarily in
|
||||
* conjunction with getKeysForRevocation.
|
||||
*
|
||||
* @param array $ids
|
||||
* @return bool|int
|
||||
*/
|
||||
public function deleteKeys(array $ids);
|
||||
}
|
||||
@@ -42,18 +42,6 @@ interface DatabaseRepositoryInterface extends RepositoryInterface
|
||||
*/
|
||||
public function getDatabasesForHost(int $host, int $count = 25): LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* Create a new database if it does not already exist on the host with
|
||||
* the provided details.
|
||||
*
|
||||
* @param array $data
|
||||
* @return \Pterodactyl\Models\Database
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\DuplicateDatabaseNameException
|
||||
*/
|
||||
public function createIfNotExists(array $data): Database;
|
||||
|
||||
/**
|
||||
* Create a new database on a given connection.
|
||||
*
|
||||
@@ -68,9 +56,10 @@ interface DatabaseRepositoryInterface extends RepositoryInterface
|
||||
* @param string $username
|
||||
* @param string $remote
|
||||
* @param string $password
|
||||
* @param $max_connections
|
||||
* @return bool
|
||||
*/
|
||||
public function createUser(string $username, string $remote, string $password): bool;
|
||||
public function createUser(string $username, string $remote, string $password, string $max_connections): bool;
|
||||
|
||||
/**
|
||||
* Give a specific user access to a given database.
|
||||
|
||||
@@ -4,9 +4,8 @@ namespace Pterodactyl\Contracts\Repository;
|
||||
|
||||
use Pterodactyl\Models\Location;
|
||||
use Illuminate\Support\Collection;
|
||||
use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
|
||||
|
||||
interface LocationRepositoryInterface extends RepositoryInterface, SearchableInterface
|
||||
interface LocationRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Return locations with a count of nodes and servers attached to it.
|
||||
|
||||
@@ -14,7 +14,7 @@ use Pterodactyl\Models\Nest;
|
||||
interface NestRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Return a nest or all nests with their associated eggs, variables, and packs.
|
||||
* Return a nest or all nests with their associated eggs and variables.
|
||||
*
|
||||
* @param int $id
|
||||
* @return \Illuminate\Database\Eloquent\Collection|\Pterodactyl\Models\Nest
|
||||
@@ -24,7 +24,7 @@ interface NestRepositoryInterface extends RepositoryInterface
|
||||
public function getWithEggs(int $id = null);
|
||||
|
||||
/**
|
||||
* Return a nest or all nests and the count of eggs, packs, and servers for that nest.
|
||||
* Return a nest or all nests and the count of eggs and servers for that nest.
|
||||
*
|
||||
* @param int|null $id
|
||||
* @return \Pterodactyl\Models\Nest|\Illuminate\Database\Eloquent\Collection
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository;
|
||||
|
||||
use Generator;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\LazyCollection;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
|
||||
|
||||
interface NodeRepositoryInterface extends RepositoryInterface, SearchableInterface
|
||||
interface NodeRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
const THRESHOLD_PERCENTAGE_LOW = 75;
|
||||
const THRESHOLD_PERCENTAGE_MEDIUM = 90;
|
||||
@@ -29,13 +29,6 @@ interface NodeRepositoryInterface extends RepositoryInterface, SearchableInterfa
|
||||
*/
|
||||
public function getUsageStatsRaw(Node $node): array;
|
||||
|
||||
/**
|
||||
* Return all available nodes with a searchable interface.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
public function getNodeListingData(): LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* Return a single node with location and server information.
|
||||
*
|
||||
@@ -61,15 +54,4 @@ interface NodeRepositoryInterface extends RepositoryInterface, SearchableInterfa
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getNodesForServerCreation(): Collection;
|
||||
|
||||
/**
|
||||
* Return the IDs of all nodes that exist in the provided locations and have the space
|
||||
* available to support the additional disk and memory provided.
|
||||
*
|
||||
* @param array $locations
|
||||
* @param int $disk
|
||||
* @param int $memory
|
||||
* @return \Generator
|
||||
*/
|
||||
public function getNodesWithResourceUse(array $locations, int $disk, int $memory): Generator;
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository;
|
||||
|
||||
use Pterodactyl\Models\Pack;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
|
||||
|
||||
interface PackRepositoryInterface extends RepositoryInterface, SearchableInterface
|
||||
{
|
||||
/**
|
||||
* Return a pack with the associated server models attached to it.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Pack $pack
|
||||
* @param bool $refresh
|
||||
* @return \Pterodactyl\Models\Pack
|
||||
*/
|
||||
public function loadServerData(Pack $pack, bool $refresh = false): Pack;
|
||||
|
||||
/**
|
||||
* Return a paginated listing of packs with their associated egg and server count.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
public function paginateWithEggAndServerCount(): LengthAwarePaginator;
|
||||
}
|
||||
@@ -2,22 +2,12 @@
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository;
|
||||
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
|
||||
|
||||
interface ServerRepositoryInterface extends RepositoryInterface, SearchableInterface
|
||||
interface ServerRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Returns a listing of all servers that exist including relationships.
|
||||
*
|
||||
* @param int $paginate
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
public function getAllServers(int $paginate): LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* Load the egg relations onto the server model.
|
||||
*
|
||||
@@ -36,6 +26,15 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter
|
||||
*/
|
||||
public function getDataForRebuild(int $server = null, int $node = null): Collection;
|
||||
|
||||
/**
|
||||
* Return a collection of servers with their associated data for reinstall operations.
|
||||
*
|
||||
* @param int|null $server
|
||||
* @param int|null $node
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function getDataForReinstall(int $server = null, int $node = null): Collection;
|
||||
|
||||
/**
|
||||
* Return a server model and all variables associated with the server.
|
||||
*
|
||||
@@ -57,18 +56,6 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter
|
||||
*/
|
||||
public function getPrimaryAllocation(Server $server, bool $refresh = false): Server;
|
||||
|
||||
/**
|
||||
* Return all of the server variables possible and default to the variable
|
||||
* default if there is no value defined for the specific server requested.
|
||||
*
|
||||
* @param int $id
|
||||
* @param bool $returnAsObject
|
||||
* @return array|object
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function getVariablesWithValues(int $id, bool $returnAsObject = false);
|
||||
|
||||
/**
|
||||
* Return enough data to be used for the creation of a server via the daemon.
|
||||
*
|
||||
@@ -89,7 +76,7 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter
|
||||
|
||||
/**
|
||||
* Get data for use when updating a server on the Daemon. Returns an array of
|
||||
* the egg and pack UUID which are used for build and rebuild. Only loads relations
|
||||
* the egg which is used for build and rebuild. Only loads relations
|
||||
* if they are missing, or refresh is set to true.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
@@ -98,16 +85,6 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter
|
||||
*/
|
||||
public function getDaemonServiceData(Server $server, bool $refresh = false): array;
|
||||
|
||||
/**
|
||||
* Return a paginated list of servers that a user can access at a given level.
|
||||
*
|
||||
* @param \Pterodactyl\Models\User $user
|
||||
* @param int $level
|
||||
* @param bool|int $paginate
|
||||
* @return \Illuminate\Pagination\LengthAwarePaginator|\Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function filterUserAccessServers(User $user, int $level, $paginate = 25);
|
||||
|
||||
/**
|
||||
* Return a server by UUID.
|
||||
*
|
||||
@@ -124,7 +101,7 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter
|
||||
* @param int[] $servers
|
||||
* @param int[] $nodes
|
||||
* @param bool $returnCount
|
||||
* @return int|\Generator
|
||||
* @return int|\Illuminate\Support\LazyCollection
|
||||
*/
|
||||
public function getServersForPowerAction(array $servers = [], array $nodes = [], bool $returnCount = false);
|
||||
|
||||
@@ -162,4 +139,16 @@ interface ServerRepositoryInterface extends RepositoryInterface, SearchableInter
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
public function loadAllServersForNode(int $node, int $limit): LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* Returns every server that exists for a given node.
|
||||
*
|
||||
* This is different from {@see loadAllServersForNode} because
|
||||
* it does not paginate the response.
|
||||
*
|
||||
* @param int $node
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
|
||||
*/
|
||||
public function loadEveryServerForNode(int $node);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ interface SessionRepositoryInterface extends RepositoryInterface
|
||||
*
|
||||
* @param int $user
|
||||
* @param string $session
|
||||
* @return null|int
|
||||
* @return int|null
|
||||
*/
|
||||
public function deleteUserSession(int $user, string $session);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ interface TaskRepositoryInterface extends RepositoryInterface
|
||||
*
|
||||
* @param int $schedule
|
||||
* @param int $index
|
||||
* @return null|\Pterodactyl\Models\Task
|
||||
* @return \Pterodactyl\Models\Task|null
|
||||
*/
|
||||
public function getNextTask(int $schedule, int $index);
|
||||
}
|
||||
|
||||
@@ -2,24 +2,6 @@
|
||||
|
||||
namespace Pterodactyl\Contracts\Repository;
|
||||
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
|
||||
use Pterodactyl\Contracts\Repository\Attributes\SearchableInterface;
|
||||
|
||||
interface UserRepositoryInterface extends RepositoryInterface, SearchableInterface
|
||||
interface UserRepositoryInterface extends RepositoryInterface
|
||||
{
|
||||
/**
|
||||
* Return all users with counts of servers and subusers of servers.
|
||||
*
|
||||
* @return \Illuminate\Contracts\Pagination\LengthAwarePaginator
|
||||
*/
|
||||
public function getAllUsersWithCounts(): LengthAwarePaginator;
|
||||
|
||||
/**
|
||||
* Return all matching models for a user in a format that can be used for dropdowns.
|
||||
*
|
||||
* @param string|null $query
|
||||
* @return \Illuminate\Support\Collection
|
||||
*/
|
||||
public function filterUsersByQuery(?string $query): Collection;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
namespace Pterodactyl\Exceptions;
|
||||
|
||||
class AccountNotFoundException extends \Exception
|
||||
use Exception;
|
||||
|
||||
class AccountNotFoundException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
namespace Pterodactyl\Exceptions;
|
||||
|
||||
class AutoDeploymentException extends \Exception
|
||||
use Exception;
|
||||
|
||||
class AutoDeploymentException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
namespace Pterodactyl\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Throwable;
|
||||
use PDOException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Swift_TransportException;
|
||||
use Illuminate\Container\Container;
|
||||
use Illuminate\Database\Connection;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
@@ -49,6 +51,7 @@ class Handler extends ExceptionHandler
|
||||
*/
|
||||
protected $cleanStacks = [
|
||||
PDOException::class,
|
||||
Swift_TransportException::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -71,12 +74,12 @@ class Handler extends ExceptionHandler
|
||||
* services such as AWS Cloudwatch or other monitoring you can replace the
|
||||
* contents of this function with a call to the parent reporter.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param \Throwable $exception
|
||||
* @return mixed
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function report(Exception $exception)
|
||||
public function report(Throwable $exception)
|
||||
{
|
||||
if (! config('app.exceptions.report_all', false) && $this->shouldntReport($exception)) {
|
||||
return null;
|
||||
@@ -102,7 +105,7 @@ class Handler extends ExceptionHandler
|
||||
return $logger->error($exception);
|
||||
}
|
||||
|
||||
private function generateCleanedExceptionStack(Exception $exception)
|
||||
private function generateCleanedExceptionStack(Throwable $exception)
|
||||
{
|
||||
$cleanedStack = '';
|
||||
foreach ($exception->getTrace() as $index => $item) {
|
||||
@@ -132,12 +135,12 @@ class Handler extends ExceptionHandler
|
||||
* Render an exception into an HTTP response.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Exception $exception
|
||||
* @param \Throwable $exception
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function render($request, Exception $exception)
|
||||
public function render($request, Throwable $exception)
|
||||
{
|
||||
$connections = Container::getInstance()->make(Connection::class);
|
||||
|
||||
@@ -154,26 +157,6 @@ class Handler extends ExceptionHandler
|
||||
$connections->rollBack(0);
|
||||
}
|
||||
|
||||
// Because of some breaking change snuck into a Laravel update that didn't get caught
|
||||
// by any of the tests, exceptions implementing the HttpExceptionInterface get marked
|
||||
// as being HttpExceptions, but aren't actually implementing the HttpException abstract.
|
||||
//
|
||||
// This is incredibly annoying because we can't just temporarily override the handler to
|
||||
// allow these (at least without taking on a high maintenance cost). Laravel 5.8 fixes this,
|
||||
// so when we update (or have updated) this code can be removed.
|
||||
//
|
||||
// @see https://github.com/laravel/framework/pull/25975
|
||||
// @todo remove this code when upgrading to Laravel 5.8
|
||||
if ($exception instanceof HttpExceptionInterface && ! $exception instanceof HttpException) {
|
||||
$exception = new HttpException(
|
||||
$exception->getStatusCode(),
|
||||
$exception->getMessage(),
|
||||
$exception,
|
||||
$exception->getHeaders(),
|
||||
$exception->getCode()
|
||||
);
|
||||
}
|
||||
|
||||
return parent::render($request, $exception);
|
||||
}
|
||||
|
||||
@@ -196,16 +179,21 @@ class Handler extends ExceptionHandler
|
||||
return [str_replace('.', '_', $field) => $cleaned];
|
||||
})->toArray();
|
||||
|
||||
$errors = collect($exception->errors())->map(function ($errors, $field) use ($codes) {
|
||||
$errors = collect($exception->errors())->map(function ($errors, $field) use ($codes, $exception) {
|
||||
$response = [];
|
||||
foreach ($errors as $key => $error) {
|
||||
$response[] = [
|
||||
'code' => str_replace(self::PTERODACTYL_RULE_STRING, 'p_', array_get(
|
||||
$meta = [
|
||||
'source_field' => $field,
|
||||
'rule' => str_replace(self::PTERODACTYL_RULE_STRING, 'p_', array_get(
|
||||
$codes, str_replace('.', '_', $field) . '.' . $key
|
||||
)),
|
||||
'detail' => $error,
|
||||
'source' => ['field' => $field],
|
||||
];
|
||||
|
||||
$converted = self::convertToArray($exception)['errors'][0];
|
||||
$converted['detail'] = $error;
|
||||
$converted['meta'] = is_array($converted['meta'] ?? null) ? array_merge($converted['meta'], $meta) : $meta;
|
||||
|
||||
$response[] = $converted;
|
||||
}
|
||||
|
||||
return $response;
|
||||
@@ -219,18 +207,29 @@ class Handler extends ExceptionHandler
|
||||
/**
|
||||
* Return the exception as a JSONAPI representation for use on API requests.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param \Throwable $exception
|
||||
* @param array $override
|
||||
* @return array
|
||||
*/
|
||||
public static function convertToArray(Exception $exception, array $override = []): array
|
||||
public static function convertToArray(Throwable $exception, array $override = []): array
|
||||
{
|
||||
$error = [
|
||||
'code' => class_basename($exception),
|
||||
'status' => method_exists($exception, 'getStatusCode') ? strval($exception->getStatusCode()) : '500',
|
||||
'detail' => 'An error was encountered while processing this request.',
|
||||
'status' => method_exists($exception, 'getStatusCode')
|
||||
? strval($exception->getStatusCode())
|
||||
: ($exception instanceof ValidationException ? '422' : '500'),
|
||||
'detail' => $exception instanceof HttpExceptionInterface
|
||||
? $exception->getMessage()
|
||||
: 'An unexpected error was encountered while processing this request, please try again.',
|
||||
];
|
||||
|
||||
if ($exception instanceof ModelNotFoundException || $exception->getPrevious() instanceof ModelNotFoundException) {
|
||||
// Show a nicer error message compared to the standard "No query results for model"
|
||||
// response that is normally returned. If we are in debug mode this will get overwritten
|
||||
// with a more specific error message to help narrow down things.
|
||||
$error['detail'] = 'The requested resource could not be found on the server.';
|
||||
}
|
||||
|
||||
if (config('app.debug')) {
|
||||
$error = array_merge($error, [
|
||||
'detail' => $exception->getMessage(),
|
||||
@@ -268,7 +267,7 @@ class Handler extends ExceptionHandler
|
||||
protected function unauthenticated($request, AuthenticationException $exception)
|
||||
{
|
||||
if ($request->expectsJson()) {
|
||||
return response()->json(['error' => 'Unauthenticated.'], 401);
|
||||
return response()->json(self::convertToArray($exception), 401);
|
||||
}
|
||||
|
||||
return redirect()->guest(route('auth.login'));
|
||||
@@ -278,10 +277,10 @@ class Handler extends ExceptionHandler
|
||||
* Converts an exception into an array to render in the response. Overrides
|
||||
* Laravel's built-in converter to output as a JSONAPI spec compliant object.
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param \Throwable $exception
|
||||
* @return array
|
||||
*/
|
||||
protected function convertExceptionToArray(Exception $exception)
|
||||
protected function convertExceptionToArray(Throwable $exception)
|
||||
{
|
||||
return self::convertToArray($exception);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
|
||||
namespace Pterodactyl\Exceptions\Http\Connection;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Http\Response;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
/**
|
||||
* @method \GuzzleHttp\Exception\GuzzleException getPrevious()
|
||||
*/
|
||||
class DaemonConnectionException extends DisplayException
|
||||
{
|
||||
/**
|
||||
@@ -19,18 +23,34 @@ class DaemonConnectionException extends DisplayException
|
||||
* @param \GuzzleHttp\Exception\GuzzleException $previous
|
||||
* @param bool $useStatusCode
|
||||
*/
|
||||
public function __construct(GuzzleException $previous, bool $useStatusCode = false)
|
||||
public function __construct(GuzzleException $previous, bool $useStatusCode = true)
|
||||
{
|
||||
/** @var \GuzzleHttp\Psr7\Response|null $response */
|
||||
$response = method_exists($previous, 'getResponse') ? $previous->getResponse() : null;
|
||||
|
||||
if ($useStatusCode) {
|
||||
$this->statusCode = is_null($response) ? 500 : $response->getStatusCode();
|
||||
$this->statusCode = is_null($response) ? $this->statusCode : $response->getStatusCode();
|
||||
}
|
||||
|
||||
parent::__construct(trans('admin/server.exceptions.daemon_exception', [
|
||||
$message = trans('admin/server.exceptions.daemon_exception', [
|
||||
'code' => is_null($response) ? 'E_CONN_REFUSED' : $response->getStatusCode(),
|
||||
]), $previous, DisplayException::LEVEL_WARNING);
|
||||
]);
|
||||
|
||||
// Attempt to pull the actual error message off the response and return that if it is not
|
||||
// a 500 level error.
|
||||
if ($this->statusCode < 500 && ! is_null($response)) {
|
||||
$body = $response->getBody();
|
||||
if (is_string($body) || (is_object($body) && method_exists($body, '__toString'))) {
|
||||
$body = json_decode(is_string($body) ? $body : $body->__toString(), true);
|
||||
$message = "[Wings Error]: " . Arr::get($body, 'error', $message);
|
||||
}
|
||||
}
|
||||
|
||||
$level = $this->statusCode >= 500 && $this->statusCode !== 504
|
||||
? DisplayException::LEVEL_ERROR
|
||||
: DisplayException::LEVEL_WARNING;
|
||||
|
||||
parent::__construct($message, $previous, $level);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
20
app/Exceptions/Http/HttpForbiddenException.php
Normal file
20
app/Exceptions/Http/HttpForbiddenException.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Exceptions\Http;
|
||||
|
||||
use Illuminate\Http\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class HttpForbiddenException extends HttpException
|
||||
{
|
||||
/**
|
||||
* HttpForbiddenException constructor.
|
||||
*
|
||||
* @param string|null $message
|
||||
* @param \Throwable|null $previous
|
||||
*/
|
||||
public function __construct(string $message = null, \Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(Response::HTTP_FORBIDDEN, $message, $previous);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Exceptions\Http\Server;
|
||||
|
||||
@@ -13,4 +6,11 @@ use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class FileSizeTooLargeException extends DisplayException
|
||||
{
|
||||
/**
|
||||
* FileSizeTooLargeException constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('The file you are attempting to open is too large to view in the file editor.');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Pterodactyl\Exceptions;
|
||||
|
||||
class PterodactylException extends \Exception
|
||||
use Exception;
|
||||
|
||||
class PterodactylException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
20
app/Exceptions/Service/Backup/TooManyBackupsException.php
Normal file
20
app/Exceptions/Service/Backup/TooManyBackupsException.php
Normal file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service\Backup;
|
||||
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class TooManyBackupsException extends DisplayException
|
||||
{
|
||||
/**
|
||||
* TooManyBackupsException constructor.
|
||||
*
|
||||
* @param int $backupLimit
|
||||
*/
|
||||
public function __construct(int $backupLimit)
|
||||
{
|
||||
parent::__construct(
|
||||
sprintf('Cannot create a new backup, this server has reached its limit of %d backups.', $backupLimit)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service\Helper;
|
||||
|
||||
class CdnVersionFetchingException extends \Exception
|
||||
use Exception;
|
||||
|
||||
class CdnVersionFetchingException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service\Pack;
|
||||
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class InvalidFileMimeTypeException extends DisplayException
|
||||
{
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service\Pack;
|
||||
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class InvalidPackArchiveFormatException extends DisplayException
|
||||
{
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service\Pack;
|
||||
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class UnreadableZipArchiveException extends DisplayException
|
||||
{
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service\Pack;
|
||||
|
||||
class ZipArchiveCreationException extends \Exception
|
||||
{
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service\Pack;
|
||||
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class ZipExtractionException extends DisplayException
|
||||
{
|
||||
}
|
||||
21
app/Exceptions/Service/ServiceLimitExceededException.php
Normal file
21
app/Exceptions/Service/ServiceLimitExceededException.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service;
|
||||
|
||||
use Throwable;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class ServiceLimitExceededException extends DisplayException
|
||||
{
|
||||
/**
|
||||
* Exception thrown when something goes over a defined limit, such as allocated
|
||||
* ports, tasks, databases, etc.
|
||||
*
|
||||
* @param string $message
|
||||
* @param \Throwable|null $previous
|
||||
*/
|
||||
public function __construct(string $message, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $previous, self::LEVEL_WARNING);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Exceptions\Service\User;
|
||||
|
||||
class TwoFactorAuthenticationTokenInvalid extends \Exception
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
|
||||
class TwoFactorAuthenticationTokenInvalid extends DisplayException
|
||||
{
|
||||
}
|
||||
|
||||
227
app/Extensions/Backups/BackupManager.php
Normal file
227
app/Extensions/Backups/BackupManager.php
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Extensions\Backups;
|
||||
|
||||
use Closure;
|
||||
use Aws\S3\S3Client;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Str;
|
||||
use Webmozart\Assert\Assert;
|
||||
use InvalidArgumentException;
|
||||
use League\Flysystem\AdapterInterface;
|
||||
use League\Flysystem\AwsS3v3\AwsS3Adapter;
|
||||
use League\Flysystem\Memory\MemoryAdapter;
|
||||
use Illuminate\Contracts\Config\Repository;
|
||||
|
||||
class BackupManager
|
||||
{
|
||||
/**
|
||||
* @var \Illuminate\Foundation\Application
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Contracts\Config\Repository
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* The array of resolved backup drivers.
|
||||
*
|
||||
* @var \League\Flysystem\AdapterInterface[]
|
||||
*/
|
||||
protected $adapters = [];
|
||||
|
||||
/**
|
||||
* The registered custom driver creators.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $customCreators;
|
||||
|
||||
/**
|
||||
* BackupManager constructor.
|
||||
*
|
||||
* @param \Illuminate\Foundation\Application $app
|
||||
*/
|
||||
public function __construct($app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->config = $app->make(Repository::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a backup adapter instance.
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return \League\Flysystem\AdapterInterface
|
||||
*/
|
||||
public function adapter(string $name = null)
|
||||
{
|
||||
return $this->get($name ?: $this->getDefaultAdapter());
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the given backup adapter instance.
|
||||
*
|
||||
* @param string $name
|
||||
* @param \League\Flysystem\AdapterInterface $disk
|
||||
* @return $this
|
||||
*/
|
||||
public function set(string $name, $disk)
|
||||
{
|
||||
$this->adapters[$name] = $disk;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a backup adapter.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \League\Flysystem\AdapterInterface
|
||||
*/
|
||||
protected function get(string $name)
|
||||
{
|
||||
return $this->adapters[$name] = $this->resolve($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the given backup disk.
|
||||
*
|
||||
* @param string $name
|
||||
* @return \League\Flysystem\AdapterInterface
|
||||
*/
|
||||
protected function resolve(string $name)
|
||||
{
|
||||
$config = $this->getConfig($name);
|
||||
|
||||
if (empty($config['adapter'])) {
|
||||
throw new InvalidArgumentException(
|
||||
"Backup disk [{$name}] does not have a configured adapter."
|
||||
);
|
||||
}
|
||||
|
||||
$adapter = $config['adapter'];
|
||||
|
||||
if (isset($this->customCreators[$name])) {
|
||||
return $this->callCustomCreator($config);
|
||||
}
|
||||
|
||||
$adapterMethod = 'create' . Str::studly($adapter) . 'Adapter';
|
||||
if (method_exists($this, $adapterMethod)) {
|
||||
$instance = $this->{$adapterMethod}($config);
|
||||
|
||||
Assert::isInstanceOf($instance, AdapterInterface::class);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException("Adapter [{$adapter}] is not supported.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls a custom creator for a given adapter type.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \League\Flysystem\AdapterInterface
|
||||
*/
|
||||
protected function callCustomCreator(array $config)
|
||||
{
|
||||
$adapter = $this->customCreators[$config['adapter']]($this->app, $config);
|
||||
|
||||
Assert::isInstanceOf($adapter, AdapterInterface::class);
|
||||
|
||||
return $adapter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new wings adapter.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \League\Flysystem\AdapterInterface
|
||||
*/
|
||||
public function createWingsAdapter(array $config)
|
||||
{
|
||||
return new MemoryAdapter(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new S3 adapter.
|
||||
*
|
||||
* @param array $config
|
||||
* @return \League\Flysystem\AdapterInterface
|
||||
*/
|
||||
public function createS3Adapter(array $config)
|
||||
{
|
||||
$config['version'] = 'latest';
|
||||
|
||||
if (! empty($config['key']) && ! empty($config['secret'])) {
|
||||
$config['credentials'] = Arr::only($config, ['key', 'secret', 'token']);
|
||||
}
|
||||
|
||||
$client = new S3Client($config);
|
||||
|
||||
return new AwsS3Adapter($client, $config['bucket'], $config['prefix'] ?? '', $config['options'] ?? []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration associated with a given backup type.
|
||||
*
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
protected function getConfig(string $name)
|
||||
{
|
||||
return $this->config->get("backups.disks.{$name}") ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default backup driver name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultAdapter()
|
||||
{
|
||||
return $this->config->get('backups.default');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default session driver name.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function setDefaultAdapter(string $name)
|
||||
{
|
||||
$this->config->set('backups.default', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the given adapter instances.
|
||||
*
|
||||
* @param string|string[] $adapter
|
||||
* @return $this
|
||||
*/
|
||||
public function forget($adapter)
|
||||
{
|
||||
foreach ((array) $adapter as $adapterName) {
|
||||
unset($this->adapters[$adapter]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom adapter creator closure.
|
||||
*
|
||||
* @param string $adapter
|
||||
* @param \Closure $callback
|
||||
* @return $this
|
||||
*/
|
||||
public function extend(string $adapter, Closure $callback)
|
||||
{
|
||||
$this->customCreators[$adapter] = $callback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
16
app/Extensions/Facades/Theme.php
Normal file
16
app/Extensions/Facades/Theme.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Extensions\Facades;
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
|
||||
class Theme extends Facade
|
||||
{
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
protected static function getFacadeAccessor()
|
||||
{
|
||||
return 'extensions.themes';
|
||||
}
|
||||
}
|
||||
18
app/Extensions/Illuminate/Database/Eloquent/Builder.php
Normal file
18
app/Extensions/Illuminate/Database/Eloquent/Builder.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Extensions\Illuminate\Database\Eloquent;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
||||
|
||||
class Builder extends EloquentBuilder
|
||||
{
|
||||
/**
|
||||
* Do nothing.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function search()
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
21
app/Extensions/Themes/Theme.php
Normal file
21
app/Extensions/Themes/Theme.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Extensions\Themes;
|
||||
|
||||
class Theme
|
||||
{
|
||||
public function js($path)
|
||||
{
|
||||
return sprintf('<script src="%s"></script>' . PHP_EOL, $this->getUrl($path));
|
||||
}
|
||||
|
||||
public function css($path)
|
||||
{
|
||||
return sprintf('<link media="all" type="text/css" rel="stylesheet" href="%s"/>' . PHP_EOL, $this->getUrl($path));
|
||||
}
|
||||
|
||||
protected function getUrl($path)
|
||||
{
|
||||
return '/themes/pterodactyl/' . ltrim($path, '/');
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,10 @@
|
||||
namespace Pterodactyl\Helpers;
|
||||
|
||||
use Exception;
|
||||
use Carbon\Carbon;
|
||||
use Cron\CronExpression;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\ViewErrorBag;
|
||||
|
||||
class Utilities
|
||||
{
|
||||
@@ -32,4 +35,31 @@ class Utilities
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts schedule cron data into a carbon object.
|
||||
*
|
||||
* @param string $minute
|
||||
* @param string $hour
|
||||
* @param string $dayOfMonth
|
||||
* @param string $dayOfWeek
|
||||
* @return \Carbon\Carbon
|
||||
*/
|
||||
public static function getScheduleNextRunDate(string $minute, string $hour, string $dayOfMonth, string $dayOfWeek)
|
||||
{
|
||||
return Carbon::instance(CronExpression::factory(
|
||||
sprintf('%s %s %s * %s', $minute, $hour, $dayOfMonth, $dayOfWeek)
|
||||
)->getNextRunDate());
|
||||
}
|
||||
|
||||
public static function checked($name, $default)
|
||||
{
|
||||
$errors = session('errors');
|
||||
|
||||
if (isset($errors) && $errors instanceof ViewErrorBag && $errors->any()) {
|
||||
return old($name) ? 'checked' : '';
|
||||
}
|
||||
|
||||
return ($default) ? 'checked' : '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,6 +165,7 @@ class DatabaseController extends Controller
|
||||
$this->alert->danger(
|
||||
sprintf('There was an error while trying to connect to the host or while executing a query: "%s"', $exception->getMessage())
|
||||
)->flash();
|
||||
|
||||
return $redirect->withInput($request->normalize());
|
||||
} else {
|
||||
throw $exception;
|
||||
|
||||
224
app/Http/Controllers/Admin/MountController.php
Normal file
224
app/Http/Controllers/Admin/MountController.php
Normal file
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Nest;
|
||||
use Pterodactyl\Models\Mount;
|
||||
use Pterodactyl\Models\Location;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Mounts\MountUpdateService;
|
||||
use Pterodactyl\Http\Requests\Admin\MountFormRequest;
|
||||
use Pterodactyl\Services\Mounts\MountCreationService;
|
||||
use Pterodactyl\Services\Mounts\MountDeletionService;
|
||||
use Pterodactyl\Repositories\Eloquent\MountRepository;
|
||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
||||
|
||||
class MountController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var \Prologue\Alerts\AlertsMessageBag
|
||||
*/
|
||||
protected $alert;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface
|
||||
*/
|
||||
protected $nestRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\LocationRepositoryInterface
|
||||
*/
|
||||
protected $locationRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\MountRepository
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* MountController constructor.
|
||||
*
|
||||
* @param \Prologue\Alerts\AlertsMessageBag $alert
|
||||
* @param \Pterodactyl\Contracts\Repository\NestRepositoryInterface $nestRepository
|
||||
* @param \Pterodactyl\Contracts\Repository\LocationRepositoryInterface $locationRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\MountRepository $repository
|
||||
*/
|
||||
public function __construct(
|
||||
AlertsMessageBag $alert,
|
||||
NestRepositoryInterface $nestRepository,
|
||||
LocationRepositoryInterface $locationRepository,
|
||||
MountRepository $repository
|
||||
) {
|
||||
$this->alert = $alert;
|
||||
$this->nestRepository = $nestRepository;
|
||||
$this->locationRepository = $locationRepository;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mount overview page.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
return view('admin.mounts.index', [
|
||||
'mounts' => $this->repository->getAllWithDetails(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mount view page.
|
||||
*
|
||||
* @param string $id
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function view($id)
|
||||
{
|
||||
$nests = Nest::query()->with('eggs')->get();
|
||||
$locations = Location::query()->with('nodes')->get();
|
||||
|
||||
return view('admin.mounts.view', [
|
||||
'mount' => $this->repository->getWithRelations($id),
|
||||
'nests' => $nests,
|
||||
'locations' => $locations,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to create new mount.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\MountFormRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function create(MountFormRequest $request)
|
||||
{
|
||||
/** @var \Pterodactyl\Models\Mount $mount */
|
||||
$model = (new Mount())->fill($request->validated());
|
||||
$model->forceFill(['uuid' => Uuid::uuid4()->toString()]);
|
||||
|
||||
$model->saveOrFail();
|
||||
$mount = $model->fresh();
|
||||
|
||||
$this->alert->success('Mount was created successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.mounts.view', $mount->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle request to update or delete location.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\MountFormRequest $request
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function update(MountFormRequest $request, Mount $mount)
|
||||
{
|
||||
if ($request->input('action') === 'delete') {
|
||||
return $this->delete($mount);
|
||||
}
|
||||
|
||||
$mount->forceFill($request->validated())->save();
|
||||
|
||||
$this->alert->success('Mount was updated successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.mounts.view', $mount->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a location from the system.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(Mount $mount)
|
||||
{
|
||||
$mount->delete();
|
||||
|
||||
return redirect()->route('admin.mounts');
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds eggs to the mount's many to many relation.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function addEggs(Request $request, Mount $mount)
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'eggs' => 'required|exists:eggs,id',
|
||||
]);
|
||||
|
||||
$eggs = $validatedData['eggs'] ?? [];
|
||||
if (count($eggs) > 0) {
|
||||
$mount->eggs()->attach($eggs);
|
||||
}
|
||||
|
||||
$this->alert->success('Mount was updated successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.mounts.view', $mount->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds nodes to the mount's many to many relation.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function addNodes(Request $request, Mount $mount)
|
||||
{
|
||||
$data = $request->validate(['nodes' => 'required|exists:nodes,id']);
|
||||
|
||||
$nodes = $data['nodes'] ?? [];
|
||||
if (count($nodes) > 0) {
|
||||
$mount->nodes()->attach($nodes);
|
||||
}
|
||||
|
||||
$this->alert->success('Mount was updated successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.mounts.view', $mount->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an egg from the mount's many to many relation.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
* @param int $egg_id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function deleteEgg(Mount $mount, int $egg_id)
|
||||
{
|
||||
$mount->eggs()->detach($egg_id);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an node from the mount's many to many relation.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
* @param int $node_id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function deleteNode(Mount $mount, int $node_id)
|
||||
{
|
||||
$mount->nodes()->detach($node_id);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
}
|
||||
@@ -25,10 +25,15 @@ use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
||||
class EggController extends Controller
|
||||
{
|
||||
protected $alert;
|
||||
|
||||
protected $creationService;
|
||||
|
||||
protected $deletionService;
|
||||
|
||||
protected $nestRepository;
|
||||
|
||||
protected $repository;
|
||||
|
||||
protected $updateService;
|
||||
|
||||
public function __construct(
|
||||
|
||||
@@ -1,15 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nests;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Pterodactyl\Models\Egg;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
@@ -81,14 +75,14 @@ class EggScriptController extends Controller
|
||||
* Handle a request to update the installation script for an Egg.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\Egg\EggScriptFormRequest $request
|
||||
* @param int $egg
|
||||
* @param \Pterodactyl\Models\Egg $egg
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\InvalidCopyFromException
|
||||
*/
|
||||
public function update(EggScriptFormRequest $request, int $egg): RedirectResponse
|
||||
public function update(EggScriptFormRequest $request, Egg $egg): RedirectResponse
|
||||
{
|
||||
$this->installScriptService->handle($egg, $request->normalize());
|
||||
$this->alert->success(trans('admin/nests.eggs.notices.script_updated'))->flash();
|
||||
|
||||
@@ -102,7 +102,7 @@ class EggShareController extends Controller
|
||||
* Update an existing Egg using a new imported file.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\Egg\EggImportFormRequest $request
|
||||
* @param int $egg
|
||||
* @param \Pterodactyl\Models\Egg $egg
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
@@ -110,7 +110,7 @@ class EggShareController extends Controller
|
||||
* @throws \Pterodactyl\Exceptions\Service\Egg\BadJsonFormatException
|
||||
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
|
||||
*/
|
||||
public function update(EggImportFormRequest $request, int $egg): RedirectResponse
|
||||
public function update(EggImportFormRequest $request, Egg $egg): RedirectResponse
|
||||
{
|
||||
$this->updateImporterService->handle($egg, $request->file('import_file'));
|
||||
$this->alert->success(trans('admin/nests.eggs.notices.updated_via_import'))->flash();
|
||||
|
||||
88
app/Http/Controllers/Admin/NodeAutoDeployController.php
Normal file
88
app/Http/Controllers/Admin/NodeAutoDeployController.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Pterodactyl\Models\ApiKey;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Encryption\Encrypter;
|
||||
use Pterodactyl\Services\Api\KeyCreationService;
|
||||
use Pterodactyl\Repositories\Eloquent\ApiKeyRepository;
|
||||
|
||||
class NodeAutoDeployController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Api\KeyCreationService
|
||||
*/
|
||||
private $keyCreationService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\ApiKeyRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Contracts\Encryption\Encrypter
|
||||
*/
|
||||
private $encrypter;
|
||||
|
||||
/**
|
||||
* NodeAutoDeployController constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Repositories\Eloquent\ApiKeyRepository $repository
|
||||
* @param \Illuminate\Contracts\Encryption\Encrypter $encrypter
|
||||
* @param \Pterodactyl\Services\Api\KeyCreationService $keyCreationService
|
||||
*/
|
||||
public function __construct(
|
||||
ApiKeyRepository $repository,
|
||||
Encrypter $encrypter,
|
||||
KeyCreationService $keyCreationService
|
||||
) {
|
||||
$this->keyCreationService = $keyCreationService;
|
||||
$this->repository = $repository;
|
||||
$this->encrypter = $encrypter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new API key for the logged in user with only permission to read
|
||||
* nodes, and returns that as the deployment key for a node.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
*/
|
||||
public function __invoke(Request $request, Node $node)
|
||||
{
|
||||
/** @var \Pterodactyl\Models\ApiKey|null $key */
|
||||
$key = $this->repository->getApplicationKeys($request->user())
|
||||
->filter(function (ApiKey $key) {
|
||||
foreach ($key->getAttributes() as $permission => $value) {
|
||||
if ($permission === 'r_nodes' && $value === 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
->first();
|
||||
|
||||
// We couldn't find a key that exists for this user with only permission for
|
||||
// reading nodes. Go ahead and create it now.
|
||||
if (! $key) {
|
||||
$key = $this->keyCreationService->setKeyType(ApiKey::TYPE_APPLICATION)->handle([
|
||||
'user_id' => $request->user()->id,
|
||||
'memo' => 'Automatically generated node deployment key.',
|
||||
'allowed_ips' => [],
|
||||
], ['r_nodes' => 1]);
|
||||
}
|
||||
|
||||
return JsonResponse::create([
|
||||
'node' => $node->id,
|
||||
'token' => $key->identifier . $this->encrypter->decrypt($key->token),
|
||||
]);
|
||||
}
|
||||
}
|
||||
53
app/Http/Controllers/Admin/Nodes/NodeController.php
Normal file
53
app/Http/Controllers/Admin/Nodes/NodeController.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nodes;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||
|
||||
class NodeController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var \Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
private $view;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\NodeRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* NodeController constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Repositories\Eloquent\NodeRepository $repository
|
||||
* @param \Illuminate\Contracts\View\Factory $view
|
||||
*/
|
||||
public function __construct(NodeRepository $repository, Factory $view)
|
||||
{
|
||||
$this->view = $view;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a listing of nodes on the system.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$nodes = QueryBuilder::for(
|
||||
Node::query()->with('location')->withCount('servers')
|
||||
)
|
||||
->allowedFilters(['uuid', 'name'])
|
||||
->allowedSorts(['id'])
|
||||
->paginate(25);
|
||||
|
||||
return $this->view->make('admin.nodes.index', ['nodes' => $nodes]);
|
||||
}
|
||||
}
|
||||
164
app/Http/Controllers/Admin/Nodes/NodeViewController.php
Normal file
164
app/Http/Controllers/Admin/Nodes/NodeViewController.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nodes;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Support\Collection;
|
||||
use Pterodactyl\Models\Allocation;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||
use Pterodactyl\Traits\Controllers\JavascriptInjection;
|
||||
use Pterodactyl\Services\Helpers\SoftwareVersionService;
|
||||
use Pterodactyl\Repositories\Eloquent\LocationRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\AllocationRepository;
|
||||
|
||||
class NodeViewController extends Controller
|
||||
{
|
||||
use JavascriptInjection;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\NodeRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
private $view;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Helpers\SoftwareVersionService
|
||||
*/
|
||||
private $versionService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\LocationRepository
|
||||
*/
|
||||
private $locationRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\AllocationRepository
|
||||
*/
|
||||
private $allocationRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\ServerRepository
|
||||
*/
|
||||
private $serverRepository;
|
||||
|
||||
/**
|
||||
* NodeViewController constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Repositories\Eloquent\AllocationRepository $allocationRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\LocationRepository $locationRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\NodeRepository $repository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $serverRepository
|
||||
* @param \Pterodactyl\Services\Helpers\SoftwareVersionService $versionService
|
||||
* @param \Illuminate\Contracts\View\Factory $view
|
||||
*/
|
||||
public function __construct(
|
||||
AllocationRepository $allocationRepository,
|
||||
LocationRepository $locationRepository,
|
||||
NodeRepository $repository,
|
||||
ServerRepository $serverRepository,
|
||||
SoftwareVersionService $versionService,
|
||||
Factory $view
|
||||
) {
|
||||
$this->repository = $repository;
|
||||
$this->view = $view;
|
||||
$this->versionService = $versionService;
|
||||
$this->locationRepository = $locationRepository;
|
||||
$this->allocationRepository = $allocationRepository;
|
||||
$this->serverRepository = $serverRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns index view for a specific node on the system.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request, Node $node)
|
||||
{
|
||||
$node = $this->repository->loadLocationAndServerCount($node);
|
||||
|
||||
return $this->view->make('admin.nodes.view.index', [
|
||||
'node' => $node,
|
||||
'stats' => $this->repository->getUsageStats($node),
|
||||
'version' => $this->versionService,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings page for a specific node.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function settings(Request $request, Node $node)
|
||||
{
|
||||
return $this->view->make('admin.nodes.view.settings', [
|
||||
'node' => $node,
|
||||
'locations' => $this->locationRepository->all(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the node configuration page for a specific node.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function configuration(Request $request, Node $node)
|
||||
{
|
||||
return $this->view->make('admin.nodes.view.configuration', compact('node'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the node allocation management page.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function allocations(Request $request, Node $node)
|
||||
{
|
||||
$node = $this->repository->loadNodeAllocations($node);
|
||||
|
||||
$this->plainInject(['node' => Collection::wrap($node)->only(['id'])]);
|
||||
|
||||
return $this->view->make('admin.nodes.view.allocation', [
|
||||
'node' => $node,
|
||||
'allocations' => Allocation::query()->where('node_id', $node->id)
|
||||
->groupBy('ip')
|
||||
->orderByRaw('INET_ATON(ip) ASC')
|
||||
->get(['ip']),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a listing of servers that exist for this specific node.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function servers(Request $request, Node $node)
|
||||
{
|
||||
$this->plainInject([
|
||||
'node' => Collection::wrap($node->makeVisible(['daemon_token_id', 'daemon_token']))
|
||||
->only(['scheme', 'fqdn', 'daemonListen', 'daemon_token_id', 'daemon_token']),
|
||||
]);
|
||||
|
||||
return $this->view->make('admin.nodes.view.servers', [
|
||||
'node' => $node,
|
||||
'servers' => $this->serverRepository->loadAllServersForNode($node->id, 25),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Nodes;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository;
|
||||
|
||||
class SystemInformationController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Wings\DaemonConfigurationRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* SystemInformationController constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Repositories\Wings\DaemonConfigurationRepository $repository
|
||||
*/
|
||||
public function __construct(DaemonConfigurationRepository $repository)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns system information from the Daemon.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function __invoke(Request $request, Node $node)
|
||||
{
|
||||
$data = $this->repository->setNode($node)->getSystemInformation();
|
||||
|
||||
return JsonResponse::create([
|
||||
'version' => $data['version'] ?? '',
|
||||
'system' => [
|
||||
'type' => Str::title($data['os'] ?? 'Unknown'),
|
||||
'arch' => $data['architecture'] ?? '--',
|
||||
'release' => $data['kernel_version'] ?? '--',
|
||||
'cpus' => $data['cpu_count'] ?? 0,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Javascript;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\Response;
|
||||
@@ -137,19 +136,6 @@ class NodesController extends Controller
|
||||
$this->versionService = $versionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the index page listing all nodes on the panel.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
return view('admin.nodes.index', [
|
||||
'nodes' => $this->repository->setSearchTerm($request->input('query'))->getNodeListingData(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays create new node page.
|
||||
*
|
||||
@@ -183,79 +169,6 @@ class NodesController extends Controller
|
||||
return redirect()->route('admin.nodes.view.allocation', $node->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the index overview page for a specific node.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function viewIndex(Node $node)
|
||||
{
|
||||
return view('admin.nodes.view.index', [
|
||||
'node' => $this->repository->loadLocationAndServerCount($node),
|
||||
'stats' => $this->repository->getUsageStats($node),
|
||||
'version' => $this->versionService,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the settings page for a specific node.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function viewSettings(Node $node)
|
||||
{
|
||||
return view('admin.nodes.view.settings', [
|
||||
'node' => $node,
|
||||
'locations' => $this->locationRepository->all(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the configuration page for a specific node.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function viewConfiguration(Node $node)
|
||||
{
|
||||
return view('admin.nodes.view.configuration', ['node' => $node]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the allocation page for a specific node.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function viewAllocation(Node $node)
|
||||
{
|
||||
$this->repository->loadNodeAllocations($node);
|
||||
Javascript::put(['node' => collect($node)->only(['id'])]);
|
||||
|
||||
return view('admin.nodes.view.allocation', [
|
||||
'allocations' => $this->allocationRepository->setColumns(['ip'])->getUniqueAllocationIpsForNode($node->id),
|
||||
'node' => $node,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the server listing page for a specific node.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function viewServers(Node $node)
|
||||
{
|
||||
$servers = $this->serverRepository->loadAllServersForNode($node->id, 25);
|
||||
Javascript::put([
|
||||
'node' => collect($node->makeVisible('daemonSecret'))->only(['scheme', 'fqdn', 'daemonListen', 'daemonSecret']),
|
||||
]);
|
||||
|
||||
return view('admin.nodes.view.servers', ['node' => $node, 'servers' => $servers]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates settings for a node.
|
||||
*
|
||||
@@ -386,18 +299,4 @@ class NodesController extends Controller
|
||||
|
||||
return redirect()->route('admin.nodes');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration token to auto-deploy a node.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function setToken(Node $node)
|
||||
{
|
||||
$token = bin2hex(random_bytes(16));
|
||||
$this->cache->put('Node:Configuration:' . $token, $node->id, 5);
|
||||
|
||||
return response()->json(['token' => $token]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,250 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Pterodactyl - Panel
|
||||
* Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com>.
|
||||
*
|
||||
* This software is licensed under the terms of the MIT license.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Pack;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Packs\ExportPackService;
|
||||
use Pterodactyl\Services\Packs\PackUpdateService;
|
||||
use Pterodactyl\Services\Packs\PackCreationService;
|
||||
use Pterodactyl\Services\Packs\PackDeletionService;
|
||||
use Pterodactyl\Http\Requests\Admin\PackFormRequest;
|
||||
use Pterodactyl\Services\Packs\TemplateUploadService;
|
||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\PackRepositoryInterface;
|
||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
||||
|
||||
class PackController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var \Prologue\Alerts\AlertsMessageBag
|
||||
*/
|
||||
protected $alert;
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Contracts\Config\Repository
|
||||
*/
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Packs\PackCreationService
|
||||
*/
|
||||
protected $creationService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Packs\PackDeletionService
|
||||
*/
|
||||
protected $deletionService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Packs\ExportPackService
|
||||
*/
|
||||
protected $exportService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\PackRepositoryInterface
|
||||
*/
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Packs\PackUpdateService
|
||||
*/
|
||||
protected $updateService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface
|
||||
*/
|
||||
protected $serviceRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Packs\TemplateUploadService
|
||||
*/
|
||||
protected $templateUploadService;
|
||||
|
||||
/**
|
||||
* PackController constructor.
|
||||
*
|
||||
* @param \Prologue\Alerts\AlertsMessageBag $alert
|
||||
* @param \Illuminate\Contracts\Config\Repository $config
|
||||
* @param \Pterodactyl\Services\Packs\ExportPackService $exportService
|
||||
* @param \Pterodactyl\Services\Packs\PackCreationService $creationService
|
||||
* @param \Pterodactyl\Services\Packs\PackDeletionService $deletionService
|
||||
* @param \Pterodactyl\Contracts\Repository\PackRepositoryInterface $repository
|
||||
* @param \Pterodactyl\Services\Packs\PackUpdateService $updateService
|
||||
* @param \Pterodactyl\Contracts\Repository\NestRepositoryInterface $serviceRepository
|
||||
* @param \Pterodactyl\Services\Packs\TemplateUploadService $templateUploadService
|
||||
*/
|
||||
public function __construct(
|
||||
AlertsMessageBag $alert,
|
||||
ConfigRepository $config,
|
||||
ExportPackService $exportService,
|
||||
PackCreationService $creationService,
|
||||
PackDeletionService $deletionService,
|
||||
PackRepositoryInterface $repository,
|
||||
PackUpdateService $updateService,
|
||||
NestRepositoryInterface $serviceRepository,
|
||||
TemplateUploadService $templateUploadService
|
||||
) {
|
||||
$this->alert = $alert;
|
||||
$this->config = $config;
|
||||
$this->creationService = $creationService;
|
||||
$this->deletionService = $deletionService;
|
||||
$this->exportService = $exportService;
|
||||
$this->repository = $repository;
|
||||
$this->updateService = $updateService;
|
||||
$this->serviceRepository = $serviceRepository;
|
||||
$this->templateUploadService = $templateUploadService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display listing of all packs on the system.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
return view('admin.packs.index', [
|
||||
'packs' => $this->repository->setSearchTerm($request->input('query'))->paginateWithEggAndServerCount(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display new pack creation form.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
return view('admin.packs.new', [
|
||||
'nests' => $this->serviceRepository->getWithEggs(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display new pack creation modal for use with template upload.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function newTemplate()
|
||||
{
|
||||
return view('admin.packs.modal', [
|
||||
'nests' => $this->serviceRepository->getWithEggs(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle create pack request and route user to location.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\PackFormRequest $request
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidFileMimeTypeException
|
||||
* @throws \Pterodactyl\Exceptions\Service\InvalidFileUploadException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Pack\InvalidPackArchiveFormatException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Pack\UnreadableZipArchiveException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Pack\ZipExtractionException
|
||||
*/
|
||||
public function store(PackFormRequest $request)
|
||||
{
|
||||
if ($request->filled('from_template')) {
|
||||
$pack = $this->templateUploadService->handle($request->input('egg_id'), $request->file('file_upload'));
|
||||
} else {
|
||||
$pack = $this->creationService->handle($request->normalize(), $request->file('file_upload'));
|
||||
}
|
||||
|
||||
$this->alert->success(trans('admin/pack.notices.pack_created'))->flash();
|
||||
|
||||
return redirect()->route('admin.packs.view', $pack->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display pack view template to user.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Pack $pack
|
||||
* @return \Illuminate\View\View
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function view(Pack $pack)
|
||||
{
|
||||
return view('admin.packs.view', [
|
||||
'pack' => $this->repository->loadServerData($pack),
|
||||
'nests' => $this->serviceRepository->getWithEggs(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle updating or deleting pack information.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\PackFormRequest $request
|
||||
* @param \Pterodactyl\Models\Pack $pack
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
|
||||
*/
|
||||
public function update(PackFormRequest $request, Pack $pack)
|
||||
{
|
||||
$this->updateService->handle($pack, $request->normalize());
|
||||
$this->alert->success(trans('admin/pack.notices.pack_updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.packs.view', $pack->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a pack if no servers are attached to it currently.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Pack $pack
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
|
||||
*/
|
||||
public function destroy(Pack $pack)
|
||||
{
|
||||
$this->deletionService->handle($pack->id);
|
||||
$this->alert->success(trans('admin/pack.notices.pack_deleted', [
|
||||
'name' => $pack->name,
|
||||
]))->flash();
|
||||
|
||||
return redirect()->route('admin.packs');
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an archive of the pack and downloads it to the browser.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Pack $pack
|
||||
* @param bool|string $files
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Pack\ZipArchiveCreationException
|
||||
*/
|
||||
public function export(Pack $pack, $files = false)
|
||||
{
|
||||
$filename = $this->exportService->handle($pack, is_string($files));
|
||||
|
||||
if (is_string($files)) {
|
||||
return response()->download($filename, 'pack-' . $pack->name . '.zip')->deleteFileAfterSend(true);
|
||||
}
|
||||
|
||||
return response()->download($filename, 'pack-' . $pack->name . '.json', [
|
||||
'Content-Type' => 'application/json',
|
||||
])->deleteFileAfterSend(true);
|
||||
}
|
||||
}
|
||||
132
app/Http/Controllers/Admin/Servers/CreateServerController.php
Normal file
132
app/Http/Controllers/Admin/Servers/CreateServerController.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Servers;
|
||||
|
||||
use JavaScript;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Repositories\Eloquent\NestRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||
use Pterodactyl\Http\Requests\Admin\ServerFormRequest;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||
use Pterodactyl\Services\Servers\ServerCreationService;
|
||||
use Pterodactyl\Repositories\Eloquent\LocationRepository;
|
||||
|
||||
class CreateServerController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\ServerRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\NodeRepository
|
||||
*/
|
||||
private $nodeRepository;
|
||||
|
||||
/**
|
||||
* @var \Prologue\Alerts\AlertsMessageBag
|
||||
*/
|
||||
private $alert;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\NestRepository
|
||||
*/
|
||||
private $nestRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\LocationRepository
|
||||
*/
|
||||
private $locationRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\ServerCreationService
|
||||
*/
|
||||
private $creationService;
|
||||
|
||||
/**
|
||||
* CreateServerController constructor.
|
||||
*
|
||||
* @param \Prologue\Alerts\AlertsMessageBag $alert
|
||||
* @param \Pterodactyl\Repositories\Eloquent\NestRepository $nestRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\LocationRepository $locationRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\NodeRepository $nodeRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository
|
||||
* @param \Pterodactyl\Services\Servers\ServerCreationService $creationService
|
||||
*/
|
||||
public function __construct(
|
||||
AlertsMessageBag $alert,
|
||||
NestRepository $nestRepository,
|
||||
LocationRepository $locationRepository,
|
||||
NodeRepository $nodeRepository,
|
||||
ServerRepository $repository,
|
||||
ServerCreationService $creationService
|
||||
) {
|
||||
$this->repository = $repository;
|
||||
$this->nodeRepository = $nodeRepository;
|
||||
$this->alert = $alert;
|
||||
$this->nestRepository = $nestRepository;
|
||||
$this->locationRepository = $locationRepository;
|
||||
$this->creationService = $creationService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the create server page.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\Factory
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$nodes = $this->nodeRepository->all();
|
||||
if (count($nodes) < 1) {
|
||||
$this->alert->warning(trans('admin/server.alerts.node_required'))->flash();
|
||||
|
||||
return redirect()->route('admin.nodes');
|
||||
}
|
||||
|
||||
$nests = $this->nestRepository->getWithEggs();
|
||||
|
||||
Javascript::put([
|
||||
'nodeData' => $this->nodeRepository->getNodesForServerCreation(),
|
||||
'nests' => $nests->map(function ($item) {
|
||||
return array_merge($item->toArray(), [
|
||||
'eggs' => $item->eggs->keyBy('id')->toArray(),
|
||||
]);
|
||||
})->keyBy('id'),
|
||||
]);
|
||||
|
||||
return view('admin.servers.new', [
|
||||
'locations' => $this->locationRepository->all(),
|
||||
'nests' => $nests,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new server on the remote system.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\ServerFormRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableAllocationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableNodeException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function store(ServerFormRequest $request)
|
||||
{
|
||||
$server = $this->creationService->handle(
|
||||
$request->except(['_token'])
|
||||
);
|
||||
|
||||
$this->alert->success(
|
||||
trans('admin/server.alerts.server_created')
|
||||
)->flash();
|
||||
|
||||
return RedirectResponse::create('/admin/servers/view/' . $server->id);
|
||||
}
|
||||
}
|
||||
54
app/Http/Controllers/Admin/Servers/ServerController.php
Normal file
54
app/Http/Controllers/Admin/Servers/ServerController.php
Normal file
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Servers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||
|
||||
class ServerController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var \Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
private $view;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\ServerRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* ServerController constructor.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\Factory $view
|
||||
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository
|
||||
*/
|
||||
public function __construct(
|
||||
Factory $view,
|
||||
ServerRepository $repository
|
||||
) {
|
||||
$this->view = $view;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the servers that exist on the system using a paginated result set. If
|
||||
* a query is passed along in the request it is also passed to the repository function.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$servers = QueryBuilder::for(Server::query()->with('node', 'user', 'allocation'))
|
||||
->allowedFilters(['uuid', 'name', 'image'])
|
||||
->allowedSorts(['id', 'uuid'])
|
||||
->paginate(config()->get('pterodactyl.paginate.admin.servers'));
|
||||
|
||||
return $this->view->make('admin.servers.index', ['servers' => $servers]);
|
||||
}
|
||||
}
|
||||
177
app/Http/Controllers/Admin/Servers/ServerTransferController.php
Normal file
177
app/Http/Controllers/Admin/Servers/ServerTransferController.php
Normal file
@@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Servers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Pterodactyl\Models\ServerTransfer;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Servers\TransferService;
|
||||
use Pterodactyl\Services\Servers\SuspensionService;
|
||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\LocationRepository;
|
||||
use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository;
|
||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
||||
|
||||
class ServerTransferController extends Controller
|
||||
{
|
||||
/**
|
||||
* @var \Prologue\Alerts\AlertsMessageBag
|
||||
*/
|
||||
private $alert;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface
|
||||
*/
|
||||
private $allocationRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\ServerRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\LocationRepository
|
||||
*/
|
||||
private $locationRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\NodeRepository
|
||||
*/
|
||||
private $nodeRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\SuspensionService
|
||||
*/
|
||||
private $suspensionService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\TransferService
|
||||
*/
|
||||
private $transferService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Wings\DaemonConfigurationRepository
|
||||
*/
|
||||
private $daemonConfigurationRepository;
|
||||
|
||||
/**
|
||||
* ServerTransferController constructor.
|
||||
*
|
||||
* @param \Prologue\Alerts\AlertsMessageBag $alert
|
||||
* @param \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface $allocationRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\LocationRepository $locationRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\NodeRepository $nodeRepository
|
||||
* @param \Pterodactyl\Services\Servers\SuspensionService $suspensionService
|
||||
* @param \Pterodactyl\Services\Servers\TransferService $transferService
|
||||
* @param \Pterodactyl\Repositories\Wings\DaemonConfigurationRepository $daemonConfigurationRepository
|
||||
*/
|
||||
public function __construct(
|
||||
AlertsMessageBag $alert,
|
||||
AllocationRepositoryInterface $allocationRepository,
|
||||
ServerRepository $repository,
|
||||
LocationRepository $locationRepository,
|
||||
NodeRepository $nodeRepository,
|
||||
SuspensionService $suspensionService,
|
||||
TransferService $transferService,
|
||||
DaemonConfigurationRepository $daemonConfigurationRepository
|
||||
) {
|
||||
$this->alert = $alert;
|
||||
$this->allocationRepository = $allocationRepository;
|
||||
$this->repository = $repository;
|
||||
$this->locationRepository = $locationRepository;
|
||||
$this->nodeRepository = $nodeRepository;
|
||||
$this->suspensionService = $suspensionService;
|
||||
$this->transferService = $transferService;
|
||||
$this->daemonConfigurationRepository = $daemonConfigurationRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a transfer of a server to a new node.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function transfer(Request $request, Server $server)
|
||||
{
|
||||
$validatedData = $request->validate([
|
||||
'node_id' => 'required|exists:nodes,id',
|
||||
'allocation_id' => 'required|bail|unique:servers|exists:allocations,id',
|
||||
'allocation_additional' => 'nullable',
|
||||
]);
|
||||
|
||||
$node_id = $validatedData['node_id'];
|
||||
$allocation_id = intval($validatedData['allocation_id']);
|
||||
$additional_allocations = array_map('intval', $validatedData['allocation_additional'] ?? []);
|
||||
|
||||
// Check if the node is viable for the transfer.
|
||||
$node = $this->nodeRepository->getNodeWithResourceUsage($node_id);
|
||||
if ($node->isViable($server->memory, $server->disk)) {
|
||||
// Check if the selected daemon is online.
|
||||
$this->daemonConfigurationRepository->setNode($node)->getSystemInformation();
|
||||
|
||||
// Suspend the server and request an archive to be created.
|
||||
$this->suspensionService->toggle($server, 'suspend');
|
||||
|
||||
// Create a new ServerTransfer entry.
|
||||
$transfer = new ServerTransfer;
|
||||
|
||||
$transfer->server_id = $server->id;
|
||||
$transfer->old_node = $server->node_id;
|
||||
$transfer->new_node = $node_id;
|
||||
$transfer->old_allocation = $server->allocation_id;
|
||||
$transfer->new_allocation = $allocation_id;
|
||||
$transfer->old_additional_allocations = json_encode($server->allocations->where('id', '!=', $server->allocation_id)->pluck('id'));
|
||||
$transfer->new_additional_allocations = json_encode($additional_allocations);
|
||||
|
||||
$transfer->save();
|
||||
|
||||
// Add the allocations to the server so they cannot be automatically assigned while the transfer is in progress.
|
||||
$this->assignAllocationsToServer($server, $node_id, $allocation_id, $additional_allocations);
|
||||
|
||||
// Request an archive from the server's current daemon. (this also checks if the daemon is online)
|
||||
$this->transferService->requestArchive($server);
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.transfer_started'))->flash();
|
||||
} else {
|
||||
$this->alert->danger(trans('admin/server.alerts.transfer_not_viable'))->flash();
|
||||
}
|
||||
|
||||
return redirect()->route('admin.servers.view.manage', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the specified allocations to the specified server.
|
||||
*
|
||||
* @param Server $server
|
||||
* @param int $node_id
|
||||
* @param int $allocation_id
|
||||
* @param array $additional_allocations
|
||||
*/
|
||||
private function assignAllocationsToServer(Server $server, int $node_id, int $allocation_id, array $additional_allocations)
|
||||
{
|
||||
$allocations = $additional_allocations;
|
||||
array_push($allocations, $allocation_id);
|
||||
|
||||
$unassigned = $this->allocationRepository->getUnassignedAllocationIds($node_id);
|
||||
|
||||
$updateIds = [];
|
||||
foreach ($allocations as $allocation) {
|
||||
if (! in_array($allocation, $unassigned)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$updateIds[] = $allocation;
|
||||
}
|
||||
|
||||
if (! empty($updateIds)) {
|
||||
$this->allocationRepository->updateWhereIn('id', $updateIds, ['server_id' => $server->id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
245
app/Http/Controllers/Admin/Servers/ServerViewController.php
Normal file
245
app/Http/Controllers/Admin/Servers/ServerViewController.php
Normal file
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin\Servers;
|
||||
|
||||
use JavaScript;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\Nest;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Services\Servers\EnvironmentService;
|
||||
use Pterodactyl\Repositories\Eloquent\NestRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\NodeRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\MountRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
||||
use Pterodactyl\Traits\Controllers\JavascriptInjection;
|
||||
use Pterodactyl\Repositories\Eloquent\LocationRepository;
|
||||
use Pterodactyl\Repositories\Eloquent\DatabaseHostRepository;
|
||||
|
||||
class ServerViewController extends Controller
|
||||
{
|
||||
use JavascriptInjection;
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Contracts\View\Factory
|
||||
*/
|
||||
private $view;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\DatabaseHostRepository
|
||||
*/
|
||||
private $databaseHostRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\ServerRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\MountRepository
|
||||
*/
|
||||
protected $mountRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\NestRepository
|
||||
*/
|
||||
private $nestRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\LocationRepository
|
||||
*/
|
||||
private $locationRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Repositories\Eloquent\NodeRepository
|
||||
*/
|
||||
private $nodeRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\EnvironmentService
|
||||
*/
|
||||
private $environmentService;
|
||||
|
||||
/**
|
||||
* ServerViewController constructor.
|
||||
*
|
||||
* @param \Illuminate\Contracts\View\Factory $view
|
||||
* @param \Pterodactyl\Repositories\Eloquent\DatabaseHostRepository $databaseHostRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\LocationRepository $locationRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\MountRepository $mountRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\NestRepository $nestRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\NodeRepository $nodeRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository
|
||||
* @param \Pterodactyl\Services\Servers\EnvironmentService $environmentService
|
||||
*/
|
||||
public function __construct(
|
||||
Factory $view,
|
||||
DatabaseHostRepository $databaseHostRepository,
|
||||
LocationRepository $locationRepository,
|
||||
MountRepository $mountRepository,
|
||||
NestRepository $nestRepository,
|
||||
NodeRepository $nodeRepository,
|
||||
ServerRepository $repository,
|
||||
EnvironmentService $environmentService
|
||||
) {
|
||||
$this->view = $view;
|
||||
$this->databaseHostRepository = $databaseHostRepository;
|
||||
$this->locationRepository = $locationRepository;
|
||||
$this->mountRepository = $mountRepository;
|
||||
$this->nestRepository = $nestRepository;
|
||||
$this->nodeRepository = $nodeRepository;
|
||||
$this->repository = $repository;
|
||||
$this->environmentService = $environmentService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index view for a server.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index(Request $request, Server $server)
|
||||
{
|
||||
return $this->view->make('admin.servers.view.index', compact('server'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server details page.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function details(Request $request, Server $server)
|
||||
{
|
||||
return $this->view->make('admin.servers.view.details', compact('server'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view of server build settings.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function build(Request $request, Server $server)
|
||||
{
|
||||
$allocations = $server->node->allocations->toBase();
|
||||
|
||||
return $this->view->make('admin.servers.view.build', [
|
||||
'server' => $server,
|
||||
'assigned' => $allocations->where('server_id', $server->id)->sortBy('port')->sortBy('ip'),
|
||||
'unassigned' => $allocations->where('server_id', null)->sortBy('port')->sortBy('ip'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server startup management page.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function startup(Request $request, Server $server)
|
||||
{
|
||||
$nests = $this->nestRepository->getWithEggs();
|
||||
$variables = $this->environmentService->handle($server);
|
||||
|
||||
$this->plainInject([
|
||||
'server' => $server,
|
||||
'server_variables' => $variables,
|
||||
'nests' => $nests->map(function (Nest $item) {
|
||||
return array_merge($item->toArray(), [
|
||||
'eggs' => $item->eggs->keyBy('id')->toArray(),
|
||||
]);
|
||||
})->keyBy('id'),
|
||||
]);
|
||||
|
||||
return $this->view->make('admin.servers.view.startup', compact('server', 'nests'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the databases that exist for the server.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function database(Request $request, Server $server)
|
||||
{
|
||||
return $this->view->make('admin.servers.view.database', [
|
||||
'hosts' => $this->databaseHostRepository->all(),
|
||||
'server' => $server,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all of the mounts that exist for the server.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function mounts(Request $request, Server $server)
|
||||
{
|
||||
$server->load('mounts');
|
||||
|
||||
return $this->view->make('admin.servers.view.mounts', [
|
||||
'mounts' => $this->mountRepository->getMountListForServer($server),
|
||||
'server' => $server,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base server management page, or an exception if the server
|
||||
* is in a state that cannot be recovered from.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function manage(Request $request, Server $server)
|
||||
{
|
||||
if ($server->installed > 1) {
|
||||
throw new DisplayException(
|
||||
'This server is in a failed install state and cannot be recovered. Please delete and re-create the server.'
|
||||
);
|
||||
}
|
||||
|
||||
// Check if the panel doesn't have at least 2 nodes configured.
|
||||
$nodes = $this->nodeRepository->all();
|
||||
$canTransfer = false;
|
||||
if (count($nodes) >= 2) {
|
||||
$canTransfer = true;
|
||||
}
|
||||
|
||||
Javascript::put([
|
||||
'nodeData' => $this->nodeRepository->getNodesForServerCreation(),
|
||||
]);
|
||||
|
||||
return $this->view->make('admin.servers.view.manage', [
|
||||
'server' => $server,
|
||||
'locations' => $this->locationRepository->all(),
|
||||
'canTransfer' => $canTransfer,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the server deletion page.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function delete(Request $request, Server $server)
|
||||
{
|
||||
return $this->view->make('admin.servers.view.delete', compact('server'));
|
||||
}
|
||||
}
|
||||
@@ -9,32 +9,35 @@
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Admin;
|
||||
|
||||
use Javascript;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\User;
|
||||
use Pterodactyl\Models\Mount;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use GuzzleHttp\Exception\RequestException;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Pterodactyl\Services\Servers\SuspensionService;
|
||||
use Pterodactyl\Http\Requests\Admin\ServerFormRequest;
|
||||
use Pterodactyl\Services\Servers\ServerCreationService;
|
||||
use Pterodactyl\Repositories\Eloquent\MountRepository;
|
||||
use Pterodactyl\Services\Servers\ServerDeletionService;
|
||||
use Pterodactyl\Services\Servers\ReinstallServerService;
|
||||
use Pterodactyl\Services\Servers\ContainerRebuildService;
|
||||
use Pterodactyl\Exceptions\Model\DataValidationException;
|
||||
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
|
||||
use Pterodactyl\Services\Servers\BuildModificationService;
|
||||
use Pterodactyl\Services\Databases\DatabasePasswordService;
|
||||
use Pterodactyl\Services\Servers\DetailsModificationService;
|
||||
use Pterodactyl\Services\Servers\StartupModificationService;
|
||||
use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\NodeRepositoryInterface;
|
||||
use Pterodactyl\Repositories\Eloquent\DatabaseHostRepository;
|
||||
use Pterodactyl\Services\Databases\DatabaseManagementService;
|
||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
||||
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
||||
use Pterodactyl\Services\Servers\ServerConfigurationStructureService;
|
||||
use Pterodactyl\Http\Requests\Admin\Servers\Databases\StoreServerDatabaseRequest;
|
||||
|
||||
class ServersController extends Controller
|
||||
@@ -60,9 +63,9 @@ class ServersController extends Controller
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\ContainerRebuildService
|
||||
* @var \Pterodactyl\Repositories\Wings\DaemonServerRepository
|
||||
*/
|
||||
protected $containerRebuildService;
|
||||
private $daemonServerRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface
|
||||
@@ -95,20 +98,15 @@ class ServersController extends Controller
|
||||
protected $detailsModificationService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\LocationRepositoryInterface
|
||||
* @var \Pterodactyl\Repositories\Eloquent\MountRepository
|
||||
*/
|
||||
protected $locationRepository;
|
||||
protected $mountRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\NestRepositoryInterface
|
||||
*/
|
||||
protected $nestRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\NodeRepositoryInterface
|
||||
*/
|
||||
protected $nodeRepository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\ReinstallServerService
|
||||
*/
|
||||
@@ -120,9 +118,9 @@ class ServersController extends Controller
|
||||
protected $repository;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\ServerCreationService
|
||||
* @var \Pterodactyl\Services\Servers\ServerConfigurationStructureService
|
||||
*/
|
||||
protected $service;
|
||||
private $serverConfigurationStructureService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\StartupModificationService
|
||||
@@ -141,19 +139,18 @@ class ServersController extends Controller
|
||||
* @param \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface $allocationRepository
|
||||
* @param \Pterodactyl\Services\Servers\BuildModificationService $buildModificationService
|
||||
* @param \Illuminate\Contracts\Config\Repository $config
|
||||
* @param \Pterodactyl\Services\Servers\ContainerRebuildService $containerRebuildService
|
||||
* @param \Pterodactyl\Services\Servers\ServerCreationService $service
|
||||
* @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonServerRepository
|
||||
* @param \Pterodactyl\Services\Databases\DatabaseManagementService $databaseManagementService
|
||||
* @param \Pterodactyl\Services\Databases\DatabasePasswordService $databasePasswordService
|
||||
* @param \Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface $databaseRepository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\DatabaseHostRepository $databaseHostRepository
|
||||
* @param \Pterodactyl\Services\Servers\ServerDeletionService $deletionService
|
||||
* @param \Pterodactyl\Services\Servers\DetailsModificationService $detailsModificationService
|
||||
* @param \Pterodactyl\Contracts\Repository\LocationRepositoryInterface $locationRepository
|
||||
* @param \Pterodactyl\Contracts\Repository\NodeRepositoryInterface $nodeRepository
|
||||
* @param \Pterodactyl\Services\Servers\ReinstallServerService $reinstallService
|
||||
* @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository
|
||||
* @param \Pterodactyl\Repositories\Eloquent\MountRepository $mountRepository
|
||||
* @param \Pterodactyl\Contracts\Repository\NestRepositoryInterface $nestRepository
|
||||
* @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $serverConfigurationStructureService
|
||||
* @param \Pterodactyl\Services\Servers\StartupModificationService $startupModificationService
|
||||
* @param \Pterodactyl\Services\Servers\SuspensionService $suspensionService
|
||||
*/
|
||||
@@ -162,19 +159,18 @@ class ServersController extends Controller
|
||||
AllocationRepositoryInterface $allocationRepository,
|
||||
BuildModificationService $buildModificationService,
|
||||
ConfigRepository $config,
|
||||
ContainerRebuildService $containerRebuildService,
|
||||
ServerCreationService $service,
|
||||
DaemonServerRepository $daemonServerRepository,
|
||||
DatabaseManagementService $databaseManagementService,
|
||||
DatabasePasswordService $databasePasswordService,
|
||||
DatabaseRepositoryInterface $databaseRepository,
|
||||
DatabaseHostRepository $databaseHostRepository,
|
||||
ServerDeletionService $deletionService,
|
||||
DetailsModificationService $detailsModificationService,
|
||||
LocationRepositoryInterface $locationRepository,
|
||||
NodeRepositoryInterface $nodeRepository,
|
||||
ReinstallServerService $reinstallService,
|
||||
ServerRepositoryInterface $repository,
|
||||
MountRepository $mountRepository,
|
||||
NestRepositoryInterface $nestRepository,
|
||||
ServerConfigurationStructureService $serverConfigurationStructureService,
|
||||
StartupModificationService $startupModificationService,
|
||||
SuspensionService $suspensionService
|
||||
) {
|
||||
@@ -182,223 +178,22 @@ class ServersController extends Controller
|
||||
$this->allocationRepository = $allocationRepository;
|
||||
$this->buildModificationService = $buildModificationService;
|
||||
$this->config = $config;
|
||||
$this->containerRebuildService = $containerRebuildService;
|
||||
$this->daemonServerRepository = $daemonServerRepository;
|
||||
$this->databaseHostRepository = $databaseHostRepository;
|
||||
$this->databaseManagementService = $databaseManagementService;
|
||||
$this->databasePasswordService = $databasePasswordService;
|
||||
$this->databaseRepository = $databaseRepository;
|
||||
$this->detailsModificationService = $detailsModificationService;
|
||||
$this->deletionService = $deletionService;
|
||||
$this->locationRepository = $locationRepository;
|
||||
$this->nestRepository = $nestRepository;
|
||||
$this->nodeRepository = $nodeRepository;
|
||||
$this->reinstallService = $reinstallService;
|
||||
$this->repository = $repository;
|
||||
$this->service = $service;
|
||||
$this->mountRepository = $mountRepository;
|
||||
$this->serverConfigurationStructureService = $serverConfigurationStructureService;
|
||||
$this->startupModificationService = $startupModificationService;
|
||||
$this->suspensionService = $suspensionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the index page with all servers currently on the system.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
return view('admin.servers.index', [
|
||||
'servers' => $this->repository->setSearchTerm($request->input('query'))->getAllServers(
|
||||
$this->config->get('pterodactyl.paginate.admin.servers')
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display create new server page.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$nodes = $this->nodeRepository->all();
|
||||
if (count($nodes) < 1) {
|
||||
$this->alert->warning(trans('admin/server.alerts.node_required'))->flash();
|
||||
|
||||
return redirect()->route('admin.nodes');
|
||||
}
|
||||
|
||||
$nests = $this->nestRepository->getWithEggs();
|
||||
|
||||
Javascript::put([
|
||||
'nodeData' => $this->nodeRepository->getNodesForServerCreation(),
|
||||
'nests' => $nests->map(function ($item) {
|
||||
return array_merge($item->toArray(), [
|
||||
'eggs' => $item->eggs->keyBy('id')->toArray(),
|
||||
]);
|
||||
})->keyBy('id'),
|
||||
]);
|
||||
|
||||
return view('admin.servers.new', [
|
||||
'locations' => $this->locationRepository->all(),
|
||||
'nests' => $nests,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle POST of server creation form.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\ServerFormRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableAllocationException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableNodeException
|
||||
*/
|
||||
public function store(ServerFormRequest $request)
|
||||
{
|
||||
$server = $this->service->handle($request->except('_token'));
|
||||
$this->alert->success(trans('admin/server.alerts.server_created'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the index when viewing a specific server.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function viewIndex(Server $server)
|
||||
{
|
||||
return view('admin.servers.view.index', ['server' => $server]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the details page when viewing a specific server.
|
||||
*
|
||||
* @param int $server
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function viewDetails($server)
|
||||
{
|
||||
return view('admin.servers.view.details', [
|
||||
'server' => $this->repository->findFirstWhere([
|
||||
['id', '=', $server],
|
||||
['installed', '=', 1],
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the build details page when viewing a specific server.
|
||||
*
|
||||
* @param int $server
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function viewBuild($server)
|
||||
{
|
||||
$server = $this->repository->findFirstWhere([
|
||||
['id', '=', $server],
|
||||
['installed', '=', 1],
|
||||
]);
|
||||
|
||||
$allocations = $this->allocationRepository->getAllocationsForNode($server->node_id);
|
||||
|
||||
return view('admin.servers.view.build', [
|
||||
'server' => $server,
|
||||
'assigned' => $allocations->where('server_id', $server->id)->sortBy('port')->sortBy('ip'),
|
||||
'unassigned' => $allocations->where('server_id', null)->sortBy('port')->sortBy('ip'),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display startup configuration page for a server.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function viewStartup(Server $server)
|
||||
{
|
||||
$parameters = $this->repository->getVariablesWithValues($server->id, true);
|
||||
if (! $parameters->server->installed) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$nests = $this->nestRepository->getWithEggs();
|
||||
|
||||
Javascript::put([
|
||||
'server' => $server,
|
||||
'nests' => $nests->map(function ($item) {
|
||||
return array_merge($item->toArray(), [
|
||||
'eggs' => $item->eggs->keyBy('id')->toArray(),
|
||||
]);
|
||||
})->keyBy('id'),
|
||||
'server_variables' => $parameters->data,
|
||||
]);
|
||||
|
||||
return view('admin.servers.view.startup', [
|
||||
'server' => $parameters->server,
|
||||
'nests' => $nests,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the database management page for a specific server.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function viewDatabase(Server $server)
|
||||
{
|
||||
$this->repository->loadDatabaseRelations($server);
|
||||
|
||||
return view('admin.servers.view.database', [
|
||||
'hosts' => $this->databaseHostRepository->all(),
|
||||
'server' => $server,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the management page when viewing a specific server.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\View\View
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
*/
|
||||
public function viewManage(Server $server)
|
||||
{
|
||||
if ($server->installed > 1) {
|
||||
throw new DisplayException('This server is in a failed installation state and must be deleted and recreated.');
|
||||
}
|
||||
|
||||
return view('admin.servers.view.manage', ['server' => $server]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the deletion page for a server.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function viewDelete(Server $server)
|
||||
{
|
||||
return view('admin.servers.view.delete', ['server' => $server]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the details for a server.
|
||||
*
|
||||
@@ -406,7 +201,6 @@ class ServersController extends Controller
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
@@ -447,7 +241,7 @@ class ServersController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Reinstalls the server with the currently assigned pack and service.
|
||||
* Reinstalls the server with the currently assigned service.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
@@ -458,27 +252,12 @@ class ServersController extends Controller
|
||||
*/
|
||||
public function reinstallServer(Server $server)
|
||||
{
|
||||
$this->reinstallService->reinstall($server);
|
||||
$this->reinstallService->handle($server);
|
||||
$this->alert->success(trans('admin/server.alerts.server_reinstalled'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.manage', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup a server to have a container rebuild.
|
||||
*
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function rebuildContainer(Server $server)
|
||||
{
|
||||
$this->containerRebuildService->handle($server);
|
||||
$this->alert->success(trans('admin/server.alerts.rebuild_on_boot'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.manage', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the suspension status for a server.
|
||||
*
|
||||
@@ -508,16 +287,21 @@ class ServersController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
*/
|
||||
public function updateBuild(Request $request, Server $server)
|
||||
{
|
||||
try {
|
||||
$this->buildModificationService->handle($server, $request->only([
|
||||
'allocation_id', 'add_allocations', 'remove_allocations',
|
||||
'memory', 'swap', 'io', 'cpu', 'disk',
|
||||
'database_limit', 'allocation_limit', 'oom_disabled',
|
||||
'memory', 'swap', 'io', 'cpu', 'threads', 'disk',
|
||||
'database_limit', 'allocation_limit', 'backup_limit', 'oom_disabled',
|
||||
]));
|
||||
} catch (DataValidationException $exception) {
|
||||
throw new ValidationException($exception->validator);
|
||||
}
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.build_updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.build', $server->id);
|
||||
@@ -531,7 +315,7 @@ class ServersController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function delete(Request $request, Server $server)
|
||||
{
|
||||
@@ -549,14 +333,18 @@ class ServersController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function saveStartup(Request $request, Server $server)
|
||||
{
|
||||
$this->startupModificationService->setUserLevel(User::USER_LEVEL_ADMIN);
|
||||
$this->startupModificationService->handle($server, $request->except('_token'));
|
||||
try {
|
||||
$this->startupModificationService
|
||||
->setUserLevel(User::USER_LEVEL_ADMIN)
|
||||
->handle($server, $request->except('_token'));
|
||||
} catch (DataValidationException $exception) {
|
||||
throw new ValidationException($exception->validator);
|
||||
}
|
||||
|
||||
$this->alert->success(trans('admin/server.alerts.startup_changed'))->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.startup', $server->id);
|
||||
@@ -566,20 +354,21 @@ class ServersController extends Controller
|
||||
* Creates a new database assigned to a specific server.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Admin\Servers\Databases\StoreServerDatabaseRequest $request
|
||||
* @param int $server
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function newDatabase(StoreServerDatabaseRequest $request, $server)
|
||||
public function newDatabase(StoreServerDatabaseRequest $request, Server $server)
|
||||
{
|
||||
$this->databaseManagementService->create($server, [
|
||||
'database' => $request->input('database'),
|
||||
'database' => DatabaseManagementService::generateUniqueDatabaseName($request->input('database'), $server->id),
|
||||
'remote' => $request->input('remote'),
|
||||
'database_host_id' => $request->input('database_host_id'),
|
||||
'max_connections' => $request->input('max_connections'),
|
||||
]);
|
||||
|
||||
return redirect()->route('admin.servers.view.database', $server)->withInput();
|
||||
return redirect()->route('admin.servers.view.database', $server->id)->withInput();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -620,8 +409,72 @@ class ServersController extends Controller
|
||||
['id', '=', $database],
|
||||
]);
|
||||
|
||||
$this->databaseManagementService->delete($database->id);
|
||||
$this->databaseManagementService->delete($database);
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a mount to a server.
|
||||
*
|
||||
* @param Server $server
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function addMount(Server $server, Mount $mount)
|
||||
{
|
||||
$server->mounts()->updateOrCreate([
|
||||
'mount_id' => $mount->id,
|
||||
'server_id' => $server->id,
|
||||
]);
|
||||
|
||||
$data = $this->serverConfigurationStructureService->handle($server);
|
||||
|
||||
try {
|
||||
$this->daemonServerRepository
|
||||
->setServer($server)
|
||||
->update(Arr::only($data, ['mounts']));
|
||||
} catch (RequestException $exception) {
|
||||
throw new DaemonConnectionException($exception);
|
||||
}
|
||||
|
||||
$this->alert->success('Mount was added successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.mounts', $server->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a mount from a server.
|
||||
*
|
||||
* @param Server $server
|
||||
* @param \Pterodactyl\Models\Mount $mount
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function deleteMount(Server $server, Mount $mount)
|
||||
{
|
||||
$server->mounts()
|
||||
->where('mount_id', $mount->id)
|
||||
->where('server_id', $server->id)
|
||||
->delete();
|
||||
|
||||
$data = $this->serverConfigurationStructureService->handle($server);
|
||||
|
||||
try {
|
||||
$this->daemonServerRepository
|
||||
->setServer($server)
|
||||
->update(Arr::only($data, ['mounts']));
|
||||
} catch (RequestException $exception) {
|
||||
throw new DaemonConnectionException($exception);
|
||||
}
|
||||
|
||||
$this->alert->success('Mount was removed successfully.')->flash();
|
||||
|
||||
return redirect()->route('admin.servers.view.mounts', $server->id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ use Pterodactyl\Contracts\Repository\NodeRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\UserRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
||||
|
||||
class StatisticsController extends Controller
|
||||
@@ -45,6 +46,7 @@ class StatisticsController extends Controller
|
||||
|
||||
public function index()
|
||||
{
|
||||
throw new NotFoundHttpException;
|
||||
$servers = $this->serverRepository->all();
|
||||
$nodes = $this->nodeRepository->all();
|
||||
$usersCount = $this->userRepository->count();
|
||||
@@ -67,7 +69,7 @@ class StatisticsController extends Controller
|
||||
|
||||
$tokens = [];
|
||||
foreach ($nodes as $node) {
|
||||
$tokens[$node->id] = $node->daemonSecret;
|
||||
$tokens[$node->id] = decrypt($node->daemon_token);
|
||||
}
|
||||
|
||||
$this->injectJavascript([
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Pterodactyl\Http\Controllers\Admin;
|
||||
use Illuminate\Http\Request;
|
||||
use Pterodactyl\Models\User;
|
||||
use Prologue\Alerts\AlertsMessageBag;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Exceptions\DisplayException;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Illuminate\Contracts\Translation\Translator;
|
||||
@@ -83,7 +84,17 @@ class UserController extends Controller
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$users = $this->repository->setSearchTerm($request->input('query'))->getAllUsersWithCounts();
|
||||
$users = QueryBuilder::for(
|
||||
User::query()->select('users.*')
|
||||
->selectRaw('COUNT(DISTINCT(subusers.id)) as subuser_of_count')
|
||||
->selectRaw('COUNT(DISTINCT(servers.id)) as servers_count')
|
||||
->leftJoin('subusers', 'subusers.user_id', '=', 'users.id')
|
||||
->leftJoin('servers', 'servers.owner_id', '=', 'users.id')
|
||||
->groupBy('users.id')
|
||||
)
|
||||
->allowedFilters(['username', 'email', 'uuid'])
|
||||
->allowedSorts(['id', 'uuid'])
|
||||
->paginate(50);
|
||||
|
||||
return view('admin.users.index', ['users' => $users]);
|
||||
}
|
||||
@@ -147,7 +158,7 @@ class UserController extends Controller
|
||||
public function store(UserFormRequest $request)
|
||||
{
|
||||
$user = $this->creationService->handle($request->normalize());
|
||||
$this->alert->success($this->translator->trans('admin/user.notices.account_created'))->flash();
|
||||
$this->alert->success($this->translator->get('admin/user.notices.account_created'))->flash();
|
||||
|
||||
return redirect()->route('admin.users.view', $user->id);
|
||||
}
|
||||
@@ -164,27 +175,11 @@ class UserController extends Controller
|
||||
*/
|
||||
public function update(UserFormRequest $request, User $user)
|
||||
{
|
||||
$this->updateService->setUserLevel(User::USER_LEVEL_ADMIN);
|
||||
$data = $this->updateService->handle($user, $request->normalize());
|
||||
$this->updateService
|
||||
->setUserLevel(User::USER_LEVEL_ADMIN)
|
||||
->handle($user, $request->normalize());
|
||||
|
||||
if (! empty($data->get('exceptions'))) {
|
||||
foreach ($data->get('exceptions') as $node => $exception) {
|
||||
/** @var \GuzzleHttp\Exception\RequestException $exception */
|
||||
/** @var \GuzzleHttp\Psr7\Response|null $response */
|
||||
$response = method_exists($exception, 'getResponse') ? $exception->getResponse() : null;
|
||||
$message = trans('admin/server.exceptions.daemon_exception', [
|
||||
'code' => is_null($response) ? 'E_CONN_REFUSED' : $response->getStatusCode(),
|
||||
]);
|
||||
|
||||
$this->alert->danger(trans('exceptions.users.node_revocation_failed', [
|
||||
'node' => $node,
|
||||
'error' => $message,
|
||||
'link' => route('admin.nodes.view', $node),
|
||||
]))->flash();
|
||||
}
|
||||
}
|
||||
|
||||
$this->alert->success($this->translator->trans('admin/user.notices.account_updated'))->flash();
|
||||
$this->alert->success(trans('admin/user.notices.account_updated'))->flash();
|
||||
|
||||
return redirect()->route('admin.users.view', $user->id);
|
||||
}
|
||||
@@ -193,10 +188,24 @@ class UserController extends Controller
|
||||
* Get a JSON response of users on the system.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Database\Eloquent\Collection
|
||||
* @return \Illuminate\Support\Collection|\Pterodactyl\Models\Model
|
||||
*/
|
||||
public function json(Request $request)
|
||||
{
|
||||
return $this->repository->filterUsersByQuery($request->input('q'));
|
||||
$users = QueryBuilder::for(User::query())->allowedFilters(['email'])->paginate(25);
|
||||
|
||||
// Handle single user requests.
|
||||
if ($request->query('user_id')) {
|
||||
$user = User::query()->findOrFail($request->input('user_id'));
|
||||
$user->md5 = md5(strtolower($user->email));
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
return $users->map(function ($item) {
|
||||
$item->md5 = md5(strtolower($item->email));
|
||||
|
||||
return $item;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Pterodactyl\Http\Controllers\Api\Application;
|
||||
use Illuminate\Http\Request;
|
||||
use Webmozart\Assert\Assert;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Container\Container;
|
||||
use Pterodactyl\Http\Controllers\Controller;
|
||||
use Pterodactyl\Extensions\Spatie\Fractalistic\Fractal;
|
||||
@@ -30,7 +31,10 @@ abstract class ApplicationApiController extends Controller
|
||||
Container::getInstance()->call([$this, 'loadDependencies']);
|
||||
|
||||
// Parse all of the includes to use on this request.
|
||||
$includes = collect(explode(',', $this->request->input('include', '')))->map(function ($value) {
|
||||
$input = $this->request->input('include', []);
|
||||
$input = is_array($input) ? $input : explode(',', $input);
|
||||
|
||||
$includes = (new Collection($input))->map(function ($value) {
|
||||
return trim($value);
|
||||
})->filter()->toArray();
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Pterodactyl\Http\Controllers\Api\Application\Locations;
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Location;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Services\Locations\LocationUpdateService;
|
||||
use Pterodactyl\Services\Locations\LocationCreationService;
|
||||
use Pterodactyl\Services\Locations\LocationDeletionService;
|
||||
@@ -69,7 +70,10 @@ class LocationController extends ApplicationApiController
|
||||
*/
|
||||
public function index(GetLocationsRequest $request): array
|
||||
{
|
||||
$locations = $this->repository->setSearchTerm($request->input('search'))->paginated(50);
|
||||
$locations = QueryBuilder::for(Location::query())
|
||||
->allowedFilters(['short', 'long'])
|
||||
->allowedSorts(['id'])
|
||||
->paginate(100);
|
||||
|
||||
return $this->fractal->collection($locations)
|
||||
->transformWith($this->getTransformer(LocationTransformer::class))
|
||||
|
||||
@@ -3,11 +3,10 @@
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Nodes;
|
||||
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Models\Allocation;
|
||||
use Pterodactyl\Services\Allocations\AssignmentService;
|
||||
use Pterodactyl\Services\Allocations\AllocationDeletionService;
|
||||
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
|
||||
use Pterodactyl\Transformers\Api\Application\AllocationTransformer;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Allocations\GetAllocationsRequest;
|
||||
@@ -26,41 +25,32 @@ class AllocationController extends ApplicationApiController
|
||||
*/
|
||||
private $deletionService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* AllocationController constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Services\Allocations\AssignmentService $assignmentService
|
||||
* @param \Pterodactyl\Services\Allocations\AllocationDeletionService $deletionService
|
||||
* @param \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface $repository
|
||||
*/
|
||||
public function __construct(
|
||||
AssignmentService $assignmentService,
|
||||
AllocationDeletionService $deletionService,
|
||||
AllocationRepositoryInterface $repository
|
||||
AllocationDeletionService $deletionService
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->assignmentService = $assignmentService;
|
||||
$this->deletionService = $deletionService;
|
||||
$this->repository = $repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all of the allocations that exist for a given node.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Allocations\GetAllocationsRequest $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return array
|
||||
*/
|
||||
public function index(GetAllocationsRequest $request): array
|
||||
public function index(GetAllocationsRequest $request, Node $node): array
|
||||
{
|
||||
$allocations = $this->repository->getPaginatedAllocationsForNode(
|
||||
$request->getModel(Node::class)->id, 50
|
||||
);
|
||||
$allocations = $node->allocations()->paginate(50);
|
||||
|
||||
return $this->fractal->collection($allocations)
|
||||
->transformWith($this->getTransformer(AllocationTransformer::class))
|
||||
@@ -71,32 +61,35 @@ class AllocationController extends ApplicationApiController
|
||||
* Store new allocations for a given node.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Allocations\StoreAllocationRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\TooManyPortsInRangeException
|
||||
*/
|
||||
public function store(StoreAllocationRequest $request): Response
|
||||
public function store(StoreAllocationRequest $request, Node $node): JsonResponse
|
||||
{
|
||||
$this->assignmentService->handle($request->getModel(Node::class), $request->validated());
|
||||
$this->assignmentService->handle($node, $request->validated());
|
||||
|
||||
return response('', 204);
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a specific allocation from the Panel.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Allocations\DeleteAllocationRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @param \Pterodactyl\Models\Allocation $allocation
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException
|
||||
*/
|
||||
public function delete(DeleteAllocationRequest $request): Response
|
||||
public function delete(DeleteAllocationRequest $request, Node $node, Allocation $allocation): JsonResponse
|
||||
{
|
||||
$this->deletionService->handle($request->getModel(Allocation::class));
|
||||
$this->deletionService->handle($allocation);
|
||||
|
||||
return response('', 204);
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Nodes;
|
||||
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Nodes\GetNodeRequest;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
class NodeConfigurationController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* Returns the configuration information for a node. This allows for automated deployments
|
||||
* to remote machines so long as an API key is provided to the machine to make the request
|
||||
* with, and the node is known.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Nodes\GetNodeRequest $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function __invoke(GetNodeRequest $request, Node $node)
|
||||
{
|
||||
return JsonResponse::create($node->getConfiguration());
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@
|
||||
namespace Pterodactyl\Http\Controllers\Api\Application\Nodes;
|
||||
|
||||
use Pterodactyl\Models\Node;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Services\Nodes\NodeUpdateService;
|
||||
use Pterodactyl\Services\Nodes\NodeCreationService;
|
||||
use Pterodactyl\Services\Nodes\NodeDeletionService;
|
||||
@@ -69,7 +69,10 @@ class NodeController extends ApplicationApiController
|
||||
*/
|
||||
public function index(GetNodesRequest $request): array
|
||||
{
|
||||
$nodes = $this->repository->setSearchTerm($request->input('search'))->paginated(50);
|
||||
$nodes = QueryBuilder::for(Node::query())
|
||||
->allowedFilters(['uuid', 'name', 'fqdn', 'daemon_token_id'])
|
||||
->allowedSorts(['id', 'uuid', 'memory', 'disk'])
|
||||
->paginate(100);
|
||||
|
||||
return $this->fractal->collection($nodes)
|
||||
->transformWith($this->getTransformer(NodeTransformer::class))
|
||||
@@ -80,11 +83,12 @@ class NodeController extends ApplicationApiController
|
||||
* Return data for a single instance of a node.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Nodes\GetNodeRequest $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return array
|
||||
*/
|
||||
public function view(GetNodeRequest $request): array
|
||||
public function view(GetNodeRequest $request, Node $node): array
|
||||
{
|
||||
return $this->fractal->item($request->getModel(Node::class))
|
||||
return $this->fractal->item($node)
|
||||
->transformWith($this->getTransformer(NodeTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
@@ -116,16 +120,15 @@ class NodeController extends ApplicationApiController
|
||||
* Update an existing node on the Panel.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Nodes\UpdateNodeRequest $request
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return array
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function update(UpdateNodeRequest $request): array
|
||||
public function update(UpdateNodeRequest $request, Node $node): array
|
||||
{
|
||||
$node = $this->updateService->handle(
|
||||
$request->getModel(Node::class), $request->validated(), $request->input('reset_secret') === true
|
||||
$node, $request->validated(), $request->input('reset_secret') === true
|
||||
);
|
||||
|
||||
return $this->fractal->item($node)
|
||||
@@ -138,14 +141,15 @@ class NodeController extends ApplicationApiController
|
||||
* currently attached to it.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Nodes\DeleteNodeRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \Pterodactyl\Models\Node $node
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Service\HasActiveServersException
|
||||
*/
|
||||
public function delete(DeleteNodeRequest $request): Response
|
||||
public function delete(DeleteNodeRequest $request, Node $node): JsonResponse
|
||||
{
|
||||
$this->deletionService->handle($request->getModel(Node::class));
|
||||
$this->deletionService->handle($node);
|
||||
|
||||
return response('', 204);
|
||||
return new JsonResponse([], JsonResponse::HTTP_NO_CONTENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,13 +57,12 @@ class DatabaseController extends ApplicationApiController
|
||||
* server.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\Databases\GetServerDatabasesRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return array
|
||||
*/
|
||||
public function index(GetServerDatabasesRequest $request): array
|
||||
public function index(GetServerDatabasesRequest $request, Server $server): array
|
||||
{
|
||||
$databases = $this->repository->getDatabasesForServer($request->getModel(Server::class)->id);
|
||||
|
||||
return $this->fractal->collection($databases)
|
||||
return $this->fractal->collection($server->databases)
|
||||
->transformWith($this->getTransformer(ServerDatabaseTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
@@ -72,11 +71,13 @@ class DatabaseController extends ApplicationApiController
|
||||
* Return a single server database.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\Databases\GetServerDatabaseRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @param \Pterodactyl\Models\Database $database
|
||||
* @return array
|
||||
*/
|
||||
public function view(GetServerDatabaseRequest $request): array
|
||||
public function view(GetServerDatabaseRequest $request, Server $server, Database $database): array
|
||||
{
|
||||
return $this->fractal->item($request->getModel(Database::class))
|
||||
return $this->fractal->item($database)
|
||||
->transformWith($this->getTransformer(ServerDatabaseTransformer::class))
|
||||
->toArray();
|
||||
}
|
||||
@@ -85,29 +86,33 @@ class DatabaseController extends ApplicationApiController
|
||||
* Reset the password for a specific server database.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\Databases\ServerDatabaseWriteRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @param \Pterodactyl\Models\Database $database
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function resetPassword(ServerDatabaseWriteRequest $request): Response
|
||||
public function resetPassword(ServerDatabaseWriteRequest $request, Server $server, Database $database): JsonResponse
|
||||
{
|
||||
$this->databasePasswordService->handle($request->getModel(Database::class));
|
||||
$this->databasePasswordService->handle($database);
|
||||
|
||||
return response('', 204);
|
||||
return JsonResponse::create([], JsonResponse::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new database on the Panel for a given server.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\Databases\StoreServerDatabaseRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function store(StoreServerDatabaseRequest $request): JsonResponse
|
||||
public function store(StoreServerDatabaseRequest $request, Server $server): JsonResponse
|
||||
{
|
||||
$server = $request->getModel(Server::class);
|
||||
$database = $this->databaseManagementService->create($server->id, $request->validated());
|
||||
$database = $this->databaseManagementService->create($server, array_merge($request->validated(), [
|
||||
'database' => $request->databaseName(),
|
||||
]));
|
||||
|
||||
return $this->fractal->item($database)
|
||||
->transformWith($this->getTransformer(ServerDatabaseTransformer::class))
|
||||
@@ -117,7 +122,7 @@ class DatabaseController extends ApplicationApiController
|
||||
'database' => $database->id,
|
||||
]),
|
||||
])
|
||||
->respond(201);
|
||||
->respond(Response::HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +135,7 @@ class DatabaseController extends ApplicationApiController
|
||||
*/
|
||||
public function delete(ServerDatabaseWriteRequest $request): Response
|
||||
{
|
||||
$this->databaseManagementService->delete($request->getModel(Database::class)->id);
|
||||
$this->databaseManagementService->delete($request->getModel(Database::class));
|
||||
|
||||
return response('', 204);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Pterodactyl\Http\Controllers\Api\Application\Servers;
|
||||
use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Pterodactyl\Services\Servers\ServerCreationService;
|
||||
use Pterodactyl\Services\Servers\ServerDeletionService;
|
||||
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
|
||||
@@ -59,7 +60,10 @@ class ServerController extends ApplicationApiController
|
||||
*/
|
||||
public function index(GetServersRequest $request): array
|
||||
{
|
||||
$servers = $this->repository->setSearchTerm($request->input('search'))->paginated(50);
|
||||
$servers = QueryBuilder::for(Server::query())
|
||||
->allowedFilters(['uuid', 'name', 'image', 'external_id'])
|
||||
->allowedSorts(['id', 'uuid'])
|
||||
->paginate(100);
|
||||
|
||||
return $this->fractal->collection($servers)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
@@ -72,9 +76,9 @@ class ServerController extends ApplicationApiController
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\StoreServerRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*
|
||||
* @throws \Throwable
|
||||
* @throws \Illuminate\Validation\ValidationException
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Pterodactyl\Exceptions\Service\Deployment\NoViableAllocationException
|
||||
|
||||
@@ -63,15 +63,16 @@ class ServerDetailsController extends ApplicationApiController
|
||||
* Update the build details for a specific server.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\UpdateServerBuildConfigurationRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return array
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function build(UpdateServerBuildConfigurationRequest $request): array
|
||||
public function build(UpdateServerBuildConfigurationRequest $request, Server $server): array
|
||||
{
|
||||
$server = $this->buildModificationService->handle($request->getModel(Server::class), $request->validated());
|
||||
$server = $this->buildModificationService->handle($server, $request->validated());
|
||||
|
||||
return $this->fractal->item($server)
|
||||
->transformWith($this->getTransformer(ServerTransformer::class))
|
||||
|
||||
@@ -6,17 +6,11 @@ use Illuminate\Http\Response;
|
||||
use Pterodactyl\Models\Server;
|
||||
use Pterodactyl\Services\Servers\SuspensionService;
|
||||
use Pterodactyl\Services\Servers\ReinstallServerService;
|
||||
use Pterodactyl\Services\Servers\ContainerRebuildService;
|
||||
use Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest;
|
||||
use Pterodactyl\Http\Controllers\Api\Application\ApplicationApiController;
|
||||
|
||||
class ServerManagementController extends ApplicationApiController
|
||||
{
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\ContainerRebuildService
|
||||
*/
|
||||
private $rebuildService;
|
||||
|
||||
/**
|
||||
* @var \Pterodactyl\Services\Servers\ReinstallServerService
|
||||
*/
|
||||
@@ -30,18 +24,15 @@ class ServerManagementController extends ApplicationApiController
|
||||
/**
|
||||
* SuspensionController constructor.
|
||||
*
|
||||
* @param \Pterodactyl\Services\Servers\ContainerRebuildService $rebuildService
|
||||
* @param \Pterodactyl\Services\Servers\ReinstallServerService $reinstallServerService
|
||||
* @param \Pterodactyl\Services\Servers\SuspensionService $suspensionService
|
||||
*/
|
||||
public function __construct(
|
||||
ContainerRebuildService $rebuildService,
|
||||
ReinstallServerService $reinstallServerService,
|
||||
SuspensionService $suspensionService
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->rebuildService = $rebuildService;
|
||||
$this->reinstallServerService = $reinstallServerService;
|
||||
$this->suspensionService = $suspensionService;
|
||||
}
|
||||
@@ -50,15 +41,14 @@ class ServerManagementController extends ApplicationApiController
|
||||
* Suspend a server on the Panel.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function suspend(ServerWriteRequest $request): Response
|
||||
public function suspend(ServerWriteRequest $request, Server $server): Response
|
||||
{
|
||||
$this->suspensionService->toggle($request->getModel(Server::class), SuspensionService::ACTION_SUSPEND);
|
||||
$this->suspensionService->toggle($server, SuspensionService::ACTION_SUSPEND);
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
@@ -67,15 +57,14 @@ class ServerManagementController extends ApplicationApiController
|
||||
* Unsuspend a server on the Panel.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
* @throws \Throwable
|
||||
*/
|
||||
public function unsuspend(ServerWriteRequest $request): Response
|
||||
public function unsuspend(ServerWriteRequest $request, Server $server): Response
|
||||
{
|
||||
$this->suspensionService->toggle($request->getModel(Server::class), SuspensionService::ACTION_UNSUSPEND);
|
||||
$this->suspensionService->toggle($server, SuspensionService::ACTION_UNSUSPEND);
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
@@ -84,30 +73,16 @@ class ServerManagementController extends ApplicationApiController
|
||||
* Mark a server as needing to be reinstalled.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
|
||||
* @param \Pterodactyl\Models\Server $server
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\DisplayException
|
||||
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
|
||||
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
|
||||
*/
|
||||
public function reinstall(ServerWriteRequest $request): Response
|
||||
public function reinstall(ServerWriteRequest $request, Server $server): Response
|
||||
{
|
||||
$this->reinstallServerService->reinstall($request->getModel(Server::class));
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a server as needing its container rebuilt the next time it is started.
|
||||
*
|
||||
* @param \Pterodactyl\Http\Requests\Api\Application\Servers\ServerWriteRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*
|
||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||
*/
|
||||
public function rebuild(ServerWriteRequest $request): Response
|
||||
{
|
||||
$this->rebuildService->handle($request->getModel(Server::class));
|
||||
$this->reinstallServerService->handle($server);
|
||||
|
||||
return $this->returnNoContent();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user