From a775f3ccf2189ded8726b98f47da20faa1b7787f Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 11 Sep 2021 21:45:48 +0300 Subject: [PATCH 1/8] egg(ark): Fix inverted OR operation (#3605) --- .../Seeders/eggs/source-engine/egg-ark--survival-evolved.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/database/Seeders/eggs/source-engine/egg-ark--survival-evolved.json b/database/Seeders/eggs/source-engine/egg-ark--survival-evolved.json index 172a9824a..012bf62f7 100644 --- a/database/Seeders/eggs/source-engine/egg-ark--survival-evolved.json +++ b/database/Seeders/eggs/source-engine/egg-ark--survival-evolved.json @@ -4,7 +4,7 @@ "version": "PTDL_v1", "update_url": null }, - "exported_at": "2021-07-27T14:14:20+03:00", + "exported_at": "2021-09-11T14:35:10-04:00", "name": "Ark: Survival Evolved", "author": "dev@shepper.fr", "description": "As a man or woman stranded, naked, freezing, and starving on the unforgiving shores of a mysterious island called ARK, use your skill and cunning to kill or tame and ride the plethora of leviathan dinosaurs and other primeval creatures roaming the land. Hunt, harvest resources, craft items, grow crops, research technologies, and build shelters to withstand the elements and store valuables, all while teaming up with (or preying upon) hundreds of other players to survive, dominate... and escape! \u2014 Gamepedia: ARK", @@ -13,7 +13,7 @@ "quay.io\/parkervcp\/pterodactyl-images:debian_source" ], "file_denylist": [], - "startup": "rmv() { echo -e \"stopping server\"; rcon -t rcon -a 127.0.0.1:${RCON_PORT} -p ${ARK_ADMIN_PASSWORD} -c saveworld && rcon -a 127.0.0.1:${RCON_PORT} -p ${ARK_ADMIN_PASSWORD} -c DoExit; }; trap rmv 15; cd ShooterGame\/Binaries\/Linux && .\/ShooterGameServer {{SERVER_MAP}}?listen?SessionName=\"{{SESSION_NAME}}\"?ServerPassword={{ARK_PASSWORD}}?ServerAdminPassword={{ARK_ADMIN_PASSWORD}}?Port={{SERVER_PORT}}?RCONPort={{RCON_PORT}}?QueryPort={{QUERY_PORT}}?RCONEnabled=True$( [ \"$BATTLE_EYE\" == \"0\" ] || printf %s '?-NoBattlEye' ) -server {{ARGS}} -log & until echo \"waiting for rcon connection...\"; rcon -t rcon -a 127.0.0.1:${RCON_PORT} -p ${ARK_ADMIN_PASSWORD}; do sleep 5; done", + "startup": "rmv() { echo -e \"stopping server\"; rcon -t rcon -a 127.0.0.1:${RCON_PORT} -p ${ARK_ADMIN_PASSWORD} -c saveworld && rcon -a 127.0.0.1:${RCON_PORT} -p ${ARK_ADMIN_PASSWORD} -c DoExit; }; trap rmv 15; cd ShooterGame\/Binaries\/Linux && .\/ShooterGameServer {{SERVER_MAP}}?listen?SessionName=\"{{SESSION_NAME}}\"?ServerPassword={{ARK_PASSWORD}}?ServerAdminPassword={{ARK_ADMIN_PASSWORD}}?Port={{SERVER_PORT}}?RCONPort={{RCON_PORT}}?QueryPort={{QUERY_PORT}}?RCONEnabled=True$( [ \"$BATTLE_EYE\" == \"1\" ] || printf %s ' -NoBattlEye' ) -server {{ARGS}} -log & until echo \"waiting for rcon connection...\"; rcon -t rcon -a 127.0.0.1:${RCON_PORT} -p ${ARK_ADMIN_PASSWORD}; do sleep 5; done", "config": { "files": "{}", "startup": "{\r\n \"done\": \"Waiting commands for 127.0.0.1:\"\r\n}", From fde0660e6cf3f9a6ee99f8f5a767fcb5250f5815 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 11 Sep 2021 12:02:15 -0700 Subject: [PATCH 2/8] Return tests to passing state --- .../Servers/BuildModificationServiceTest.php | 30 +++++-------------- .../Servers/ServerCreationServiceTest.php | 21 ++++--------- .../Servers/SuspensionServiceTest.php | 11 ++----- 3 files changed, 17 insertions(+), 45 deletions(-) diff --git a/tests/Integration/Services/Servers/BuildModificationServiceTest.php b/tests/Integration/Services/Servers/BuildModificationServiceTest.php index 88be5d8fc..cadc9276d 100644 --- a/tests/Integration/Services/Servers/BuildModificationServiceTest.php +++ b/tests/Integration/Services/Servers/BuildModificationServiceTest.php @@ -26,8 +26,7 @@ class BuildModificationServiceTest extends IntegrationTestCase { parent::setUp(); - $this->daemonServerRepository = Mockery::mock(DaemonServerRepository::class); - $this->swap(DaemonServerRepository::class, $this->daemonServerRepository); + $this->daemonServerRepository = $this->mock(DaemonServerRepository::class); } /** @@ -50,7 +49,7 @@ class BuildModificationServiceTest extends IntegrationTestCase $allocations[2]->update(['server_id' => $server2->id]); $allocations[3]->update(['server_id' => $server2->id]); - $this->daemonServerRepository->expects('setServer->update')->andReturnUndefined(); + $this->daemonServerRepository->expects('setServer->sync')->andReturnUndefined(); $response = $this->getService()->handle($server, [ // Attempt to add one new allocation, and an allocation assigned to another server. The @@ -113,20 +112,7 @@ class BuildModificationServiceTest extends IntegrationTestCase return $s->id === $server->id; }))->andReturnSelf(); - $this->daemonServerRepository->expects('update')->with(Mockery::on(function ($data) { - $this->assertEquals([ - 'build' => [ - 'memory_limit' => 256, - 'swap' => 128, - 'io_weight' => 600, - 'cpu_limit' => 150, - 'threads' => '1,2', - 'disk_space' => 1024, - ], - ], $data); - - return true; - }))->andReturnUndefined(); + $this->daemonServerRepository->expects('sync')->withNoArgs()->andReturnUndefined(); $response = $this->getService()->handle($server, [ 'oom_disabled' => false, @@ -162,7 +148,7 @@ class BuildModificationServiceTest extends IntegrationTestCase { $server = $this->createServerModel(); - $this->daemonServerRepository->expects('setServer->update')->andThrows( + $this->daemonServerRepository->expects('setServer->sync')->andThrows( new DaemonConnectionException( new RequestException('Bad request', new Request('GET', '/test'), new Response()) ) @@ -186,7 +172,7 @@ class BuildModificationServiceTest extends IntegrationTestCase /** @var \Pterodactyl\Models\Allocation $allocation */ $allocation = Allocation::factory()->create(['node_id' => $server->node_id, 'server_id' => $server->id]); - $this->daemonServerRepository->expects('setServer->update')->andReturnUndefined(); + $this->daemonServerRepository->expects('setServer->sync')->andReturnUndefined(); $this->getService()->handle($server, [ 'remove_allocations' => [$allocation->id], @@ -209,7 +195,7 @@ class BuildModificationServiceTest extends IntegrationTestCase /** @var \Pterodactyl\Models\Allocation $allocation */ $allocation = Allocation::factory()->create(['node_id' => $server->node_id]); - $this->daemonServerRepository->expects('setServer->update')->andReturnUndefined(); + $this->daemonServerRepository->expects('setServer->sync')->andReturnUndefined(); $this->getService()->handle($server, [ 'add_allocations' => [$allocation->id], @@ -230,7 +216,7 @@ class BuildModificationServiceTest extends IntegrationTestCase /** @var \Pterodactyl\Models\Allocation $allocation2 */ $allocation2 = Allocation::factory()->create(['node_id' => $server->node_id]); - $this->daemonServerRepository->expects('setServer->update')->andReturnUndefined(); + $this->daemonServerRepository->expects('setServer->sync')->andReturnUndefined(); $this->getService()->handle($server, [ 'add_allocations' => [$allocation2->id, $allocation2->id], @@ -253,7 +239,7 @@ class BuildModificationServiceTest extends IntegrationTestCase /** @var \Pterodactyl\Models\Allocation $allocation */ $allocation = Allocation::factory()->create(['node_id' => $server->node_id]); - $this->daemonServerRepository->expects('setServer->update')->andThrows(new DisplayException('Test')); + $this->daemonServerRepository->expects('setServer->sync')->andThrows(new DisplayException('Test')); $this->expectException(DisplayException::class); diff --git a/tests/Integration/Services/Servers/ServerCreationServiceTest.php b/tests/Integration/Services/Servers/ServerCreationServiceTest.php index c622359e9..329e3be1d 100644 --- a/tests/Integration/Services/Servers/ServerCreationServiceTest.php +++ b/tests/Integration/Services/Servers/ServerCreationServiceTest.php @@ -67,7 +67,6 @@ class ServerCreationServiceTest extends IntegrationTestCase $allocations[0]->port, ]); - /** @noinspection PhpParamsInspection */ $egg = $this->cloneEggAndVariables(Egg::query()->findOrFail(1)); // We want to make sure that the validator service runs as an admin, and not as a regular // user when saving variables. @@ -94,19 +93,10 @@ class ServerCreationServiceTest extends IntegrationTestCase 'BUNGEE_VERSION' => '123', 'SERVER_JARFILE' => 'server2.jar', ], + 'start_on_completion' => true, ]; - $this->daemonServerRepository->expects('setServer')->andReturnSelf(); - $this->daemonServerRepository->expects('create')->with(Mockery::on(function ($value) { - $this->assertIsArray($value); - // Just check for some keys to make sure we're getting the expected configuration - // structure back. Other tests exist to confirm it is the correct structure. - $this->assertArrayHasKey('uuid', $value); - $this->assertArrayHasKey('environment', $value); - $this->assertArrayHasKey('invocation', $value); - - return true; - }))->andReturnUndefined(); + $this->daemonServerRepository->expects('setServer->create')->with(true)->andReturnUndefined(); try { $this->getService()->handle(array_merge($data, [ @@ -115,7 +105,8 @@ class ServerCreationServiceTest extends IntegrationTestCase 'SERVER_JARFILE' => 'server2.jar', ], ]), $deployment); - $this->assertTrue(false, 'This statement should not be reached.'); + + $this->fail('This execution pathway should not be reached.'); } catch (ValidationException $exception) { $this->assertCount(1, $exception->errors()); $this->assertArrayHasKey('environment.BUNGEE_VERSION', $exception->errors()); @@ -133,11 +124,11 @@ class ServerCreationServiceTest extends IntegrationTestCase $this->assertSame('server2.jar', $response->variables[1]->server_value); foreach ($data as $key => $value) { - if (in_array($key, ['allocation_additional', 'environment'])) { + if (in_array($key, ['allocation_additional', 'environment', 'start_on_completion'])) { continue; } - $this->assertSame($value, $response->{$key}); + $this->assertSame($value, $response->{$key}, "Failed asserting equality of '$key' in server response. Got: [{$response->{$key}}] Expected: [$value]"); } $this->assertCount(2, $response->allocations); diff --git a/tests/Integration/Services/Servers/SuspensionServiceTest.php b/tests/Integration/Services/Servers/SuspensionServiceTest.php index 61d018364..258a8ca2e 100644 --- a/tests/Integration/Services/Servers/SuspensionServiceTest.php +++ b/tests/Integration/Services/Servers/SuspensionServiceTest.php @@ -29,20 +29,15 @@ class SuspensionServiceTest extends IntegrationTestCase { $server = $this->createServerModel(); - $this->repository->expects('setServer')->twice()->andReturnSelf(); - $this->repository->expects('suspend')->with(false)->andReturnUndefined(); + $this->repository->expects('setServer->sync')->twice()->andReturnSelf(); $this->getService()->toggle($server, SuspensionService::ACTION_SUSPEND); - $server->refresh(); - $this->assertTrue($server->isSuspended()); - - $this->repository->expects('suspend')->with(true)->andReturnUndefined(); + $this->assertTrue($server->refresh()->isSuspended()); $this->getService()->toggle($server, SuspensionService::ACTION_UNSUSPEND); - $server->refresh(); - $this->assertFalse($server->isSuspended()); + $this->assertFalse($server->refresh()->isSuspended()); } public function testNoActionIsTakenIfSuspensionStatusIsUnchanged() From 0b521c011f097680d7a3f2add1f75d28e9a7cf1b Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 11 Sep 2021 12:13:15 -0700 Subject: [PATCH 3/8] Fix test workflow matrix for databases --- .github/workflows/tests.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index d07844386..2ec6523c3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -46,8 +46,6 @@ jobs: ~/.php_cs.cache ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-cache-${{ matrix.php }}-${{ hashFiles('**.composer.lock') }} - restore-keys: | - ${{ runner.os }}-cache-${{ matrix.php }}- - name: setup uses: shivammathur/setup-php@v2 with: @@ -63,20 +61,20 @@ jobs: run: vendor/bin/php-cs-fixer fix --dry-run --diff --diff-format=udiff --config .php_cs.dist continue-on-error: true - name: execute unit tests - run: vendor/bin/phpunit --bootstrap bootstrap/app.php tests/Unit + run: vendor/bin/phpunit --bootstrap vendor/autoload.php tests/Unit if: ${{ always() }} env: DB_CONNECTION: testing TESTING_DB_HOST: UNIT_NO_DB - name: execute integration tests (mysql) run: vendor/bin/phpunit tests/Integration - if: "${{ matrix.database }} == 'mysql'" + if: ${{ matrix.database == 'mysql' }} env: TESTING_DB_PORT: ${{ job.services.mysql.ports[3306] }} TESTING_DB_USERNAME: root - name: execute integration tests (mariadb) run: vendor/bin/phpunit tests/Integration - if: "${{ matrix.database }} == 'mariadb'" + if: ${{ matrix.database == 'mariadb' }} env: TESTING_DB_PORT: ${{ job.services.mariadb.ports[3306] }} TESTING_DB_USERNAME: root From 4d7140bd3bc8ba0ca617b1f16c4511e0976328c8 Mon Sep 17 00:00:00 2001 From: Matthew Penner Date: Sat, 11 Sep 2021 13:20:04 -0600 Subject: [PATCH 4/8] actions(tests): backport v2 workflow (#3558) Co-authored-by: Dane Everitt --- .github/workflows/tests.yml | 71 +++++++++++++------------------------ 1 file changed, 25 insertions(+), 46 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 2ec6523c3..a59f99a47 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -1,64 +1,50 @@ -name: run tests +name: Run Tests on: push: - branches-ignore: - - master - - "release/**" + branches: + - 'develop' + - 'v2' pull_request: jobs: tests: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 if: "!contains(github.event.head_commit.message, 'skip ci') && !contains(github.event.head_commit.message, 'ci skip')" - services: - mariadb: - image: mariadb:10.2 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_DATABASE: panel_test - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 - mysql: - image: mysql:8 - env: - MYSQL_ALLOW_EMPTY_PASSWORD: yes - MYSQL_DATABASE: panel_test - ports: - - 3306 - options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 strategy: fail-fast: false matrix: php: [ 7.4, 8.0 ] - database: [ mysql, mariadb ] - name: "php-${{ matrix.php }} (engine: ${{ matrix.database }})" + database: [ 'mariadb:10.2', 'mysql:8' ] + services: + database: + image: ${{ matrix.database }} + env: + MYSQL_ALLOW_EMPTY_PASSWORD: yes + MYSQL_DATABASE: panel_test + ports: + - 3306 + options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3 + name: "php-${{ matrix.php }} (${{ matrix.database }})" steps: - - name: checkout - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - name: get cache directory id: composer-cache run: | echo "::set-output name=dir::$(composer config cache-files-dir)" - - name: cache dependencies - uses: actions/cache@v2 + - uses: actions/cache@v2 with: path: | ~/.php_cs.cache ${{ steps.composer-cache.outputs.dir }} key: ${{ runner.os }}-cache-${{ matrix.php }}-${{ hashFiles('**.composer.lock') }} - - name: setup - uses: shivammathur/setup-php@v2 + - uses: shivammathur/setup-php@v2 with: php-version: ${{ matrix.php }} - extensions: cli, openssl, gd, mysql, pdo, mbstring, tokenizer, bcmath, xml, curl, zip + extensions: bcmath, cli, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip tools: composer:v2 coverage: none - - name: configure - run: cp .env.ci .env - - name: install dependencies - run: composer install --prefer-dist --no-interaction --no-progress - - name: run cs-fixer - run: vendor/bin/php-cs-fixer fix --dry-run --diff --diff-format=udiff --config .php_cs.dist + - run: cp .env.ci .env + - run: composer install --prefer-dist --no-interaction --no-progress + - run: vendor/bin/php-cs-fixer fix --dry-run --diff --diff-format=udiff --config .php-cs-fixer.dist.php continue-on-error: true - name: execute unit tests run: vendor/bin/phpunit --bootstrap vendor/autoload.php tests/Unit @@ -66,15 +52,8 @@ jobs: env: DB_CONNECTION: testing TESTING_DB_HOST: UNIT_NO_DB - - name: execute integration tests (mysql) + - name: execute integration tests run: vendor/bin/phpunit tests/Integration - if: ${{ matrix.database == 'mysql' }} env: - TESTING_DB_PORT: ${{ job.services.mysql.ports[3306] }} - TESTING_DB_USERNAME: root - - name: execute integration tests (mariadb) - run: vendor/bin/phpunit tests/Integration - if: ${{ matrix.database == 'mariadb' }} - env: - TESTING_DB_PORT: ${{ job.services.mariadb.ports[3306] }} + TESTING_DB_PORT: ${{ job.services.database.ports[3306] }} TESTING_DB_USERNAME: root From 5e5d7d6689de07b35af84135576379793990d8fd Mon Sep 17 00:00:00 2001 From: Boy132 Date: Sat, 11 Sep 2021 21:20:15 +0200 Subject: [PATCH 5/8] Update egg-garrys-mod.json (#3606) Co-authored-by: Dane Everitt --- .../eggs/source-engine/egg-garrys-mod.json | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/database/Seeders/eggs/source-engine/egg-garrys-mod.json b/database/Seeders/eggs/source-engine/egg-garrys-mod.json index 84b4dc812..93de416a6 100644 --- a/database/Seeders/eggs/source-engine/egg-garrys-mod.json +++ b/database/Seeders/eggs/source-engine/egg-garrys-mod.json @@ -4,7 +4,7 @@ "version": "PTDL_v1", "update_url": null }, - "exported_at": "2021-06-05T16:28:06-04:00", + "exported_at": "2021-08-27T00:12:31-04: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.", @@ -13,16 +13,16 @@ "ghcr.io\/pterodactyl\/games:source" ], "file_denylist": [], - "startup": ".\/srcds_run -game garrysmod -console -port {{SERVER_PORT}} +ip 0.0.0.0 +host_workshop_collection {{WORKSHOP_ID}} +map {{SRCDS_MAP}} +gamemode {{GAMEMODE}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}} +maxplayers {{MAX_PLAYERS}} -tickrate {{TICKRATE}}", + "startup": ".\/srcds_run -game garrysmod -console -port {{SERVER_PORT}} +ip 0.0.0.0 +host_workshop_collection {{WORKSHOP_ID}} +map {{SRCDS_MAP}} +gamemode {{GAMEMODE}} -strictportbind -norestart +sv_setsteamaccount {{STEAM_ACC}} +maxplayers {{MAX_PLAYERS}} -tickrate {{TICKRATE}} $( [ \"$LUA_REFRESH\" == \"1\" ] || printf %s '-disableluarefresh' )", "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\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\n\r\n\/\/ Steam Server List Settings\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# 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", "container": "ghcr.io\/pterodactyl\/installers:debian", "entrypoint": "bash" } @@ -90,6 +90,15 @@ "user_viewable": true, "user_editable": true, "rules": "required|integer|max:100" + }, + { + "name": "Lua Refresh", + "description": "0 = disable Lua refresh,\r\n1 = enable Lua refresh", + "env_variable": "LUA_REFRESH", + "default_value": "0", + "user_viewable": true, + "user_editable": true, + "rules": "required|boolean" } ] -} \ No newline at end of file +} From 7b429831ce9b59b75d85b225a1f24ff31e3c88be Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 11 Sep 2021 13:00:53 -0700 Subject: [PATCH 6/8] Fix missing user agent headers to store an empty string rather than null value --- app/Models/AuditLog.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Models/AuditLog.php b/app/Models/AuditLog.php index 1cd942e95..eb306da9c 100644 --- a/app/Models/AuditLog.php +++ b/app/Models/AuditLog.php @@ -120,8 +120,8 @@ class AuditLog extends Model 'server_id' => null, 'action' => $action, 'device' => $request ? [ - 'ip_address' => $request->getClientIp(), - 'user_agent' => $request->userAgent(), + 'ip_address' => $request->getClientIp() ?? '127.0.0.1', + 'user_agent' => $request->userAgent() ?? '', ] : [], 'metadata' => $metadata, ]); From 52588beeb0c116af68c68fccd5957f21a8af918c Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 11 Sep 2021 13:24:57 -0700 Subject: [PATCH 7/8] Fix state management of overrides not properly resetting loader; closes #3429 --- resources/scripts/hoc/asModal.tsx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/resources/scripts/hoc/asModal.tsx b/resources/scripts/hoc/asModal.tsx index 876037a69..bb947e7c7 100644 --- a/resources/scripts/hoc/asModal.tsx +++ b/resources/scripts/hoc/asModal.tsx @@ -13,7 +13,6 @@ export type SettableModalProps = Omit; } @@ -31,7 +30,6 @@ function asModal

(modalProps?: SettableModalProps | ((props: P) => this.state = { render: props.visible, visible: props.visible, - showSpinnerOverlay: undefined, propOverrides: {}, }; } @@ -39,7 +37,6 @@ function asModal

(modalProps?: SettableModalProps | ((props: P) => get computedModalProps (): Readonly { return { ...(typeof modalProps === 'function' ? modalProps(this.props) : modalProps), - showSpinnerOverlay: this.state.showSpinnerOverlay, ...this.state.propOverrides, visible: this.state.visible, }; @@ -50,7 +47,7 @@ function asModal

(modalProps?: SettableModalProps | ((props: P) => */ componentDidUpdate (prevProps: Readonly

, prevState: Readonly) { if (prevProps.visible && !this.props.visible) { - this.setState({ visible: false, showSpinnerOverlay: false }); + this.setState({ visible: false, propOverrides: {} }); } else if (!prevProps.visible && this.props.visible) { this.setState({ render: true, visible: true }); } From 8f0eda21c58cdce2a697b0eae44fee5c19bc6024 Mon Sep 17 00:00:00 2001 From: Dane Everitt Date: Sat, 11 Sep 2021 14:17:20 -0700 Subject: [PATCH 8/8] Fix all screens on the panel unintentionally loading the root directory for a server --- resources/scripts/components/server/InstallListener.tsx | 6 +++--- resources/scripts/plugins/useFileManagerSwr.ts | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/resources/scripts/components/server/InstallListener.tsx b/resources/scripts/components/server/InstallListener.tsx index c0a7f6ac8..fbf377a2c 100644 --- a/resources/scripts/components/server/InstallListener.tsx +++ b/resources/scripts/components/server/InstallListener.tsx @@ -1,16 +1,16 @@ import useWebsocketEvent from '@/plugins/useWebsocketEvent'; import { ServerContext } from '@/state/server'; import { SocketEvent } from '@/components/server/events'; -import useFileManagerSwr from '@/plugins/useFileManagerSwr'; +import { mutate } from 'swr'; +import { getDirectorySwrKey } from '@/plugins/useFileManagerSwr'; const InstallListener = () => { const uuid = ServerContext.useStoreState(state => state.server.data!.uuid); const getServer = ServerContext.useStoreActions(actions => actions.server.getServer); - const { mutate } = useFileManagerSwr(); const setServerFromState = ServerContext.useStoreActions(actions => actions.server.setServerFromState); useWebsocketEvent(SocketEvent.BACKUP_RESTORE_COMPLETED, () => { - mutate(undefined); + mutate(getDirectorySwrKey(uuid, '/'), undefined); setServerFromState(s => ({ ...s, status: null })); }); diff --git a/resources/scripts/plugins/useFileManagerSwr.ts b/resources/scripts/plugins/useFileManagerSwr.ts index 390ce839b..e134cb402 100644 --- a/resources/scripts/plugins/useFileManagerSwr.ts +++ b/resources/scripts/plugins/useFileManagerSwr.ts @@ -3,12 +3,14 @@ import loadDirectory, { FileObject } from '@/api/server/files/loadDirectory'; import { cleanDirectoryPath } from '@/helpers'; import { ServerContext } from '@/state/server'; +export const getDirectorySwrKey = (uuid: string, directory: string): string => `${uuid}:files:${directory}`; + export default () => { const uuid = ServerContext.useStoreState(state => state.server.data!.uuid); const directory = ServerContext.useStoreState(state => state.files.directory); return useSWR( - `${uuid}:files:${directory}`, + getDirectorySwrKey(uuid, directory), () => loadDirectory(uuid, cleanDirectoryPath(directory)), { focusThrottleInterval: 30000,