Merge branch 'develop' into v2

This commit is contained in:
Matthew Penner 2022-01-08 15:20:23 -07:00
commit d1c9af8f04
No known key found for this signature in database
GPG key ID: 31311906AD4CF6D6
35 changed files with 304 additions and 98 deletions

View file

@ -8,6 +8,7 @@ APP_DELETE_MINUTES=10
APP_ENVIRONMENT_ONLY=true
LOG_CHANNEL=daily
APP_LOCALE=en
APP_URL=http://panel.example.com
DB_HOST=127.0.0.1
DB_PORT=3306
@ -30,7 +31,7 @@ MAILGUN_ENDPOINT=api.mailgun.net
# mail servers such as Gmail to reject your mail.
#
# @see: https://github.com/pterodactyl/panel/pull/3110
# SERVER_NAME=panel.yourdomain.com
# SERVER_NAME=panel.example.com
QUEUE_HIGH=high
QUEUE_STANDARD=standard

View file

@ -33,7 +33,7 @@ Note: If your `APP_URL` starts with `https://` you need to provide an `LETSENCRY
| ------------------- | ------------------------------------------------------------------------------ | -------- |
| `APP_URL` | The URL the panel will be reachable with (including protocol) | yes |
| `APP_TIMEZONE` | The timezone to use for the panel | yes |
| `LETSENCRYPT_EMAIL` | The email used for letsencrypt certificate generation | yes |
| `LE_EMAIL` | The email used for letsencrypt certificate generation | yes |
| `DB_HOST` | The host of the mysql instance | yes |
| `DB_PORT` | The port of the mysql instance | yes |
| `DB_DATABASE` | The name of the mysql database | yes |

View file

@ -57,7 +57,7 @@ fi
## check for DB up before starting the panel
echo "Checking database status."
until nc -z -v -w30 $DB_HOST 3306
until nc -z -v -w30 $DB_HOST $DB_PORT
do
echo "Waiting for database connection..."
# wait for 1 seconds before check again

View file

@ -36,6 +36,7 @@ jobs:
if: "!contains(github.ref, 'develop')"
with:
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
- name: Release Development Build
@ -43,5 +44,6 @@ jobs:
if: "contains(github.ref, 'develop')"
with:
push: ${{ github.event_name != 'pull_request' }}
platforms: linux/amd64,linux/arm64
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}

View file

@ -3,6 +3,13 @@ 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.6.6
### Fixed
* **[security]** Fixes a CSRF vulnerability for both the administrative test email endpoint and node auto-deployment token generation endpoint. [GHSA-wwgq-9jhf-qgw6](https://github.com/pterodactyl/panel/security/advisories/GHSA-wwgq-9jhf-qgw6)
### Changed
* Updates Minecraft eggs to include latest Java 17 yolk by default.
## v1.6.5
### Fixed
* Fixes broken application API endpoints due to changes introduced with session management in 1.6.4.

View file

@ -2,7 +2,7 @@
# Build the assets that are needed for the frontend. This build stage is then discarded
# since we won't need NodeJS anymore in the future. This Docker image ships a final production
# level distribution of Pterodactyl.
FROM mhart/alpine-node:14
FROM --platform=$TARGETOS/$TARGETARCH mhart/alpine-node:14
WORKDIR /app
COPY . ./
RUN yarn install --frozen-lockfile \
@ -10,7 +10,7 @@ RUN yarn install --frozen-lockfile \
# Stage 1:
# Build the actual container with all of the needed PHP dependencies that will run the application.
FROM php:7.4-fpm-alpine
FROM --platform=$TARGETOS/$TARGETARCH php:7.4-fpm-alpine
WORKDIR /app
COPY . ./
COPY --from=0 /app/public/assets ./public/assets

View file

@ -1,7 +1,8 @@
# The MIT License (MIT)
```
Copyright (c) 2015 - 2021 Dane Everitt <dane@daneeveritt.com> and Contributors
Pterodactyl®
Copyright © Dane Everitt <dane@daneeveritt.com> and 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

View file

