forked from Alex/Pterodactyl-Panel
Compare commits
17 Commits
workflows/
...
develop
Author | SHA1 | Date | |
---|---|---|---|
|
1d02365efe | ||
|
1564742606 | ||
|
66c56b0da8 | ||
|
15619fb8e4 | ||
|
4e6fe112b0 | ||
|
f04b87a37c | ||
|
928b060647 | ||
|
b8bf537737 | ||
|
0d5ff6afac | ||
|
5cde059f21 | ||
|
0db772a82b | ||
|
dcbc1360a9 | ||
|
622b939f00 | ||
|
e8e2911a92 | ||
|
96c3338e96 | ||
|
49d5ef271d | ||
|
4cc8658334 |
2
.github/docker/README.md
vendored
2
.github/docker/README.md
vendored
@ -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_URL` | The URL the panel will be reachable with (including protocol) | yes |
|
||||||
| `APP_TIMEZONE` | The timezone to use for the panel | 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_HOST` | The host of the mysql instance | yes |
|
||||||
| `DB_PORT` | The port of the mysql instance | yes |
|
| `DB_PORT` | The port of the mysql instance | yes |
|
||||||
| `DB_DATABASE` | The name of the mysql database | yes |
|
| `DB_DATABASE` | The name of the mysql database | yes |
|
||||||
|
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
@ -36,6 +36,7 @@ jobs:
|
|||||||
if: "!contains(github.ref, 'develop')"
|
if: "!contains(github.ref, 'develop')"
|
||||||
with:
|
with:
|
||||||
push: true
|
push: true
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||||
- name: Release Development Build
|
- name: Release Development Build
|
||||||
@ -43,5 +44,6 @@ jobs:
|
|||||||
if: "contains(github.ref, 'develop')"
|
if: "contains(github.ref, 'develop')"
|
||||||
with:
|
with:
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: ${{ github.event_name != 'pull_request' }}
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
tags: ${{ steps.docker_meta.outputs.tags }}
|
tags: ${{ steps.docker_meta.outputs.tags }}
|
||||||
labels: ${{ steps.docker_meta.outputs.labels }}
|
labels: ${{ steps.docker_meta.outputs.labels }}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# Build the assets that are needed for the frontend. This build stage is then discarded
|
# 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
|
# since we won't need NodeJS anymore in the future. This Docker image ships a final production
|
||||||
# level distribution of Pterodactyl.
|
# level distribution of Pterodactyl.
|
||||||
FROM mhart/alpine-node:14
|
FROM --platform=$TARGETOS/$TARGETARCH mhart/alpine-node:14
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY . ./
|
COPY . ./
|
||||||
RUN yarn install --frozen-lockfile \
|
RUN yarn install --frozen-lockfile \
|
||||||
@ -10,7 +10,7 @@ RUN yarn install --frozen-lockfile \
|
|||||||
|
|
||||||
# Stage 1:
|
# Stage 1:
|
||||||
# Build the actual container with all of the needed PHP dependencies that will run the application.
|
# 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
|
WORKDIR /app
|
||||||
COPY . ./
|
COPY . ./
|
||||||
COPY --from=0 /app/public/assets ./public/assets
|
COPY --from=0 /app/public/assets ./public/assets
|
||||||
|
@ -37,6 +37,7 @@ 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. |
|
| [**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.|
|
| [**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! |
|
| [**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! |
|
||||||
|
| [**HostEZ**](https://hostez.io) | Providing North America Valheim, Minecraft and other popular games with low latency, high uptime and maximum availability. EZ! |
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
* [Panel Documentation](https://pterodactyl.io/panel/1.0/getting_started.html)
|
* [Panel Documentation](https://pterodactyl.io/panel/1.0/getting_started.html)
|
||||||
|
@ -12,6 +12,7 @@ namespace Pterodactyl\Console\Commands\Environment;
|
|||||||
use DateTimeZone;
|
use DateTimeZone;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Contracts\Console\Kernel;
|
use Illuminate\Contracts\Console\Kernel;
|
||||||
|
use Illuminate\Validation\Factory as ValidatorFactory;
|
||||||
use Pterodactyl\Traits\Commands\EnvironmentWriterTrait;
|
use Pterodactyl\Traits\Commands\EnvironmentWriterTrait;
|
||||||
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
use Illuminate\Contracts\Config\Repository as ConfigRepository;
|
||||||
|
|
||||||
@ -78,12 +79,13 @@ class AppSettingsCommand extends Command
|
|||||||
/**
|
/**
|
||||||
* AppSettingsCommand constructor.
|
* AppSettingsCommand constructor.
|
||||||
*/
|
*/
|
||||||
public function __construct(ConfigRepository $config, Kernel $command)
|
public function __construct(ConfigRepository $config, Kernel $command, ValidatorFactory $validator)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
|
||||||
$this->command = $command;
|
|
||||||
$this->config = $config;
|
$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')
|
$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->output->comment(trans('command/messages.environment.app.app_url_help'));
|
||||||
$this->variables['APP_URL'] = $this->option('url') ?? $this->ask(
|
$this->variables['APP_URL'] = $this->option('url') ?? $this->ask(
|
||||||
trans('command/messages.environment.app.app_url'),
|
trans('command/messages.environment.app.app_url'),
|
||||||
|
File diff suppressed because one or more lines are too long
@ -48,7 +48,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Server Map",
|
"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",
|
"env_variable": "SERVER_MAP",
|
||||||
"default_value": "TheIsland",
|
"default_value": "TheIsland",
|
||||||
"user_viewable": true,
|
"user_viewable": true,
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
"version": "PTDL_v1",
|
"version": "PTDL_v1",
|
||||||
"update_url": null
|
"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",
|
"name": "Counter-Strike: Global Offensive",
|
||||||
"author": "support@pterodactyl.io",
|
"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.",
|
"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": [
|
"images": [
|
||||||
"ghcr.io\/pterodactyl\/games:source"
|
"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}}",
|
"startup": ".\/srcds_run -game csgo -console -port {{SERVER_PORT}} +ip 0.0.0.0 +map {{SRCDS_MAP}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}}",
|
||||||
"config": {
|
"config": {
|
||||||
"files": "{}",
|
"files": "{}",
|
||||||
"startup": "{\r\n \"done\": \"Connection to Steam servers successful\",\r\n \"userInteraction\": []\r\n}",
|
"startup": "{\r\n \"done\": \"Connection to Steam servers successful\"\r\n}",
|
||||||
"logs": "{\r\n \"custom\": true,\r\n \"location\": \"logs\/latest.log\"\r\n}",
|
"logs": "{}",
|
||||||
"stop": "quit"
|
"stop": "quit"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"installation": {
|
"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",
|
"container": "ghcr.io\/pterodactyl\/installers:debian",
|
||||||
"entrypoint": "bash"
|
"entrypoint": "bash"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"variables": [
|
"variables": [{
|
||||||
{
|
|
||||||
"name": "Map",
|
"name": "Map",
|
||||||
"description": "The default map for the server.",
|
"description": "The default map for the server.",
|
||||||
"env_variable": "SRCDS_MAP",
|
"env_variable": "SRCDS_MAP",
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"version": "PTDL_v1",
|
"version": "PTDL_v1",
|
||||||
"update_url": null
|
"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",
|
"name": "Custom Source Engine Game",
|
||||||
"author": "support@pterodactyl.io",
|
"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.",
|
"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",
|
"startup": ".\/srcds_run -game {{SRCDS_GAME}} -console -port {{SERVER_PORT}} +map {{SRCDS_MAP}} +ip 0.0.0.0 -strictportbind -norestart",
|
||||||
"config": {
|
"config": {
|
||||||
"files": "{}",
|
"files": "{}",
|
||||||
"startup": "{\r\n \"done\": \"gameserver Steam ID\",\r\n \"userInteraction\": []\r\n}",
|
"startup": "{\r\n \"done\": \"gameserver Steam ID\"\r\n}",
|
||||||
"logs": "{\r\n \"custom\": true,\r\n \"location\": \"logs\/latest.log\"\r\n}",
|
"logs": "{}",
|
||||||
"stop": "quit"
|
"stop": "quit"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"installation": {
|
"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",
|
"container": "ghcr.io\/pterodactyl\/installers:debian",
|
||||||
"entrypoint": "bash"
|
"entrypoint": "bash"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"variables": [
|
"variables": [{
|
||||||
{
|
|
||||||
"name": "Game ID",
|
"name": "Game ID",
|
||||||
"description": "The ID corresponding to the game to download and run using SRCDS.",
|
"description": "The ID corresponding to the game to download and run using SRCDS.",
|
||||||
"env_variable": "SRCDS_APPID",
|
"env_variable": "SRCDS_APPID",
|
||||||
|
@ -4,11 +4,13 @@
|
|||||||
"version": "PTDL_v1",
|
"version": "PTDL_v1",
|
||||||
"update_url": null
|
"update_url": null
|
||||||
},
|
},
|
||||||
"exported_at": "2021-08-27T00:12:31-04:00",
|
"exported_at": "2021-12-04T18:47:10+00:00",
|
||||||
"name": "Garrys Mod",
|
"name": "Garrys Mod",
|
||||||
"author": "support@pterodactyl.io",
|
"author": "support@pterodactyl.io",
|
||||||
"description": "Garrys Mod, is a sandbox physics game created by Garry Newman, and developed by his company, Facepunch Studios.",
|
"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": [
|
"images": [
|
||||||
"ghcr.io\/pterodactyl\/games:source"
|
"ghcr.io\/pterodactyl\/games:source"
|
||||||
],
|
],
|
||||||
@ -22,7 +24,7 @@
|
|||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"installation": {
|
"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",
|
"container": "ghcr.io\/pterodactyl\/installers:debian",
|
||||||
"entrypoint": "bash"
|
"entrypoint": "bash"
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ x-common:
|
|||||||
#
|
#
|
||||||
services:
|
services:
|
||||||
database:
|
database:
|
||||||
image: library/mysql:8.0
|
image: mariadb:10.5
|
||||||
restart: always
|
restart: always
|
||||||
command: --default-authentication-plugin=mysql_native_password
|
command: --default-authentication-plugin=mysql_native_password
|
||||||
volumes:
|
volumes:
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
"swr": "^0.2.3",
|
"swr": "^0.2.3",
|
||||||
"tailwindcss": "^2.0.2",
|
"tailwindcss": "^2.0.2",
|
||||||
"uuid": "^3.3.2",
|
"uuid": "^3.3.2",
|
||||||
"xterm": "^4.12.0",
|
"xterm": "^4.15.0",
|
||||||
"xterm-addon-attach": "^0.6.0",
|
"xterm-addon-attach": "^0.6.0",
|
||||||
"xterm-addon-fit": "^0.4.0",
|
"xterm-addon-fit": "^0.4.0",
|
||||||
"xterm-addon-search": "^0.7.0",
|
"xterm-addon-search": "^0.7.0",
|
||||||
|
@ -47,7 +47,7 @@ export default () => {
|
|||||||
>
|
>
|
||||||
<UpdateEmailAddressForm/>
|
<UpdateEmailAddressForm/>
|
||||||
</ContentBox>
|
</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/>
|
<ConfigureTwoFactorForm/>
|
||||||
</ContentBox>
|
</ContentBox>
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -4,7 +4,7 @@ import { faEthernet, faHdd, faMemory, faMicrochip, faServer } from '@fortawesome
|
|||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Server } from '@/api/server/getServer';
|
import { Server } from '@/api/server/getServer';
|
||||||
import getServerResourceUsage, { ServerPowerState, ServerStats } from '@/api/server/getServerResourceUsage';
|
import getServerResourceUsage, { ServerPowerState, ServerStats } from '@/api/server/getServerResourceUsage';
|
||||||
import { bytesToHuman, megabytesToHuman } from '@/helpers';
|
import { bytesToHuman, megabytesToHuman, formatIp } from '@/helpers';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
import GreyRowBox from '@/components/elements/GreyRowBox';
|
import GreyRowBox from '@/components/elements/GreyRowBox';
|
||||||
import Spinner from '@/components/elements/Spinner';
|
import Spinner from '@/components/elements/Spinner';
|
||||||
@ -97,7 +97,7 @@ export default ({ server, className }: { server: Server; className?: string }) =
|
|||||||
{
|
{
|
||||||
server.allocations.filter(alloc => alloc.isDefault).map(allocation => (
|
server.allocations.filter(alloc => alloc.isDefault).map(allocation => (
|
||||||
<React.Fragment key={allocation.ip + allocation.port.toString()}>
|
<React.Fragment key={allocation.ip + allocation.port.toString()}>
|
||||||
{allocation.alias || allocation.ip}:{allocation.port}
|
{allocation.alias || formatIp(allocation.ip)}:{allocation.port}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import styled from 'styled-components/macro';
|
import styled from 'styled-components/macro';
|
||||||
import tw from 'twin.macro';
|
import tw from 'twin.macro';
|
||||||
import Input from '@/components/elements/Input';
|
import Input from '@/components/elements/Input';
|
||||||
|
import { formatIp } from '@/helpers';
|
||||||
type Props = RequiredModalProps;
|
type Props = RequiredModalProps;
|
||||||
|
|
||||||
interface Values {
|
interface Values {
|
||||||
@ -109,7 +109,7 @@ export default ({ ...props }: Props) => {
|
|||||||
<p css={tw`mt-1 text-xs text-neutral-400`}>
|
<p css={tw`mt-1 text-xs text-neutral-400`}>
|
||||||
{
|
{
|
||||||
server.allocations.filter(alloc => alloc.isDefault).map(allocation => (
|
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>
|
</p>
|
||||||
|
@ -7,7 +7,7 @@ import ServerContentBlock from '@/components/elements/ServerContentBlock';
|
|||||||
import ServerDetailsBlock from '@/components/server/ServerDetailsBlock';
|
import ServerDetailsBlock from '@/components/server/ServerDetailsBlock';
|
||||||
import isEqual from 'react-fast-compare';
|
import isEqual from 'react-fast-compare';
|
||||||
import PowerControls from '@/components/server/PowerControls';
|
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 ErrorBoundary from '@/components/elements/ErrorBoundary';
|
||||||
import Spinner from '@/components/elements/Spinner';
|
import Spinner from '@/components/elements/Spinner';
|
||||||
|
|
||||||
@ -60,6 +60,7 @@ const ServerConsole = () => {
|
|||||||
<React.Suspense fallback={null}>
|
<React.Suspense fallback={null}>
|
||||||
{eggFeatures.includes('eula') && <EulaModalFeature/>}
|
{eggFeatures.includes('eula') && <EulaModalFeature/>}
|
||||||
{eggFeatures.includes('java_version') && <JavaVersionModalFeature/>}
|
{eggFeatures.includes('java_version') && <JavaVersionModalFeature/>}
|
||||||
|
{eggFeatures.includes('gsl_token') && <GSLTokenModalFeature/>}
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
</div>
|
</div>
|
||||||
</ServerContentBlock>
|
</ServerContentBlock>
|
||||||
|
@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react';
|
|||||||
import tw, { TwStyle } from 'twin.macro';
|
import tw, { TwStyle } from 'twin.macro';
|
||||||
import { faCircle, faEthernet, faHdd, faMemory, faMicrochip, faServer } from '@fortawesome/free-solid-svg-icons';
|
import { faCircle, faEthernet, faHdd, faMemory, faMicrochip, faServer } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import { bytesToHuman, megabytesToHuman } from '@/helpers';
|
import { bytesToHuman, megabytesToHuman, formatIp } from '@/helpers';
|
||||||
import TitledGreyBox from '@/components/elements/TitledGreyBox';
|
import TitledGreyBox from '@/components/elements/TitledGreyBox';
|
||||||
import { ServerContext } from '@/state/server';
|
import { ServerContext } from '@/state/server';
|
||||||
import CopyOnClick from '@/components/elements/CopyOnClick';
|
import CopyOnClick from '@/components/elements/CopyOnClick';
|
||||||
@ -72,7 +72,7 @@ const ServerDetailsBlock = () => {
|
|||||||
const isTransferring = ServerContext.useStoreState(state => state.server.data!.isTransferring);
|
const isTransferring = ServerContext.useStoreState(state => state.server.data!.isTransferring);
|
||||||
const limits = ServerContext.useStoreState(state => state.server.data!.limits);
|
const limits = ServerContext.useStoreState(state => state.server.data!.limits);
|
||||||
const primaryAllocation = ServerContext.useStoreState(state => state.server.data!.allocations.filter(alloc => alloc.isDefault).map(
|
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();
|
)).toString();
|
||||||
|
|
||||||
const diskLimit = limits.disk ? megabytesToHuman(limits.disk) : 'Unlimited';
|
const diskLimit = limits.disk ? megabytesToHuman(limits.disk) : 'Unlimited';
|
||||||
|
@ -97,6 +97,7 @@ export default () => {
|
|||||||
setCpu(
|
setCpu(
|
||||||
new Chart(node.getContext('2d')!, chartDefaults({
|
new Chart(node.getContext('2d')!, chartDefaults({
|
||||||
callback: (value) => `${value}% `,
|
callback: (value) => `${value}% `,
|
||||||
|
suggestedMax: limits.cpu,
|
||||||
})),
|
})),
|
||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
@ -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;
|
@ -10,16 +10,16 @@ import { SocketEvent, SocketRequest } from '@/components/server/events';
|
|||||||
import Select from '@/components/elements/Select';
|
import Select from '@/components/elements/Select';
|
||||||
|
|
||||||
const dockerImageList = [
|
const dockerImageList = [
|
||||||
{ name: 'Java 8', image: 'ghcr.io/pterodactyl/yolks:java_8' },
|
|
||||||
{ name: 'Java 11', image: 'ghcr.io/pterodactyl/yolks:java_11' },
|
|
||||||
{ name: 'Java 16', image: 'ghcr.io/pterodactyl/yolks:java_16' },
|
|
||||||
{ name: 'Java 17', image: 'ghcr.io/pterodactyl/yolks:java_17' },
|
{ 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 JavaVersionModalFeature = () => {
|
||||||
const [ visible, setVisible ] = useState(false);
|
const [ visible, setVisible ] = useState(false);
|
||||||
const [ loading, setLoading ] = 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 uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
||||||
const status = ServerContext.useStoreState(state => state.status.value);
|
const status = ServerContext.useStoreState(state => state.status.value);
|
||||||
@ -31,6 +31,7 @@ const JavaVersionModalFeature = () => {
|
|||||||
|
|
||||||
const errors = [
|
const errors = [
|
||||||
'minecraft 1.17 requires running the server with java 16 or above',
|
'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',
|
'java.lang.unsupportedclassversionerror',
|
||||||
'unsupported major.minor version',
|
'unsupported major.minor version',
|
||||||
'has been compiled by a more recent version of the java runtime',
|
'has been compiled by a more recent version of the java runtime',
|
||||||
|
@ -8,5 +8,6 @@ import { lazy } from 'react';
|
|||||||
*/
|
*/
|
||||||
const EulaModalFeature = lazy(() => import(/* webpackChunkName: "feature.eula" */'@feature/eula/EulaModalFeature'));
|
const EulaModalFeature = lazy(() => import(/* webpackChunkName: "feature.eula" */'@feature/eula/EulaModalFeature'));
|
||||||
const JavaVersionModalFeature = lazy(() => import(/* webpackChunkName: "feature.java_version" */'@feature/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 };
|
||||||
|
@ -18,6 +18,7 @@ import CopyOnClick from '@/components/elements/CopyOnClick';
|
|||||||
import DeleteAllocationButton from '@/components/server/network/DeleteAllocationButton';
|
import DeleteAllocationButton from '@/components/server/network/DeleteAllocationButton';
|
||||||
import setPrimaryServerAllocation from '@/api/server/network/setPrimaryServerAllocation';
|
import setPrimaryServerAllocation from '@/api/server/network/setPrimaryServerAllocation';
|
||||||
import getServerAllocations from '@/api/swr/getServerAllocations';
|
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 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`}`;
|
const Label = styled.label`${tw`uppercase text-xs mt-1 text-neutral-400 block px-1 select-none transition-colors duration-150`}`;
|
||||||
@ -66,7 +67,7 @@ const AllocationRow = ({ allocation }: Props) => {
|
|||||||
<div css={tw`mr-4 flex-1 md:w-40`}>
|
<div css={tw`mr-4 flex-1 md:w-40`}>
|
||||||
{allocation.alias ?
|
{allocation.alias ?
|
||||||
<CopyOnClick text={allocation.alias}><Code css={tw`w-40 truncate`}>{allocation.alias}</Code></CopyOnClick> :
|
<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>
|
<Label>{allocation.alias ? 'Hostname' : 'IP Address'}</Label>
|
||||||
</div>
|
</div>
|
||||||
<div css={tw`w-16 md:w-24 overflow-hidden`}>
|
<div css={tw`w-16 md:w-24 overflow-hidden`}>
|
||||||
|
@ -13,6 +13,7 @@ import { LinkButton } from '@/components/elements/Button';
|
|||||||
import ServerContentBlock from '@/components/elements/ServerContentBlock';
|
import ServerContentBlock from '@/components/elements/ServerContentBlock';
|
||||||
import isEqual from 'react-fast-compare';
|
import isEqual from 'react-fast-compare';
|
||||||
import CopyOnClick from '@/components/elements/CopyOnClick';
|
import CopyOnClick from '@/components/elements/CopyOnClick';
|
||||||
|
import { formatIp } from '@/helpers';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
const username = useStoreState(state => state.user.data!.username);
|
const username = useStoreState(state => state.user.data!.username);
|
||||||
@ -30,10 +31,10 @@ export default () => {
|
|||||||
<TitledGreyBox title={'SFTP Details'} css={tw`mb-6 md:mb-10`}>
|
<TitledGreyBox title={'SFTP Details'} css={tw`mb-6 md:mb-10`}>
|
||||||
<div>
|
<div>
|
||||||
<Label>Server Address</Label>
|
<Label>Server Address</Label>
|
||||||
<CopyOnClick text={`sftp://${sftp.ip}:${sftp.port}`}>
|
<CopyOnClick text={`sftp://${formatIp(sftp.ip)}:${sftp.port}`}>
|
||||||
<Input
|
<Input
|
||||||
type={'text'}
|
type={'text'}
|
||||||
value={`sftp://${sftp.ip}:${sftp.port}`}
|
value={`sftp://${formatIp(sftp.ip)}:${sftp.port}`}
|
||||||
readOnly
|
readOnly
|
||||||
/>
|
/>
|
||||||
</CopyOnClick>
|
</CopyOnClick>
|
||||||
@ -59,7 +60,7 @@ export default () => {
|
|||||||
<div css={tw`ml-4`}>
|
<div css={tw`ml-4`}>
|
||||||
<LinkButton
|
<LinkButton
|
||||||
isSecondary
|
isSecondary
|
||||||
href={`sftp://${username}.${id}@${sftp.ip}:${sftp.port}`}
|
href={`sftp://${username}.${id}@${formatIp(sftp.ip)}:${sftp.port}`}
|
||||||
>
|
>
|
||||||
Launch SFTP
|
Launch SFTP
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
|
@ -63,3 +63,7 @@ export function encodePathSegments (path: string): string {
|
|||||||
export function hashToPath (hash: string): string {
|
export function hashToPath (hash: string): string {
|
||||||
return hash.length > 0 ? decodeURIComponent(hash.substr(1)) : '/';
|
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;
|
||||||
|
}
|
||||||
|
@ -10,13 +10,7 @@ export interface Mode {
|
|||||||
|
|
||||||
const modes: Mode[] = [
|
const modes: Mode[] = [
|
||||||
{ name: 'C', mime: 'text/x-csrc', mode: 'clike', ext: [ 'c', 'h', 'ino' ] },
|
{ name: 'C', mime: 'text/x-csrc', mode: 'clike', ext: [ 'c', 'h', 'ino' ] },
|
||||||
{
|
{ name: 'C++', mime: 'text/x-c++src', mode: 'clike', ext: [ 'cpp', 'c++', 'cc', 'cxx', 'hpp', 'h++', 'hh', 'hxx' ], alias: [ 'cpp' ] },
|
||||||
name: 'C++',
|
|
||||||
mime: 'text/x-c++src',
|
|
||||||
mode: 'clike',
|
|
||||||
ext: [ 'cpp', 'c++', 'cc', 'cxx', 'hpp', 'h++', 'hh', 'hxx' ],
|
|
||||||
alias: [ 'cpp' ],
|
|
||||||
},
|
|
||||||
{ name: 'C#', mime: 'text/x-csharp', mode: 'clike', ext: [ 'cs' ], alias: [ 'csharp', 'cs' ] },
|
{ name: 'C#', mime: 'text/x-csharp', mode: 'clike', ext: [ 'cs' ], alias: [ 'csharp', 'cs' ] },
|
||||||
{ name: 'CSS', mime: 'text/css', mode: 'css', ext: [ 'css' ] },
|
{ name: 'CSS', mime: 'text/css', mode: 'css', ext: [ 'css' ] },
|
||||||
{ name: 'CQL', mime: 'text/x-cassandra', mode: 'sql', ext: [ 'cql' ] },
|
{ name: 'CQL', mime: 'text/x-cassandra', mode: 'sql', ext: [ 'cql' ] },
|
||||||
@ -24,99 +18,34 @@ const modes: Mode[] = [
|
|||||||
{ name: 'Dockerfile', mime: 'text/x-dockerfile', mode: 'dockerfile', file: /^Dockerfile$/ },
|
{ name: 'Dockerfile', mime: 'text/x-dockerfile', mode: 'dockerfile', file: /^Dockerfile$/ },
|
||||||
{ name: 'Git Markdown', mime: 'text/x-gfm', mode: 'gfm', file: /^(readme|contributing|history|license).md$/i },
|
{ name: 'Git Markdown', mime: 'text/x-gfm', mode: 'gfm', file: /^(readme|contributing|history|license).md$/i },
|
||||||
{ name: 'Golang', mime: 'text/x-go', mode: 'go', ext: [ 'go' ] },
|
{ name: 'Golang', mime: 'text/x-go', mode: 'go', ext: [ 'go' ] },
|
||||||
{
|
{ name: 'HTML', mime: 'text/html', mode: 'htmlmixed', ext: [ 'html', 'htm', 'handlebars', 'hbs' ], alias: [ 'xhtml' ] },
|
||||||
name: 'HTML',
|
|
||||||
mime: 'text/html',
|
|
||||||
mode: 'htmlmixed',
|
|
||||||
ext: [ 'html', 'htm', 'handlebars', 'hbs' ],
|
|
||||||
alias: [ 'xhtml' ],
|
|
||||||
},
|
|
||||||
{ name: 'HTTP', mime: 'message/http', mode: 'http' },
|
{ name: 'HTTP', mime: 'message/http', mode: 'http' },
|
||||||
{
|
{ name: 'JavaScript', mime: 'text/javascript', mimes: [ 'text/javascript', 'text/ecmascript', 'application/javascript', 'application/x-javascript', 'application/ecmascript' ], mode: 'javascript', ext: [ 'js' ], alias: [ 'ecmascript', 'js', 'node' ] },
|
||||||
name: 'JavaScript',
|
{ name: 'JSON', mime: 'application/json', mimes: [ 'application/json', 'application/x-json' ], mode: 'javascript', ext: [ 'json', 'map' ], alias: [ 'json5' ] },
|
||||||
mime: 'text/javascript',
|
|
||||||
mimes: [ 'text/javascript', 'text/ecmascript', 'application/javascript', 'application/x-javascript', 'application/ecmascript' ],
|
|
||||||
mode: 'javascript',
|
|
||||||
ext: [ 'js' ],
|
|
||||||
alias: [ 'ecmascript', 'js', 'node' ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'JSON',
|
|
||||||
mime: 'application/json',
|
|
||||||
mimes: [ 'application/json', 'application/x-json' ],
|
|
||||||
mode: 'javascript',
|
|
||||||
ext: [ 'json', 'map' ],
|
|
||||||
alias: [ 'json5' ],
|
|
||||||
},
|
|
||||||
{ name: 'Lua', mime: 'text/x-lua', mode: 'lua', ext: [ 'lua' ] },
|
{ name: 'Lua', mime: 'text/x-lua', mode: 'lua', ext: [ 'lua' ] },
|
||||||
{ name: 'Markdown', mime: 'text/x-markdown', mode: 'markdown', ext: [ 'markdown', 'md', 'mkd' ] },
|
{ name: 'Markdown', mime: 'text/x-markdown', mode: 'markdown', ext: [ 'markdown', 'md', 'mkd' ] },
|
||||||
{ name: 'MariaDB', mime: 'text/x-mariadb', mode: 'sql' },
|
{ name: 'MariaDB', mime: 'text/x-mariadb', mode: 'sql' },
|
||||||
{ name: 'MS SQL', mime: 'text/x-mssql', mode: 'sql' },
|
{ name: 'MS SQL', mime: 'text/x-mssql', mode: 'sql' },
|
||||||
{ name: 'MySQL', mime: 'text/x-mysql', mode: 'sql' },
|
{ name: 'MySQL', mime: 'text/x-mysql', mode: 'sql' },
|
||||||
{ name: 'Nginx', mime: 'text/x-nginx-conf', mode: 'nginx', file: /nginx.*\.conf$/i },
|
{ name: 'Nginx', mime: 'text/x-nginx-conf', mode: 'nginx', file: /nginx.*\.conf$/i },
|
||||||
{
|
{ name: 'PHP', mime: 'text/x-php', mimes: [ 'text/x-php', 'application/x-httpd-php', 'application/x-httpd-php-open' ], mode: 'php', ext: [ 'php', 'php3', 'php4', 'php5', 'php7', 'phtml' ] },
|
||||||
name: 'PHP',
|
|
||||||
mime: 'text/x-php',
|
|
||||||
mimes: [ 'text/x-php', 'application/x-httpd-php', 'application/x-httpd-php-open' ],
|
|
||||||
mode: 'php',
|
|
||||||
ext: [ 'php', 'php3', 'php4', 'php5', 'php7', 'phtml' ],
|
|
||||||
},
|
|
||||||
{ name: 'Plain Text', mime: 'text/plain', mode: 'null', ext: [ 'txt', 'text', 'conf', 'def', 'list', 'log' ] },
|
{ name: 'Plain Text', mime: 'text/plain', mode: 'null', ext: [ 'txt', 'text', 'conf', 'def', 'list', 'log' ] },
|
||||||
{ name: 'PostgreSQL', mime: 'text/x-pgsql', mode: 'sql' },
|
{ name: 'PostgreSQL', mime: 'text/x-pgsql', mode: 'sql' },
|
||||||
{
|
{ name: 'Properties', mime: 'text/x-properties', mode: 'properties', ext: [ 'properties', 'ini', 'in' ], alias: [ 'ini', 'properties' ] },
|
||||||
name: 'Properties',
|
{ name: 'Pug', mime: 'text/x-pug', mimes: [ 'text/x-pug', 'text/x-jade' ], mode: 'null', ext: [ 'pug' ] },
|
||||||
mime: 'text/x-properties',
|
{ name: 'Python', mime: 'text/x-python', mode: 'python', ext: [ 'BUILD', 'bzl', 'py', 'pyw' ], file: /^(BUCK|BUILD)$/ },
|
||||||
mode: 'properties',
|
{ name: 'Ruby', mime: 'text/x-ruby', mode: 'ruby', ext: [ 'rb' ], alias: [ 'jruby', 'macruby', 'rake', 'rb', 'rbx' ] },
|
||||||
ext: [ 'properties', 'ini', 'in' ],
|
|
||||||
alias: [ 'ini', 'properties' ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Python',
|
|
||||||
mime: 'text/x-python',
|
|
||||||
mode: 'python',
|
|
||||||
ext: [ 'BUILD', 'bzl', 'py', 'pyw' ],
|
|
||||||
file: /^(BUCK|BUILD)$/,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Ruby',
|
|
||||||
mime: 'text/x-ruby',
|
|
||||||
mode: 'ruby',
|
|
||||||
ext: [ 'rb' ],
|
|
||||||
alias: [ 'jruby', 'macruby', 'rake', 'rb', 'rbx' ],
|
|
||||||
},
|
|
||||||
{ name: 'Rust', mime: 'text/x-rustsrc', mode: 'rust', ext: [ 'rs' ] },
|
{ name: 'Rust', mime: 'text/x-rustsrc', mode: 'rust', ext: [ 'rs' ] },
|
||||||
{ name: 'Sass', mime: 'text/x-sass', mode: 'sass', ext: [ 'sass' ] },
|
{ name: 'Sass', mime: 'text/x-sass', mode: 'sass', ext: [ 'sass' ] },
|
||||||
{ name: 'SCSS', mime: 'text/x-scss', mode: 'css', ext: [ 'scss' ] },
|
{ name: 'SCSS', mime: 'text/x-scss', mode: 'css', ext: [ 'scss' ] },
|
||||||
{
|
{ name: 'Shell', mime: 'text/x-sh', mimes: [ 'text/x-sh', 'application/x-sh' ], mode: 'shell', ext: [ 'sh', 'ksh', 'bash' ], alias: [ 'bash', 'sh', 'zsh' ], file: /^PKGBUILD$/ },
|
||||||
name: 'Shell',
|
|
||||||
mime: 'text/x-sh',
|
|
||||||
mimes: [ 'text/x-sh', 'application/x-sh' ],
|
|
||||||
mode: 'shell',
|
|
||||||
ext: [ 'sh', 'ksh', 'bash' ],
|
|
||||||
alias: [ 'bash', 'sh', 'zsh' ],
|
|
||||||
file: /^PKGBUILD$/,
|
|
||||||
},
|
|
||||||
{ name: 'SQL', mime: 'text/x-sql', mode: 'sql', ext: [ 'sql' ] },
|
{ name: 'SQL', mime: 'text/x-sql', mode: 'sql', ext: [ 'sql' ] },
|
||||||
{ name: 'SQLite', mime: 'text/x-sqlite', mode: 'sql' },
|
{ name: 'SQLite', mime: 'text/x-sqlite', mode: 'sql' },
|
||||||
{ name: 'TOML', mime: 'text/x-toml', mode: 'toml', ext: [ 'toml' ] },
|
{ name: 'TOML', mime: 'text/x-toml', mode: 'toml', ext: [ 'toml' ] },
|
||||||
{ name: 'TypeScript', mime: 'application/typescript', mode: 'javascript', ext: [ 'ts' ], alias: [ 'ts' ] },
|
{ name: 'TypeScript', mime: 'application/typescript', mode: 'javascript', ext: [ 'ts' ], alias: [ 'ts' ] },
|
||||||
{ name: 'Vue', mime: 'script/x-vue', mimes: [ 'script/x-vue', 'text/x-vue' ], mode: 'vue', ext: [ 'vue' ] },
|
{ name: 'Vue', mime: 'script/x-vue', mimes: [ 'script/x-vue', 'text/x-vue' ], mode: 'vue', ext: [ 'vue' ] },
|
||||||
{
|
{ name: 'XML', mime: 'application/xml', mimes: [ 'application/xml', 'text/xml' ], mode: 'xml', ext: [ 'xml', 'xsl', 'xsd', 'svg' ], alias: [ 'rss', 'wsdl', 'xsd' ] },
|
||||||
name: 'XML',
|
{ name: 'YAML', mime: 'text/x-yaml', mimes: [ 'text/x-yaml', 'text/yaml' ], mode: 'yaml', ext: [ 'yaml', 'yml' ], alias: [ 'yml' ] },
|
||||||
mime: 'application/xml',
|
|
||||||
mimes: [ 'application/xml', 'text/xml' ],
|
|
||||||
mode: 'xml',
|
|
||||||
ext: [ 'xml', 'xsl', 'xsd', 'svg' ],
|
|
||||||
alias: [ 'rss', 'wsdl', 'xsd' ],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'YAML',
|
|
||||||
mime: 'text/x-yaml',
|
|
||||||
mimes: [ 'text/x-yaml', 'text/yaml' ],
|
|
||||||
mode: 'yaml',
|
|
||||||
ext: [ 'yaml', 'yml' ],
|
|
||||||
alias: [ 'yml' ],
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
|
|
||||||
export default modes;
|
export default modes;
|
||||||
|
@ -5,6 +5,7 @@ namespace Pterodactyl\Tests\Integration\Api\Application\Location;
|
|||||||
use Pterodactyl\Models\Node;
|
use Pterodactyl\Models\Node;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Pterodactyl\Models\Location;
|
use Pterodactyl\Models\Location;
|
||||||
|
use Pterodactyl\Transformers\Api\Application\LocationTransformer;
|
||||||
use Pterodactyl\Transformers\Api\Application\NodeTransformer;
|
use Pterodactyl\Transformers\Api\Application\NodeTransformer;
|
||||||
use Pterodactyl\Transformers\Api\Application\ServerTransformer;
|
use Pterodactyl\Transformers\Api\Application\ServerTransformer;
|
||||||
use Pterodactyl\Tests\Integration\Api\Application\ApplicationApiIntegrationTestCase;
|
use Pterodactyl\Tests\Integration\Api\Application\ApplicationApiIntegrationTestCase;
|
||||||
@ -88,6 +89,77 @@ class LocationControllerTest extends ApplicationApiIntegrationTestCase
|
|||||||
], true);
|
], 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.
|
* Test that all of the defined relationships for a location can be loaded successfully.
|
||||||
*/
|
*/
|
||||||
|
@ -8040,10 +8040,10 @@ xterm-addon-web-links@^0.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0.tgz#265cbf8221b9b315d0a748e1323bee331cd5da03"
|
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0.tgz#265cbf8221b9b315d0a748e1323bee331cd5da03"
|
||||||
integrity sha512-xv8GeiINmx0zENO9hf5k+5bnkaE8mRzF+OBAr9WeFq2eLaQSudioQSiT34M1ofKbzcdjSsKiZm19Rw3i4eXamg==
|
integrity sha512-xv8GeiINmx0zENO9hf5k+5bnkaE8mRzF+OBAr9WeFq2eLaQSudioQSiT34M1ofKbzcdjSsKiZm19Rw3i4eXamg==
|
||||||
|
|
||||||
xterm@^4.12.0:
|
xterm@^4.15.0:
|
||||||
version "4.12.0"
|
version "4.15.0"
|
||||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.12.0.tgz#db09b425b4dcae5b96f8cbbaaa93b3bc60997ca9"
|
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.15.0.tgz#e52038507eba7e0d36d47f81e29fe548c82b9561"
|
||||||
integrity sha512-K5mF/p3txUV18mjiZFlElagoHFpqXrm5OYHeoymeXSu8GG/nMaOO/+NRcNCwfdjzAbdQ5VLF32hEHiWWKKm0bw==
|
integrity sha512-Ik1GoSq1yqKZQ2LF37RPS01kX9t4TP8gpamUYblD09yvWX5mEYuMK4CcqH6+plgiNEZduhTz/UrcaWs97gOlOw==
|
||||||
|
|
||||||
y18n@^4.0.0:
|
y18n@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
|
Loading…
Reference in New Issue
Block a user