@ -6,7 +6,7 @@
![GitHub contributors](https://img.shields.io/github/contributors/pterodactyl/panel?style=for-the-badge)
# Pterodactyl Panel
Pterodactyl is an open-source game server management panel built with PHP 7, React, and Go. Designed with security
Pterodactyl® is a free, open-source game server management panel built with PHP, React, and Go. Designed with security
in mind, Pterodactyl runs all game servers in isolated Docker containers while exposing a beautiful and intuitive
UI to end users.
@ -14,6 +14,12 @@ Stop settling for less. Make game servers a first class citizen on your platform
![Image](https://cdn.pterodactyl.io/site-assets/pterodactyl_v1_demo.gif)
## 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)
## Sponsors
I would like to extend my sincere thanks to the following sponsors for helping fund Pterodactyl's developement.
[Interested in becoming a sponsor?](https://github.com/sponsors/DaneEveritt)
@ -37,16 +43,11 @@ I would like to extend my sincere thanks to the following sponsors for helping f
| [**Aussie Server Hosts**](https://aussieserverhosts.com/) | No frills Australian Owned and operated High Performance Server hosting for some of the most demanding games serving Australia and New Zealand. |
| [**VibeGAMES**](https://vibegames.net/) | VibeGAMES is a game server provider that specializes in DDOS protection for the games we offer. We have multiple locations in the US, Brazil, France, Germany, Singapore, Australia and South Africa.|
| [**RocketNode**](https://rocketnode.net) | RocketNode is a VPS and Game Server provider that offers the best performing VPS and Game hosting Solutions at affordable prices! |
## 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)
| [**HostEZ**](https://hostez.io) | Providing North America Valheim, Minecraft and other popular games with low latency, high uptime and maximum availability. EZ! |
### 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.
Pterodactyl supports a wide variety of games by utilizing Docker containers to isolate each instance. This gives
you the power to run game servers without bloating machines with a host of additional dependencies.
Some of our core supported games include:
@ -73,27 +74,6 @@ and there are plenty more games available provided by the community. Some of the
* [and many more...](https://github.com/parkervcp/eggs)
## License
```
Copyright (c) 2015 - 2021 Dane Everitt <dane@daneeveritt.com> and Contributors
Pterodactyl® Copyright © 2015 - 2022 Dane Everitt and 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
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
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.
Code released under the [MIT License](./LICENSE.md).

View file

@ -12,6 +12,7 @@ namespace Pterodactyl\Console\Commands\Environment;
use DateTimeZone;
use Illuminate\Console\Command;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Validation\Factory as ValidatorFactory;
use Pterodactyl\Traits\Commands\EnvironmentWriterTrait;
use Illuminate\Contracts\Config\Repository as ConfigRepository;
@ -78,12 +79,13 @@ class AppSettingsCommand extends Command
/**
* AppSettingsCommand constructor.
*/
public function __construct(ConfigRepository $config, Kernel $command)
public function __construct(ConfigRepository $config, Kernel $command, ValidatorFactory $validator)
{
parent::__construct();
$this->command = $command;
$this->config = $config;
$this->command = $command;
$this->validator = $validator;
}
/**
@ -103,6 +105,18 @@ class AppSettingsCommand extends Command
$this->config->get('pterodactyl.service.author', 'unknown@unknown.com')
);
$validator = $this->validator->make(
['email' => $this->variables['APP_SERVICE_AUTHOR']],
['email' => 'email']
);
if ($validator->fails()) {
foreach ($validator->errors()->all() as $error) {
$this->output->error($error);
}
return 1;
}
$this->output->comment(trans('command/messages.environment.app.app_url_help'));
$this->variables['APP_URL'] = $this->option('url') ?? $this->ask(
trans('command/messages.environment.app.app_url'),

View file

@ -4,7 +4,7 @@
"version": "PTDL_v1",
"update_url": null
},
"exported_at": "2021-07-04T19:18:34-04:00",
"exported_at": "2021-11-14T19:23:12+00:00",
"name": "Bungeecord",
"author": "support@pterodactyl.io",
"description": "For a long time, Minecraft server owners have had a dream that encompasses a free, easy, and reliable way to connect multiple Minecraft servers together. BungeeCord is the answer to said dream. Whether you are a small server wishing to string multiple game-modes together, or the owner of the ShotBow Network, BungeeCord is the ideal solution for you. With the help of BungeeCord, you will be able to unlock your community's full potential.",
@ -15,14 +15,15 @@
"images": [
"ghcr.io\/pterodactyl\/yolks:java_8",
"ghcr.io\/pterodactyl\/yolks:java_11",
"ghcr.io\/pterodactyl\/yolks:java_16"
"ghcr.io\/pterodactyl\/yolks:java_16",
"ghcr.io\/pterodactyl\/yolks:java_17"
],
"file_denylist": [],
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}",
"config": {
"files": "{\r\n \"config.yml\": {\r\n \"parser\": \"yaml\",\r\n \"find\": {\r\n \"listeners[0].query_port\": \"{{server.build.default.port}}\",\r\n \"listeners[0].host\": \"0.0.0.0:{{server.build.default.port}}\",\r\n \"servers.*.address\": {\r\n \"regex:^(127\\\\.0\\\\.0\\\\.1|localhost)(:\\\\d{1,5})?$\": \"{{config.docker.interface}}$2\"\r\n }\r\n }\r\n }\r\n}",
"startup": "{\r\n \"done\": \"Listening on \"\r\n}",
"logs": "{\r\n \"custom\": false,\r\n \"location\": \"proxy.log.0\"\r\n}",
"logs": "{}",
"stop": "end"
},
"scripts": {

File diff suppressed because one or more lines are too long

View file

@ -4,7 +4,7 @@
"version": "PTDL_v1",
"update_url": null
},
"exported_at": "2021-10-22T19:19:11+02:00",
"exported_at": "2021-11-14T19:21:07+00:00",
"name": "Paper",
"author": "parker@pterodactyl.io",
"description": "High performance Spigot fork that aims to fix gameplay and mechanics inconsistencies.",
@ -15,7 +15,8 @@
"images": [
"ghcr.io\/pterodactyl\/yolks:java_8",
"ghcr.io\/pterodactyl\/yolks:java_11",
"ghcr.io\/pterodactyl\/yolks:java_16"
"ghcr.io\/pterodactyl\/yolks:java_16",
"ghcr.io\/pterodactyl\/yolks:java_17"
],
"file_denylist": [],
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -Dterminal.jline=false -Dterminal.ansi=true -jar {{SERVER_JARFILE}}",

View file

@ -4,7 +4,7 @@
"version": "PTDL_v1",
"update_url": null
},
"exported_at": "2021-10-22T19:19:23+02:00",
"exported_at": "2021-11-14T19:18:30+00:00",
"name": "Vanilla Minecraft",
"author": "support@pterodactyl.io",
"description": "Minecraft is a game about placing blocks and going on adventures. Explore randomly generated worlds and build amazing things from the simplest of homes to the grandest of castles. Play in Creative Mode with unlimited resources or mine deep in Survival Mode, crafting weapons and armor to fend off dangerous mobs. Do all this alone or with friends.",
@ -15,14 +15,15 @@
"images": [
"ghcr.io\/pterodactyl\/yolks:java_8",
"ghcr.io\/pterodactyl\/yolks:java_11",
"ghcr.io\/pterodactyl\/yolks:java_16"
"ghcr.io\/pterodactyl\/yolks:java_16",
"ghcr.io\/pterodactyl\/yolks:java_17"
],
"file_denylist": [],
"startup": "java -Xms128M -Xmx{{SERVER_MEMORY}}M -jar {{SERVER_JARFILE}}",
"config": {
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.build.default.port}}\",\r\n \"query.port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
"startup": "{\r\n \"done\": \")! For help, type \"\r\n}",
"logs": "{\r\n \"custom\": false,\r\n \"location\": \"logs\/latest.log\"\r\n}",
"logs": "{}",
"stop": "stop"
},
"scripts": {

View file

@ -48,7 +48,7 @@
},
{
"name": "Server Map",
"description": "Available Maps: TheIsland, TheCenter, Ragnarok, ScorchedEarth_P, Aberration_P, Extinction, Valguero_P, Genesis, CrystalIsles, Gen2",
"description": "Available Maps: TheIsland, TheCenter, Ragnarok, ScorchedEarth_P, Aberration_P, Extinction, Valguero_P, Genesis, CrystalIsles, Gen2, LostIsland",
"env_variable": "SERVER_MAP",
"default_value": "TheIsland",
"user_viewable": true,
@ -119,4 +119,4 @@
"rules": "nullable|string"
}
]
}
}

View file

@ -4,11 +4,13 @@
"version": "PTDL_v1",
"update_url": null
},
"exported_at": "2021-06-05T16:19:30-04:00",
"exported_at": "2021-09-10T14:36:37-04:00",
"name": "Counter-Strike: Global Offensive",
"author": "support@pterodactyl.io",
"description": "Counter-Strike: Global Offensive is a multiplayer first-person shooter video game developed by Hidden Path Entertainment and Valve Corporation.",
"features": null,
"features": [
"gsl_token"
],
"images": [
"ghcr.io\/pterodactyl\/games:source"
],
@ -16,19 +18,18 @@
"startup": ".\/srcds_run -game csgo -console -port {{SERVER_PORT}} +ip 0.0.0.0 +map {{SRCDS_MAP}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}}",
"config": {
"files": "{}",
"startup": "{\r\n \"done\": \"Connection to Steam servers successful\",\r\n \"userInteraction\": []\r\n}",
"logs": "{\r\n \"custom\": true,\r\n \"location\": \"logs\/latest.log\"\r\n}",
"startup": "{\r\n \"done\": \"Connection to Steam servers successful\"\r\n}",
"logs": "{}",
"stop": "quit"
},
"scripts": {
"installation": {
"script": "#!\/bin\/bash\r\n# steamcmd Base Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n# Image to install with is 'ubuntu:18.04'\r\napt -y update\r\napt -y --no-install-recommends install curl lib32gcc1 ca-certificates\r\n\r\n## just in case someone removed the defaults.\r\nif [ \"${STEAM_USER}\" == \"\" ]; then\r\n STEAM_USER=anonymous\r\n STEAM_PASS=\"\"\r\n STEAM_AUTH=\"\"\r\nfi\r\n\r\n## download and install steamcmd\r\ncd \/tmp\r\nmkdir -p \/mnt\/server\/steamcmd\r\ncurl -sSL -o steamcmd.tar.gz https:\/\/steamcdn-a.akamaihd.net\/client\/installer\/steamcmd_linux.tar.gz\r\ntar -xzvf steamcmd.tar.gz -C \/mnt\/server\/steamcmd\r\nmkdir -p \/mnt\/server\/steamapps # Fix steamcmd disk write error when this folder is missing\r\ncd \/mnt\/server\/steamcmd\r\n\r\n# SteamCMD fails otherwise for some reason, even running as root.\r\n# This is changed at the end of the install process anyways.\r\nchown -R root:root \/mnt\r\nexport HOME=\/mnt\/server\r\n\r\n## install game using steamcmd\r\n.\/steamcmd.sh +login ${STEAM_USER} ${STEAM_PASS} ${STEAM_AUTH} +force_install_dir \/mnt\/server +app_update ${SRCDS_APPID} ${EXTRA_FLAGS} +quit ## other flags may be needed depending on install. looking at you cs 1.6\r\n\r\n## set up 32 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk32\r\ncp -v linux32\/steamclient.so ..\/.steam\/sdk32\/steamclient.so\r\n\r\n## set up 64 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk64\r\ncp -v linux64\/steamclient.so ..\/.steam\/sdk64\/steamclient.so",
"script": "#!\/bin\/bash\r\n# steamcmd Base Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n\r\n## just in case someone removed the defaults.\r\nif [ \"${STEAM_USER}\" == \"\" ]; then\r\n STEAM_USER=anonymous\r\n STEAM_PASS=\"\"\r\n STEAM_AUTH=\"\"\r\nfi\r\n\r\n## download and install steamcmd\r\ncd \/tmp\r\nmkdir -p \/mnt\/server\/steamcmd\r\ncurl -sSL -o steamcmd.tar.gz https:\/\/steamcdn-a.akamaihd.net\/client\/installer\/steamcmd_linux.tar.gz\r\ntar -xzvf steamcmd.tar.gz -C \/mnt\/server\/steamcmd\r\nmkdir -p \/mnt\/server\/steamapps # Fix steamcmd disk write error when this folder is missing\r\ncd \/mnt\/server\/steamcmd\r\n\r\n# SteamCMD fails otherwise for some reason, even running as root.\r\n# This is changed at the end of the install process anyways.\r\nchown -R root:root \/mnt\r\nexport HOME=\/mnt\/server\r\n\r\n## install game using steamcmd\r\n.\/steamcmd.sh +login ${STEAM_USER} ${STEAM_PASS} ${STEAM_AUTH} +force_install_dir \/mnt\/server +app_update ${SRCDS_APPID} ${EXTRA_FLAGS} +quit ## other flags may be needed depending on install. looking at you cs 1.6\r\n\r\n## set up 32 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk32\r\ncp -v linux32\/steamclient.so ..\/.steam\/sdk32\/steamclient.so\r\n\r\n## set up 64 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk64\r\ncp -v linux64\/steamclient.so ..\/.steam\/sdk64\/steamclient.so",
"container": "ghcr.io\/pterodactyl\/installers:debian",
"entrypoint": "bash"
}
},
"variables": [
{
"variables": [{
"name": "Map",
"description": "The default map for the server.",
"env_variable": "SRCDS_MAP",

View file

@ -4,7 +4,7 @@
"version": "PTDL_v1",
"update_url": null
},
"exported_at": "2021-06-05T16:24:05-04:00",
"exported_at": "2021-09-10T14:36:22-04:00",
"name": "Custom Source Engine Game",
"author": "support@pterodactyl.io",
"description": "This option allows modifying the startup arguments and other details to run a custom SRCDS based game on the panel.",
@ -16,19 +16,18 @@
"startup": ".\/srcds_run -game {{SRCDS_GAME}} -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} +ip 0.0.0.0 -strictportbind -norestart",
"config": {
"files": "{}",
"startup": "{\r\n \"done\": \"gameserver Steam ID\",\r\n \"userInteraction\": []\r\n}",
"logs": "{\r\n \"custom\": true,\r\n \"location\": \"logs\/latest.log\"\r\n}",
"startup": "{\r\n \"done\": \"gameserver Steam ID\"\r\n}",
"logs": "{}",
"stop": "quit"
},
"scripts": {
"installation": {
"script": "#!\/bin\/bash\r\n# steamcmd Base Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n# Image to install with is 'debian:buster-slim'\r\n\r\n##\r\n#\r\n# Variables\r\n# STEAM_USER, STEAM_PASS, STEAM_AUTH - Steam user setup. If a user has 2fa enabled it will most likely fail due to timeout. Leave blank for anon install.\r\n# WINDOWS_INSTALL - if it's a windows server you want to install set to 1\r\n# SRCDS_APPID - steam app id ffound here - https:\/\/developer.valvesoftware.com\/wiki\/Dedicated_Servers_List\r\n# EXTRA_FLAGS - when a server has extra glas for things like beta installs or updates.\r\n#\r\n##\r\n\r\napt -y update\r\napt -y --no-install-recommends install curl lib32gcc1 ca-certificates\r\n\r\n## just in case someone removed the defaults.\r\nif [ \"${STEAM_USER}\" == \"\" ]; then\r\n echo -e \"steam user is not set.\\n\"\r\n echo -e \"Using anonymous user.\\n\"\r\n STEAM_USER=anonymous\r\n STEAM_PASS=\"\"\r\n STEAM_AUTH=\"\"\r\nelse\r\n echo -e \"user set to ${STEAM_USER}\"\r\nfi\r\n\r\n## download and install steamcmd\r\ncd \/tmp\r\nmkdir -p \/mnt\/server\/steamcmd\r\ncurl -sSL -o steamcmd.tar.gz https:\/\/steamcdn-a.akamaihd.net\/client\/installer\/steamcmd_linux.tar.gz\r\ntar -xzvf steamcmd.tar.gz -C \/mnt\/server\/steamcmd\r\nmkdir -p \/mnt\/server\/steamapps # Fix steamcmd disk write error when this folder is missing\r\ncd \/mnt\/server\/steamcmd\r\n\r\n# SteamCMD fails otherwise for some reason, even running as root.\r\n# This is changed at the end of the install process anyways.\r\nchown -R root:root \/mnt\r\nexport HOME=\/mnt\/server\r\n\r\n## install game using steamcmd\r\n.\/steamcmd.sh +login ${STEAM_USER} ${STEAM_PASS} ${STEAM_AUTH} $( [[ \"${WINDOWS_INSTALL}\" == \"1\" ]] && printf %s '+@sSteamCmdForcePlatformType windows' ) +force_install_dir \/mnt\/server +app_update ${SRCDS_APPID} ${EXTRA_FLAGS} validate +quit ## other flags may be needed depending on install. looking at you cs 1.6\r\n\r\n## set up 32 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk32\r\ncp -v linux32\/steamclient.so ..\/.steam\/sdk32\/steamclient.so\r\n\r\n## set up 64 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk64\r\ncp -v linux64\/steamclient.so ..\/.steam\/sdk64\/steamclient.so",
"script": "#!\/bin\/bash\r\n# steamcmd Base Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n\r\n##\r\n#\r\n# Variables\r\n# STEAM_USER, STEAM_PASS, STEAM_AUTH - Steam user setup. If a user has 2fa enabled it will most likely fail due to timeout. Leave blank for anon install.\r\n# WINDOWS_INSTALL - if it's a windows server you want to install set to 1\r\n# SRCDS_APPID - steam app id ffound here - https:\/\/developer.valvesoftware.com\/wiki\/Dedicated_Servers_List\r\n# EXTRA_FLAGS - when a server has extra glas for things like beta installs or updates.\r\n#\r\n##\r\n\r\n\r\n## just in case someone removed the defaults.\r\nif [ \"${STEAM_USER}\" == \"\" ]; then\r\n echo -e \"steam user is not set.\\n\"\r\n echo -e \"Using anonymous user.\\n\"\r\n STEAM_USER=anonymous\r\n STEAM_PASS=\"\"\r\n STEAM_AUTH=\"\"\r\nelse\r\n echo -e \"user set to ${STEAM_USER}\"\r\nfi\r\n\r\n## download and install steamcmd\r\ncd \/tmp\r\nmkdir -p \/mnt\/server\/steamcmd\r\ncurl -sSL -o steamcmd.tar.gz https:\/\/steamcdn-a.akamaihd.net\/client\/installer\/steamcmd_linux.tar.gz\r\ntar -xzvf steamcmd.tar.gz -C \/mnt\/server\/steamcmd\r\nmkdir -p \/mnt\/server\/steamapps # Fix steamcmd disk write error when this folder is missing\r\ncd \/mnt\/server\/steamcmd\r\n\r\n# SteamCMD fails otherwise for some reason, even running as root.\r\n# This is changed at the end of the install process anyways.\r\nchown -R root:root \/mnt\r\nexport HOME=\/mnt\/server\r\n\r\n## install game using steamcmd\r\n.\/steamcmd.sh +login ${STEAM_USER} ${STEAM_PASS} ${STEAM_AUTH} $( [[ \"${WINDOWS_INSTALL}\" == \"1\" ]] && printf %s '+@sSteamCmdForcePlatformType windows' ) +force_install_dir \/mnt\/server +app_update ${SRCDS_APPID} ${EXTRA_FLAGS} validate +quit ## other flags may be needed depending on install. looking at you cs 1.6\r\n\r\n## set up 32 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk32\r\ncp -v linux32\/steamclient.so ..\/.steam\/sdk32\/steamclient.so\r\n\r\n## set up 64 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk64\r\ncp -v linux64\/steamclient.so ..\/.steam\/sdk64\/steamclient.so",
"container": "ghcr.io\/pterodactyl\/installers:debian",
"entrypoint": "bash"
}
},
"variables": [
{
"variables": [{
"name": "Game ID",
"description": "The ID corresponding to the game to download and run using SRCDS.",
"env_variable": "SRCDS_APPID",
@ -83,4 +82,4 @@
"rules": "nullable|string"
}
]
}
}

View file

@ -4,11 +4,13 @@
"version": "PTDL_v1",
"update_url": null
},
"exported_at": "2021-08-27T00:12:31-04:00",
"exported_at": "2021-12-04T18:47:10+00:00",
"name": "Garrys Mod",
"author": "support@pterodactyl.io",
"description": "Garrys Mod, is a sandbox physics game created by Garry Newman, and developed by his company, Facepunch Studios.",
"features": null,
"features": [
"gsl_token"
],
"images": [
"ghcr.io\/pterodactyl\/games:source"
],
@ -22,7 +24,7 @@
},
"scripts": {
"installation": {
"script": "#!\/bin\/bash\r\n# steamcmd Base Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n# Image to install with is 'debian:buster-slim'\r\napt -y update\r\napt -y --no-install-recommends install curl lib32gcc1 ca-certificates\r\n\r\n## just in case someone removed the defaults.\r\nif [ \"${STEAM_USER}\" == \"\" ]; then\r\n echo -e \"steam user is not set.\\n\"\r\n echo -e \"Using anonymous user.\\n\"\r\n STEAM_USER=anonymous\r\n STEAM_PASS=\"\"\r\n STEAM_AUTH=\"\"\r\nelse\r\n echo -e \"user set to ${STEAM_USER}\"\r\nfi\r\n\r\n## download and install steamcmd\r\ncd \/tmp\r\nmkdir -p \/mnt\/server\/steamcmd\r\ncurl -sSL -o steamcmd.tar.gz https:\/\/steamcdn-a.akamaihd.net\/client\/installer\/steamcmd_linux.tar.gz\r\ntar -xzvf steamcmd.tar.gz -C \/mnt\/server\/steamcmd\r\nmkdir -p \/mnt\/server\/steamapps # Fix steamcmd disk write error when this folder is missing\r\ncd \/mnt\/server\/steamcmd\r\n\r\n# SteamCMD fails otherwise for some reason, even running as root.\r\n# This is changed at the end of the install process anyways.\r\nchown -R root:root \/mnt\r\nexport HOME=\/mnt\/server\r\n\r\n## install game using steamcmd\r\n.\/steamcmd.sh +login ${STEAM_USER} ${STEAM_PASS} ${STEAM_AUTH} $( [[ \"${WINDOWS_INSTALL}\" == \"1\" ]] && printf %s '+@sSteamCmdForcePlatformType windows' ) +force_install_dir \/mnt\/server +app_update ${SRCDS_APPID} ${EXTRA_FLAGS} validate +quit ## other flags may be needed depending on install. looking at you cs 1.6\r\n\r\n## set up 32 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk32\r\ncp -v linux32\/steamclient.so ..\/.steam\/sdk32\/steamclient.so\r\n\r\n## set up 64 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk64\r\ncp -v linux64\/steamclient.so ..\/.steam\/sdk64\/steamclient.so\r\n\r\n# Creating needed default files for the game\r\ncd \/mnt\/server\/garrysmod\/lua\/autorun\/server\r\necho '\r\n-- Docs: https:\/\/wiki.garrysmod.com\/page\/resource\/AddWorkshop\r\n-- Place the ID of the workshop addon you want to be downloaded to people who join your server, not the collection ID\r\n-- Use https:\/\/beta.configcreator.com\/create\/gmod\/resources.lua to easily create a list based on your collection ID\r\n\r\nresource.AddWorkshop( \"\" )\r\n' > workshop.lua\r\n\r\ncd \/mnt\/server\/garrysmod\/cfg\r\necho '\r\n\/\/ Please do not set RCon in here, use the startup parameters.\r\n\r\nhostname\t\t\"New Gmod Server\"\r\nsv_password\t\t\"\"\r\nsv_loadingurl \"\"\r\nsv_downloadurl \"\"\r\n\r\n\/\/ Steam Server List Settings\r\n\/\/ sv_location \"eu\"\r\nsv_region \"255\"\r\nsv_lan \"0\"\r\nsv_max_queries_sec_global \"30000\"\r\nsv_max_queries_window \"45\"\r\nsv_max_queries_sec \"5\"\r\n\r\n\/\/ Server Limits\r\nsbox_maxprops\t\t100\r\nsbox_maxragdolls\t5\r\nsbox_maxnpcs\t\t10\r\nsbox_maxballoons\t10\r\nsbox_maxeffects\t\t10\r\nsbox_maxdynamite\t10\r\nsbox_maxlamps\t\t10\r\nsbox_maxthrusters\t10\r\nsbox_maxwheels\t\t10\r\nsbox_maxhoverballs\t10\r\nsbox_maxvehicles\t20\r\nsbox_maxbuttons\t\t10\r\nsbox_maxsents\t\t20\r\nsbox_maxemitters\t5\r\nsbox_godmode\t\t0\r\nsbox_noclip\t\t 0\r\n\r\n\/\/ Network Settings - Please keep these set to default.\r\n\r\nsv_minrate\t\t75000\r\nsv_maxrate\t\t0\r\ngmod_physiterations\t2\r\nnet_splitpacket_maxrate\t45000\r\ndecalfrequency\t\t12 \r\n\r\n\/\/ Execute Ban Files - Please do not edit\r\nexec banned_ip.cfg \r\nexec banned_user.cfg \r\n\r\n\/\/ Add custom lines under here\r\n' > server.cfg",
"script": "#!\/bin\/bash\r\n# steamcmd Base Installation Script\r\n#\r\n# Server Files: \/mnt\/server\r\n\r\n## just in case someone removed the defaults.\r\nif [ \"${STEAM_USER}\" == \"\" ]; then\r\n echo -e \"steam user is not set.\\n\"\r\n echo -e \"Using anonymous user.\\n\"\r\n STEAM_USER=anonymous\r\n STEAM_PASS=\"\"\r\n STEAM_AUTH=\"\"\r\nelse\r\n echo -e \"user set to ${STEAM_USER}\"\r\nfi\r\n\r\n## download and install steamcmd\r\ncd \/tmp\r\nmkdir -p \/mnt\/server\/steamcmd\r\ncurl -sSL -o steamcmd.tar.gz https:\/\/steamcdn-a.akamaihd.net\/client\/installer\/steamcmd_linux.tar.gz\r\ntar -xzvf steamcmd.tar.gz -C \/mnt\/server\/steamcmd\r\nmkdir -p \/mnt\/server\/steamapps # Fix steamcmd disk write error when this folder is missing\r\ncd \/mnt\/server\/steamcmd\r\n\r\n# SteamCMD fails otherwise for some reason, even running as root.\r\n# This is changed at the end of the install process anyways.\r\nchown -R root:root \/mnt\r\nexport HOME=\/mnt\/server\r\n\r\n## install game using steamcmd\r\n.\/steamcmd.sh +login ${STEAM_USER} ${STEAM_PASS} ${STEAM_AUTH} $( [[ \"${WINDOWS_INSTALL}\" == \"1\" ]] && printf %s '+@sSteamCmdForcePlatformType windows' ) +force_install_dir \/mnt\/server +app_update ${SRCDS_APPID} ${EXTRA_FLAGS} validate +quit ## other flags may be needed depending on install. looking at you cs 1.6\r\n\r\n## set up 32 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk32\r\ncp -v linux32\/steamclient.so ..\/.steam\/sdk32\/steamclient.so\r\n\r\n## set up 64 bit libraries\r\nmkdir -p \/mnt\/server\/.steam\/sdk64\r\ncp -v linux64\/steamclient.so ..\/.steam\/sdk64\/steamclient.so\r\n\r\n# Creating needed default files for the game\r\ncd \/mnt\/server\/garrysmod\/lua\/autorun\/server\r\necho '\r\n-- Docs: https:\/\/wiki.garrysmod.com\/page\/resource\/AddWorkshop\r\n-- Place the ID of the workshop addon you want to be downloaded to people who join your server, not the collection ID\r\n-- Use https:\/\/beta.configcreator.com\/create\/gmod\/resources.lua to easily create a list based on your collection ID\r\n\r\nresource.AddWorkshop( \"\" )\r\n' > workshop.lua\r\n\r\ncd \/mnt\/server\/garrysmod\/cfg\r\necho '\r\n\/\/ Please do not set RCon in here, use the startup parameters.\r\n\r\nhostname\t\t\"New Gmod Server\"\r\nsv_password\t\t\"\"\r\nsv_loadingurl \"\"\r\nsv_downloadurl \"\"\r\n\r\n\/\/ Steam Server List Settings\r\n\/\/ sv_location \"eu\"\r\nsv_region \"255\"\r\nsv_lan \"0\"\r\nsv_max_queries_sec_global \"30000\"\r\nsv_max_queries_window \"45\"\r\nsv_max_queries_sec \"5\"\r\n\r\n\/\/ Server Limits\r\nsbox_maxprops\t\t100\r\nsbox_maxragdolls\t5\r\nsbox_maxnpcs\t\t10\r\nsbox_maxballoons\t10\r\nsbox_maxeffects\t\t10\r\nsbox_maxdynamite\t10\r\nsbox_maxlamps\t\t10\r\nsbox_maxthrusters\t10\r\nsbox_maxwheels\t\t10\r\nsbox_maxhoverballs\t10\r\nsbox_maxvehicles\t20\r\nsbox_maxbuttons\t\t10\r\nsbox_maxsents\t\t20\r\nsbox_maxemitters\t5\r\nsbox_godmode\t\t0\r\nsbox_noclip\t\t 0\r\n\r\n\/\/ Network Settings - Please keep these set to default.\r\n\r\nsv_minrate\t\t75000\r\nsv_maxrate\t\t0\r\ngmod_physiterations\t2\r\nnet_splitpacket_maxrate\t45000\r\ndecalfrequency\t\t12 \r\n\r\n\/\/ Execute Ban Files - Please do not edit\r\nexec banned_ip.cfg \r\nexec banned_user.cfg \r\n\r\n\/\/ Add custom lines under here\r\n' > server.cfg",
"container": "ghcr.io\/pterodactyl\/installers:debian",
"entrypoint": "bash"
}
@ -101,4 +103,4 @@
"rules": "required|boolean"
}
]
}
}

View file

@ -34,7 +34,7 @@ x-common:
#
services:
database:
image: library/mysql:8.0
image: mariadb:10.5
restart: always
command: --default-authentication-plugin=mysql_native_password
volumes:

View file

@ -1,2 +1,2 @@
User-agent: *
Disallow:
Disallow: /

View file

@ -7,10 +7,21 @@ const http: AxiosInstance = axios.create({
'X-Requested-With': 'XMLHttpRequest',
Accept: 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token': (window as any).X_CSRF_TOKEN as string || '',
},
});
http.interceptors.request.use(req => {
const cookies = document.cookie.split(';').reduce((obj, val) => {
const [ key, value ] = val.trim().split('=').map(decodeURIComponent);
return { ...obj, [key]: value };
}, {} as Record<string, string>);
req.headers['X-XSRF-TOKEN'] = cookies['XSRF-TOKEN'] || 'nil';
return req;
});
http.interceptors.request.use(req => {
if (!req.url?.endsWith('/resources') && (req.url?.indexOf('_debugbar') || -1) < 0) {
store.getActions().progress.startContinuous();

View file

@ -46,7 +46,7 @@ export default () => {
>
<UpdateEmailAddressForm/>
</ContentBox>
<ContentBox css={tw`xl:ml-8 mt-8 xl:mt-0`} title={'Configure Two Factor'}>
<ContentBox css={tw`lg:ml-8 mt-8 lg:mt-0`} title={'Configure Two Factor'}>
<ConfigureTwoFactorForm/>
</ContentBox>
</Container>

View file

@ -4,7 +4,7 @@ import { faEthernet, faHdd, faMemory, faMicrochip, faServer } from '@fortawesome
import { Link } from 'react-router-dom';
import { Server } from '@/api/server/getServer';
import getServerResourceUsage, { ServerPowerState, ServerStats } from '@/api/server/getServerResourceUsage';
import { bytesToHuman, megabytesToHuman } from '@/helpers';
import { bytesToHuman, megabytesToHuman, formatIp } from '@/helpers';
import tw, { styled } from 'twin.macro';
import GreyRowBox from '@/components/elements/GreyRowBox';
import Spinner from '@/components/elements/Spinner';
@ -96,7 +96,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
{
server.allocations.filter(alloc => alloc.isDefault).map(allocation => (
<React.Fragment key={allocation.ip + allocation.port.toString()}>
{allocation.alias || allocation.ip}:{allocation.port}
{allocation.alias || formatIp(allocation.ip)}:{allocation.port}
</React.Fragment>
))
}

View file

@ -12,7 +12,7 @@ import { ApplicationStore } from '@/state';
import { Link } from 'react-router-dom';
import tw, { styled } from 'twin.macro';
import Input from '@/components/elements/Input';
import { formatIp } from '@/helpers';
type Props = RequiredModalProps;
interface Values {
@ -108,7 +108,7 @@ export default ({ ...props }: Props) => {
<p css={tw`mt-1 text-xs text-neutral-400`}>
{
server.allocations.filter(alloc => alloc.isDefault).map(allocation => (
<span key={allocation.ip + allocation.port.toString()}>{allocation.alias || allocation.ip}:{allocation.port}</span>
<span key={allocation.ip + allocation.port.toString()}>{allocation.alias || formatIp(allocation.ip)}:{allocation.port}</span>
))
}
</p>

View file

@ -28,15 +28,15 @@ const PageContentBlock: React.FC<PageContentBlockProps> = ({ title, showFlashKey
</ContentContainer>
<ContentContainer css={tw`mb-4`}>
<p css={tw`text-center text-neutral-500 text-xs`}>
&copy; 2015 - {(new Date()).getFullYear()}&nbsp;
<a
rel={'noopener nofollow noreferrer'}
href={'https://pterodactyl.io'}
target={'_blank'}
css={tw`no-underline text-neutral-500 hover:text-neutral-300`}
>
Pterodactyl Software
Pterodactyl&reg;
</a>
&nbsp;&copy; 2015 - {(new Date()).getFullYear()}
</p>
</ContentContainer>
</>

View file

@ -7,7 +7,7 @@ import ServerContentBlock from '@/components/elements/ServerContentBlock';
import ServerDetailsBlock from '@/components/server/ServerDetailsBlock';
import isEqual from 'react-fast-compare';
import PowerControls from '@/components/server/PowerControls';
import { EulaModalFeature, JavaVersionModalFeature } from 'feature/index';
import { EulaModalFeature, JavaVersionModalFeature, GSLTokenModalFeature } from 'feature/index';
import ErrorBoundary from '@/components/elements/ErrorBoundary';
import Spinner from '@/components/elements/Spinner';
@ -60,6 +60,7 @@ const ServerConsole = () => {
<React.Suspense fallback={null}>
{eggFeatures.includes('eula') && <EulaModalFeature/>}
{eggFeatures.includes('java_version') && <JavaVersionModalFeature/>}
{eggFeatures.includes('gsl_token') && <GSLTokenModalFeature/>}
</React.Suspense>
</div>
</ServerContentBlock>

View file

@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
import tw, { TwStyle } from 'twin.macro';
import { faCircle, faEthernet, faHdd, faMemory, faMicrochip, faServer } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { bytesToHuman, megabytesToHuman } from '@/helpers';
import { bytesToHuman, megabytesToHuman, formatIp } from '@/helpers';
import TitledGreyBox from '@/components/elements/TitledGreyBox';
import { ServerContext } from '@/state/server';
import CopyOnClick from '@/components/elements/CopyOnClick';
@ -72,7 +72,7 @@ const ServerDetailsBlock = () => {
const isTransferring = ServerContext.useStoreState(state => state.server.data!.isTransferring);
const limits = ServerContext.useStoreState(state => state.server.data!.limits);
const primaryAllocation = ServerContext.useStoreState(state => state.server.data!.allocations.filter(alloc => alloc.isDefault).map(
allocation => (allocation.alias || allocation.ip) + ':' + allocation.port,
allocation => (allocation.alias || formatIp(allocation.ip)) + ':' + allocation.port,
)).toString();
const diskLimit = limits.disk ? megabytesToHuman(limits.disk) : 'Unlimited';

View file

@ -97,6 +97,7 @@ export default () => {
setCpu(
new Chart(node.getContext('2d')!, chartDefaults({
callback: (value) => `${value}% `,
suggestedMax: limits.cpu,
})),
);
}, []);

View file

@ -76,7 +76,7 @@ export default ({ database, className }: Props) => {
<FlashMessageRender byKey={'database:delete'} css={tw`mb-6`}/>
<h2 css={tw`text-2xl mb-6`}>Confirm database deletion</h2>
<p css={tw`text-sm`}>
Deleting a database is a permanent action, it cannot be undone. This will permanetly
Deleting a database is a permanent action, it cannot be undone. This will permanently
delete the <strong>{database.name}</strong> database and remove all associated data.
</p>
<Form css={tw`m-0 mt-6`}>

View file

@ -0,0 +1,101 @@
import React, { useEffect, useState } from 'react';
import { ServerContext } from '@/state/server';
import Modal from '@/components/elements/Modal';
import tw from 'twin.macro';
import Button from '@/components/elements/Button';
import FlashMessageRender from '@/components/FlashMessageRender';
import useFlash from '@/plugins/useFlash';
import { SocketEvent, SocketRequest } from '@/components/server/events';
import Field from '@/components/elements/Field';
import updateStartupVariable from '@/api/server/updateStartupVariable';
import { Form, Formik } from 'formik';
interface Values {
gslToken: string;
}
const GSLTokenModalFeature = () => {
const [ visible, setVisible ] = useState(false);
const [ loading, setLoading ] = useState(false);
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
const status = ServerContext.useStoreState(state => state.status.value);
const { clearFlashes, clearAndAddHttpError } = useFlash();
const { connected, instance } = ServerContext.useStoreState(state => state.socket);
useEffect(() => {
if (!connected || !instance || status === 'running') return;
const errors = [
'(gsl token expired)',
'(account not found)',
];
const listener = (line: string) => {
if (errors.some(p => line.toLowerCase().includes(p))) {
setVisible(true);
}
};
instance.addListener(SocketEvent.CONSOLE_OUTPUT, listener);
return () => {
instance.removeListener(SocketEvent.CONSOLE_OUTPUT, listener);
};
}, [ connected, instance, status ]);
const updateGSLToken = (values: Values) => {
setLoading(true);
clearFlashes('feature:gslToken');
updateStartupVariable(uuid, 'STEAM_ACC', values.gslToken)
.then(() => {
if (instance) {
instance.send(SocketRequest.SET_STATE, 'restart');
}
setLoading(false);
setVisible(false);
})
.catch(error => {
console.error(error);
clearAndAddHttpError({ key: 'feature:gslToken', error });
})
.then(() => setLoading(false));
};
useEffect(() => {
clearFlashes('feature:gslToken');
}, []);
return (
<Formik
onSubmit={updateGSLToken}
initialValues={{ gslToken: '' }}
>
<Modal visible={visible} onDismissed={() => setVisible(false)} closeOnBackground={false} showSpinnerOverlay={loading}>
<FlashMessageRender key={'feature:gslToken'} css={tw`mb-4`}/>
<Form>
<h2 css={tw`text-2xl mb-4 text-neutral-100`}>Invalid GSL token!</h2>
<p css={tw`mt-4`}>It seems like your Gameserver Login Token (GSL token) is invalid or has expired.</p>
<p css={tw`mt-4`}>You can either generate a new one and enter it below or leave the field blank to remove it completely.</p>
<div css={tw`sm:flex items-center mt-4`}>
<Field
name={'gslToken'}
label={'GSL Token'}
description={'Visit https://steamcommunity.com/dev/managegameservers to generate a token.'}
autoFocus
/>
</div>
<div css={tw`mt-8 sm:flex items-center justify-end`}>
<Button type={'submit'} css={tw`mt-4 sm:mt-0 sm:ml-4 w-full sm:w-auto`}>
Update GSL Token
</Button>
</div>
</Form>
</Modal>
</Formik>
);
};
export default GSLTokenModalFeature;

View file

@ -7,6 +7,7 @@ import { lazy } from 'react';
* on the feature and the egg).
*/
const EulaModalFeature = lazy(() => import(/* webpackChunkName: "feature.eula" */'feature/eula/EulaModalFeature'));
const JavaVersionModalFeature = lazy(() => import(/* webpackChunkName: "feature.java_version" */'feature/java_version/JavaVersionModalFeature'));
const JavaVersionModalFeature = lazy(() => import(/* webpackChunkName: "feature.java_version" */'feature/JavaVersionModalFeature'));
const GSLTokenModalFeature = lazy(() => import(/* webpackChunkName: "feature.gsl_token" */'feature/GSLTokenModalFeature'));
export { EulaModalFeature, JavaVersionModalFeature };
export { EulaModalFeature, JavaVersionModalFeature, GSLTokenModalFeature };

View file

@ -10,15 +10,16 @@ import { SocketEvent, SocketRequest } from '@/components/server/events';
import Select from '@/components/elements/Select';
const dockerImageList = [
{ name: 'Java 8', image: 'ghcr.io/pterodactyl/yolks:java_8' },
{ name: 'Java 11', image: 'ghcr.io/pterodactyl/yolks:java_11' },
{ name: 'Java 17', image: 'ghcr.io/pterodactyl/yolks:java_17' },
{ name: 'Java 16', image: 'ghcr.io/pterodactyl/yolks:java_16' },
{ name: 'Java 11', image: 'ghcr.io/pterodactyl/yolks:java_11' },
{ name: 'Java 8', image: 'ghcr.io/pterodactyl/yolks:java_8' },
];
const JavaVersionModalFeature = () => {
const [ visible, setVisible ] = useState(false);
const [ loading, setLoading ] = useState(false);
const [ selectedVersion, setSelectedVersion ] = useState('ghcr.io/pterodactyl/yolks:java_16');
const [ selectedVersion, setSelectedVersion ] = useState('ghcr.io/pterodactyl/yolks:java_17');
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
const status = ServerContext.useStoreState(state => state.status.value);
@ -30,6 +31,7 @@ const JavaVersionModalFeature = () => {
const errors = [
'minecraft 1.17 requires running the server with java 16 or above',
'minecraft 1.18 requires running the server with java 17 or above',
'java.lang.unsupportedclassversionerror',
'unsupported major.minor version',
'has been compiled by a more recent version of the java runtime',

View file

@ -17,6 +17,7 @@ import CopyOnClick from '@/components/elements/CopyOnClick';
import DeleteAllocationButton from '@/components/server/network/DeleteAllocationButton';
import setPrimaryServerAllocation from '@/api/server/network/setPrimaryServerAllocation';
import getServerAllocations from '@/api/swr/getServerAllocations';
import { formatIp } from '@/helpers';
const Code = styled.code`${tw`font-mono py-1 px-2 bg-neutral-900 rounded text-sm inline-block`}`;
const Label = styled.label`${tw`uppercase text-xs mt-1 text-neutral-400 block px-1 select-none transition-colors duration-150`}`;
@ -65,7 +66,7 @@ const AllocationRow = ({ allocation }: Props) => {
<div css={tw`mr-4 flex-1 md:w-40`}>
{allocation.alias ?
<CopyOnClick text={allocation.alias}><Code css={tw`w-40 truncate`}>{allocation.alias}</Code></CopyOnClick> :
<CopyOnClick text={allocation.ip}><Code>{allocation.ip}</Code></CopyOnClick>}
<CopyOnClick text={formatIp(allocation.ip)}><Code>{formatIp(allocation.ip)}</Code></CopyOnClick>}
<Label>{allocation.alias ? 'Hostname' : 'IP Address'}</Label>
</div>
<div css={tw`w-16 md:w-24 overflow-hidden`}>

View file

@ -13,6 +13,7 @@ import { LinkButton } from '@/components/elements/Button';
import ServerContentBlock from '@/components/elements/ServerContentBlock';
import isEqual from 'react-fast-compare';
import CopyOnClick from '@/components/elements/CopyOnClick';
import { formatIp } from '@/helpers';
export default () => {
const username = useStoreState(state => state.user.data!.username);
@ -31,10 +32,10 @@ export default () => {
<TitledGreyBox title={'SFTP Details'} css={tw`mb-6 md:mb-10`}>
<div>
<Label>Server Address</Label>
<CopyOnClick text={`sftp://${sftp.ip}:${sftp.port}`}>
<CopyOnClick text={`sftp://${formatIp(sftp.ip)}:${sftp.port}`}>
<Input
type={'text'}
value={`sftp://${sftp.ip}:${sftp.port}`}
value={`sftp://${formatIp(sftp.ip)}:${sftp.port}`}
readOnly
/>
</CopyOnClick>
@ -60,7 +61,7 @@ export default () => {
<div css={tw`ml-4`}>
<LinkButton
isSecondary
href={`sftp://${username}.${id}@${sftp.ip}:${sftp.port}`}
href={`sftp://${username}.${id}@${formatIp(sftp.ip)}:${sftp.port}`}
>
Launch SFTP
</LinkButton>

View file

@ -63,3 +63,7 @@ export function encodePathSegments (path: string): string {
export function hashToPath (hash: string): string {
return hash.length > 0 ? decodeURIComponent(hash.substr(1)) : '/';
}
export function formatIp (ip: string): string {
return /([a-f0-9:]+:+)+[a-f0-9]+/.test(ip) ? `[${ip}]` : ip;
}

View file

@ -4,6 +4,7 @@ namespace Pterodactyl\Tests\Integration\Api\Application\Location;
use Illuminate\Http\Response;
use Pterodactyl\Models\Location;
use Pterodactyl\Transformers\Api\Application\LocationTransformer;
use Pterodactyl\Transformers\Api\Application\NodeTransformer;
use Pterodactyl\Transformers\Api\Application\ServerTransformer;
use Pterodactyl\Tests\Integration\Api\Application\ApplicationApiIntegrationTestCase;
@ -88,6 +89,77 @@ class LocationControllerTest extends ApplicationApiIntegrationTestCase
], true);
}
/**
* Test that a location can be created.
*/
public function testCreateLocation()
{
$response = $this->postJson('/api/application/locations', [
'short' => 'inhouse',
'long' => 'This is my inhouse location',
]);
$response->assertStatus(Response::HTTP_CREATED);
$response->assertJsonCount(3);
$response->assertJsonStructure([
'object',
'attributes' => ['id', 'short', 'long', 'created_at', 'updated_at'],
'meta' => ['resource'],
]);
$this->assertDatabaseHas('locations', ['short' => 'inhouse', 'long' => 'This is my inhouse location']);
$location = Location::where('short', 'inhouse')->first();
$response->assertJson([
'object' => 'location',
'attributes' => $this->getTransformer(LocationTransformer::class)->transform($location),
'meta' => [
'resource' => route('api.application.locations.view', $location->id),
],
], true);
}
/**
* Test that a location can be updated.
*/
public function testUpdateLocation()
{
$location = Location::factory()->create();
$response = $this->patchJson('/api/application/locations/' . $location->id, [
'short' => 'new inhouse',
'long' => 'This is my new inhouse location'
]);
$response->assertStatus(Response::HTTP_OK);
$response->assertJsonCount(2);
$response->assertJsonStructure([
'object',
'attributes' => ['id', 'short', 'long', 'created_at', 'updated_at']
]);
$this->assertDatabaseHas('locations', ['short' => 'new inhouse', 'long' => 'This is my new inhouse location']);
$location = $location->fresh();
$response->assertJson([
'object' => 'location',
'attributes' => $this->getTransformer(LocationTransformer::class)->transform($location),
]);
}
/**
* Test that a location can be deleted from the database.
*/
public function testDeleteLocation()
{
$location = Location::factory()->create();
$this->assertDatabaseHas('locations', ['id' => $location->id]);
$response = $this->delete('/api/application/locations/' . $location->id);
$response->assertStatus(Response::HTTP_NO_CONTENT);
$this->assertDatabaseMissing('locations', ['id' => $location->id]);
}
/**
* Test that all of the defined relationships for a location can be loaded successfully.
*/