diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e9e805e..4f65904c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,32 @@ This file is a running track of new features and fixes to each version of the pa This project follows [Semantic Versioning](http://semver.org) guidelines. +## v1.11.7 + +### Added + +* Java 21 to Minecraft eggs + +### Changed + +* Updated Minecraft EULA link + +### Fixed + +* Fixed backups not ever being marked as completed (#5088) +* Fixed `.7z` files not being detected as a compressed file (#5016) + +## v1.11.6 + +### Changed + +* Better node ownership checks for internal backup endpoints +* Improved validation rules on `docker_image` fields to prevent invalid inputs + +### Fixed + +* Multiple XSS vulnerabilities in the admin area ([GHSA-384w-wffr-x63q](https://github.com/pterodactyl/panel/security/advisories/GHSA-384w-wffr-x63q)) + ## v1.11.5 ### Fixed * Rust egg using the wrong Docker image, breaking Rust modding frameworks. diff --git a/SECURITY.md b/SECURITY.md index e5a9eb0f..96c06847 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,7 +6,6 @@ The following versions of Pterodactyl are receiving active support and maintenan | Panel | Daemon | Supported | |--------|--------------|--------------------| -| 1.10.x | wings@1.7.x | :white_check_mark: | | 1.11.x | wings@1.11.x | :white_check_mark: | | 0.7.x | daemon@0.6.x | :x: | diff --git a/app/Http/Controllers/Admin/Nests/EggVariableController.php b/app/Http/Controllers/Admin/Nests/EggVariableController.php index 40274b32..2b84e8b0 100644 --- a/app/Http/Controllers/Admin/Nests/EggVariableController.php +++ b/app/Http/Controllers/Admin/Nests/EggVariableController.php @@ -69,7 +69,7 @@ class EggVariableController extends Controller { $this->updateService->handle($variable, $request->normalize()); $this->alert->success(trans('admin/nests.variables.notices.variable_updated', [ - 'variable' => $variable->name, + 'variable' => htmlspecialchars($variable->name), ]))->flash(); return redirect()->route('admin.nests.egg.variables', $egg->id); @@ -82,7 +82,7 @@ class EggVariableController extends Controller { $this->variableRepository->delete($variable->id); $this->alert->success(trans('admin/nests.variables.notices.variable_deleted', [ - 'variable' => $variable->name, + 'variable' => htmlspecialchars($variable->name), ]))->flash(); return redirect()->route('admin.nests.egg.variables', $egg); diff --git a/app/Http/Controllers/Admin/Nests/NestController.php b/app/Http/Controllers/Admin/Nests/NestController.php index 037dd094..311a5df2 100644 --- a/app/Http/Controllers/Admin/Nests/NestController.php +++ b/app/Http/Controllers/Admin/Nests/NestController.php @@ -56,7 +56,7 @@ class NestController extends Controller public function store(StoreNestFormRequest $request): RedirectResponse { $nest = $this->nestCreationService->handle($request->normalize()); - $this->alert->success(trans('admin/nests.notices.created', ['name' => $nest->name]))->flash(); + $this->alert->success(trans('admin/nests.notices.created', ['name' => htmlspecialchars($nest->name)]))->flash(); return redirect()->route('admin.nests.view', $nest->id); } diff --git a/app/Http/Controllers/Admin/NodesController.php b/app/Http/Controllers/Admin/NodesController.php index 573a1d9f..71094a51 100644 --- a/app/Http/Controllers/Admin/NodesController.php +++ b/app/Http/Controllers/Admin/NodesController.php @@ -131,7 +131,7 @@ class NodesController extends Controller ['ip', '=', $request->input('ip')], ]); - $this->alert->success(trans('admin/node.notices.unallocated_deleted', ['ip' => $request->input('ip')])) + $this->alert->success(trans('admin/node.notices.unallocated_deleted', ['ip' => htmlspecialchars($request->input('ip'))])) ->flash(); return redirect()->route('admin.nodes.view.allocation', $node); diff --git a/app/Http/Controllers/Api/Remote/Backups/BackupRemoteUploadController.php b/app/Http/Controllers/Api/Remote/Backups/BackupRemoteUploadController.php index 7d92e0b1..15fe8d9b 100644 --- a/app/Http/Controllers/Api/Remote/Backups/BackupRemoteUploadController.php +++ b/app/Http/Controllers/Api/Remote/Backups/BackupRemoteUploadController.php @@ -32,18 +32,32 @@ class BackupRemoteUploadController extends Controller */ public function __invoke(Request $request, string $backup): JsonResponse { + // Get the node associated with the request. + /** @var \Pterodactyl\Models\Node $node */ + $node = $request->attributes->get('node'); + // Get the size query parameter. $size = (int) $request->query('size'); if (empty($size)) { throw new BadRequestHttpException('A non-empty "size" query parameter must be provided.'); } - /** @var \Pterodactyl\Models\Backup $backup */ - $backup = Backup::query()->where('uuid', $backup)->firstOrFail(); + /** @var \Pterodactyl\Models\Backup $model */ + $model = Backup::query() + ->where('uuid', $backup) + ->firstOrFail(); + + // Check that the backup is "owned" by the node making the request. This avoids other nodes + // from messing with backups that they don't own. + /** @var \Pterodactyl\Models\Server $server */ + $server = $model->server; + if ($server->node_id !== $node->id) { + throw new HttpForbiddenException('You do not have permission to access that backup.'); + } // Prevent backups that have already been completed from trying to // be uploaded again. - if (!is_null($backup->completed_at)) { + if (!is_null($model->completed_at)) { throw new ConflictHttpException('This backup is already in a completed state.'); } @@ -54,7 +68,7 @@ class BackupRemoteUploadController extends Controller } // The path where backup will be uploaded to - $path = sprintf('%s/%s.tar.gz', $backup->server->uuid, $backup->uuid); + $path = sprintf('%s/%s.tar.gz', $model->server->uuid, $model->uuid); // Get the S3 client $client = $adapter->getClient(); @@ -92,7 +106,7 @@ class BackupRemoteUploadController extends Controller } // Set the upload_id on the backup in the database. - $backup->update(['upload_id' => $params['UploadId']]); + $model->update(['upload_id' => $params['UploadId']]); return new JsonResponse([ 'parts' => $parts, diff --git a/app/Http/Controllers/Api/Remote/Backups/BackupStatusController.php b/app/Http/Controllers/Api/Remote/Backups/BackupStatusController.php index f9c2a793..7b30e075 100644 --- a/app/Http/Controllers/Api/Remote/Backups/BackupStatusController.php +++ b/app/Http/Controllers/Api/Remote/Backups/BackupStatusController.php @@ -30,8 +30,22 @@ class BackupStatusController extends Controller */ public function index(ReportBackupCompleteRequest $request, string $backup): JsonResponse { + // Get the node associated with the request. + /** @var \Pterodactyl\Models\Node $node */ + $node = $request->attributes->get('node'); + /** @var \Pterodactyl\Models\Backup $model */ - $model = Backup::query()->where('uuid', $backup)->firstOrFail(); + $model = Backup::query() + ->where('uuid', $backup) + ->firstOrFail(); + + // Check that the backup is "owned" by the node making the request. This avoids other nodes + // from messing with backups that they don't own. + /** @var \Pterodactyl\Models\Server $server */ + $server = $model->server; + if ($server->node_id !== $node->id) { + throw new HttpForbiddenException('You do not have permission to access that backup.'); + } if ($model->is_successful) { throw new BadRequestHttpException('Cannot update the status of a backup that is already marked as completed.'); diff --git a/app/Http/Requests/Admin/Egg/EggFormRequest.php b/app/Http/Requests/Admin/Egg/EggFormRequest.php index 0f153393..0a88f5a7 100644 --- a/app/Http/Requests/Admin/Egg/EggFormRequest.php +++ b/app/Http/Requests/Admin/Egg/EggFormRequest.php @@ -11,7 +11,7 @@ class EggFormRequest extends AdminFormRequest $rules = [ 'name' => 'required|string|max:191', 'description' => 'nullable|string', - 'docker_images' => 'required|string', + 'docker_images' => ['required', 'string', 'regex:/^[\w#\.\/\- ]*\|*[\w\.\/\-:@ ]*$/im'], 'force_outgoing_ip' => 'sometimes|boolean', 'file_denylist' => 'array', 'startup' => 'required|string', diff --git a/app/Http/Requests/Admin/Nest/StoreNestFormRequest.php b/app/Http/Requests/Admin/Nest/StoreNestFormRequest.php index 193f8676..81505de1 100644 --- a/app/Http/Requests/Admin/Nest/StoreNestFormRequest.php +++ b/app/Http/Requests/Admin/Nest/StoreNestFormRequest.php @@ -9,7 +9,7 @@ class StoreNestFormRequest extends AdminFormRequest public function rules(): array { return [ - 'name' => 'required|string|min:1|max:191', + 'name' => 'required|string|min:1|max:191|regex:/^[\w\- ]+$/', 'description' => 'string|nullable', ]; } diff --git a/app/Http/Requests/Api/Client/Servers/Settings/SetDockerImageRequest.php b/app/Http/Requests/Api/Client/Servers/Settings/SetDockerImageRequest.php index f618de37..231fec81 100644 --- a/app/Http/Requests/Api/Client/Servers/Settings/SetDockerImageRequest.php +++ b/app/Http/Requests/Api/Client/Servers/Settings/SetDockerImageRequest.php @@ -24,7 +24,7 @@ class SetDockerImageRequest extends ClientApiRequest implements ClientPermission Assert::isInstanceOf($server, Server::class); return [ - 'docker_image' => ['required', 'string', Rule::in(array_values($server->egg->docker_images))], + 'docker_image' => ['required', 'string', 'max:191', 'regex:/^[\w#\.\/\- ]*\|*[\w\.\/\-:@ ]*$/', Rule::in(array_values($server->egg->docker_images))], ]; } } diff --git a/app/Models/Egg.php b/app/Models/Egg.php index 31c3e342..f0e668b2 100644 --- a/app/Models/Egg.php +++ b/app/Models/Egg.php @@ -123,7 +123,7 @@ class Egg extends Model 'file_denylist' => 'array|nullable', 'file_denylist.*' => 'string', 'docker_images' => 'required|array|min:1', - 'docker_images.*' => 'required|string', + 'docker_images.*' => ['required', 'string', 'max:191', 'regex:/^[\w#\.\/\- ]*\|*[\w\.\/\-:@ ]*$/'], 'startup' => 'required|nullable|string', 'config_from' => 'sometimes|bail|nullable|numeric|exists:eggs,id', 'config_stop' => 'required_without:config_from|nullable|string|max:191', diff --git a/app/Models/Server.php b/app/Models/Server.php index d53af303..f95e1dee 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -163,7 +163,7 @@ class Server extends Model 'egg_id' => 'required|exists:eggs,id', 'startup' => 'required|string', 'skip_scripts' => 'sometimes|boolean', - 'image' => 'required|string|max:191', + 'image' => ['required', 'string', 'max:191', 'regex:/^[\w\.\/\-:@ ]*$/'], 'database_limit' => 'present|nullable|integer|min:0', 'allocation_limit' => 'sometimes|nullable|integer|min:0', 'backup_limit' => 'present|nullable|integer|min:0', diff --git a/config/app.php b/config/app.php index 32bf81ad..94978be8 100644 --- a/config/app.php +++ b/config/app.php @@ -11,7 +11,7 @@ return [ | change this value if you are not maintaining your own internal versions. */ - 'version' => '1.11.5', + 'version' => '1.11.7', /* |-------------------------------------------------------------------------- @@ -21,7 +21,7 @@ return [ | change this value if you are not maintaining your own internal versions. */ - 'fork-version' => '1.2.1', + 'fork-version' => '1.3.1', /* |-------------------------------------------------------------------------- diff --git a/database/Seeders/eggs/minecraft/egg-bungeecord.json b/database/Seeders/eggs/minecraft/egg-bungeecord.json index 0a995969..0ecf03ac 100644 --- a/database/Seeders/eggs/minecraft/egg-bungeecord.json +++ b/database/Seeders/eggs/minecraft/egg-bungeecord.json @@ -4,7 +4,7 @@ "version": "PTDL_v2", "update_url": null }, - "exported_at": "2022-06-17T08:10:44+03:00", + "exported_at": "2024-05-07T12:55:57+00:00", "name": "Bungeecord", "author": "support@pterodactyl.io", "description": "For a long time, Minecraft server owners have had a dream that encompasses a free, easy, and reliable way to connect multiple Minecraft servers together. BungeeCord is the answer to said dream. Whether you are a small server wishing to string multiple game-modes together, or the owner of the ShotBow Network, BungeeCord is the ideal solution for you. With the help of BungeeCord, you will be able to unlock your community's full potential.", @@ -14,6 +14,7 @@ "pid_limit" ], "docker_images": { + "Java 21": "ghcr.io\/pterodactyl\/yolks:java_21", "Java 17": "ghcr.io\/pterodactyl\/yolks:java_17", "Java 16": "ghcr.io\/pterodactyl\/yolks:java_16", "Java 11": "ghcr.io\/pterodactyl\/yolks:java_11", @@ -56,4 +57,4 @@ "field_type": "text" } ] -} +} \ No newline at end of file diff --git a/database/Seeders/eggs/minecraft/egg-forge-minecraft.json b/database/Seeders/eggs/minecraft/egg-forge-minecraft.json index 189cafad..a30a3087 100644 --- a/database/Seeders/eggs/minecraft/egg-forge-minecraft.json +++ b/database/Seeders/eggs/minecraft/egg-forge-minecraft.json @@ -4,7 +4,7 @@ "version": "PTDL_v2", "update_url": null }, - "exported_at": "2022-11-06T06:33:01-05:00", + "exported_at": "2024-05-07T12:55:56+00:00", "name": "Forge Minecraft", "author": "support@pterodactyl.io", "description": "Minecraft Forge Server. Minecraft Forge is a modding API (Application Programming Interface), which makes it easier to create mods, and also make sure mods are compatible with each other.", @@ -14,6 +14,7 @@ "pid_limit" ], "docker_images": { + "Java 21": "ghcr.io\/pterodactyl\/yolks:java_21", "Java 17": "ghcr.io\/pterodactyl\/yolks:java_17", "Java 16": "ghcr.io\/pterodactyl\/yolks:java_16", "Java 11": "ghcr.io\/pterodactyl\/yolks:java_11", @@ -76,4 +77,4 @@ "field_type": "text" } ] -} +} \ No newline at end of file diff --git a/database/Seeders/eggs/minecraft/egg-paper.json b/database/Seeders/eggs/minecraft/egg-paper.json index 8f001111..cb78f780 100644 --- a/database/Seeders/eggs/minecraft/egg-paper.json +++ b/database/Seeders/eggs/minecraft/egg-paper.json @@ -4,7 +4,7 @@ "version": "PTDL_v2", "update_url": null }, - "exported_at": "2022-06-17T08:11:30+03:00", + "exported_at": "2024-05-07T12:55:55+00:00", "name": "Paper", "author": "parker@pterodactyl.io", "description": "High performance Spigot fork that aims to fix gameplay and mechanics inconsistencies.", @@ -14,6 +14,7 @@ "pid_limit" ], "docker_images": { + "Java 21": "ghcr.io\/pterodactyl\/yolks:java_21", "Java 17": "ghcr.io\/pterodactyl\/yolks:java_17", "Java 16": "ghcr.io\/pterodactyl\/yolks:java_16", "Java 11": "ghcr.io\/pterodactyl\/yolks:java_11", @@ -76,4 +77,4 @@ "field_type": "text" } ] -} +} \ No newline at end of file diff --git a/database/Seeders/eggs/minecraft/egg-sponge--sponge-vanilla.json b/database/Seeders/eggs/minecraft/egg-sponge--sponge-vanilla.json index 61a531ae..51575f86 100644 --- a/database/Seeders/eggs/minecraft/egg-sponge--sponge-vanilla.json +++ b/database/Seeders/eggs/minecraft/egg-sponge--sponge-vanilla.json @@ -4,7 +4,7 @@ "version": "PTDL_v2", "update_url": null }, - "exported_at": "2022-06-17T08:11:42+03:00", + "exported_at": "2024-05-07T12:55:54+00:00", "name": "Sponge (SpongeVanilla)", "author": "support@pterodactyl.io", "description": "SpongeVanilla is the SpongeAPI implementation for Vanilla Minecraft.", @@ -14,6 +14,7 @@ "pid_limit" ], "docker_images": { + "Java 21": "ghcr.io\/pterodactyl\/yolks:java_21", "Java 16": "ghcr.io\/pterodactyl\/yolks:java_16", "Java 11": "ghcr.io\/pterodactyl\/yolks:java_11", "Java 8": "ghcr.io\/pterodactyl\/yolks:java_8" @@ -55,4 +56,4 @@ "field_type": "text" } ] -} +} \ No newline at end of file diff --git a/database/Seeders/eggs/minecraft/egg-vanilla-minecraft.json b/database/Seeders/eggs/minecraft/egg-vanilla-minecraft.json index 19964bcc..71fd1654 100644 --- a/database/Seeders/eggs/minecraft/egg-vanilla-minecraft.json +++ b/database/Seeders/eggs/minecraft/egg-vanilla-minecraft.json @@ -4,7 +4,7 @@ "version": "PTDL_v2", "update_url": null }, - "exported_at": "2022-06-17T08:11:58+03:00", + "exported_at": "2024-05-07T12:55:58+00:00", "name": "Vanilla Minecraft", "author": "support@pterodactyl.io", "description": "Minecraft is a game about placing blocks and going on adventures. Explore randomly generated worlds and build amazing things from the simplest of homes to the grandest of castles. Play in Creative Mode with unlimited resources or mine deep in Survival Mode, crafting weapons and armor to fend off dangerous mobs. Do all this alone or with friends.", @@ -14,6 +14,7 @@ "pid_limit" ], "docker_images": { + "Java 21": "ghcr.io\/pterodactyl\/yolks:java_21", "Java 17": "ghcr.io\/pterodactyl\/yolks:java_17", "Java 16": "ghcr.io\/pterodactyl\/yolks:java_16", "Java 11": "ghcr.io\/pterodactyl\/yolks:java_11", @@ -56,4 +57,4 @@ "field_type": "text" } ] -} +} \ No newline at end of file diff --git a/database/Seeders/eggs/rust/egg-rust.json b/database/Seeders/eggs/rust/egg-rust.json index 74cc27c3..35f543c7 100644 --- a/database/Seeders/eggs/rust/egg-rust.json +++ b/database/Seeders/eggs/rust/egg-rust.json @@ -47,7 +47,7 @@ "default_value": "vanilla", "user_viewable": true, "user_editable": true, - "rules": "required|in:carbon,oxide,vanilla", + "rules": "required|in:vanilla,oxide,carbon", "field_type": "text" }, { diff --git a/flake.lock b/flake.lock index f0b2fa2a..afb0fb17 100644 --- a/flake.lock +++ b/flake.lock @@ -1,38 +1,19 @@ { "nodes": { - "devshell": { - "flake": false, - "locked": { - "lastModified": 1663445644, - "narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=", - "owner": "numtide", - "repo": "devshell", - "rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "devshell", - "type": "github" - } - }, "dream2nix": { "inputs": { - "devshell": "devshell", - "flake-compat": "flake-compat", - "flake-parts": "flake-parts", - "nix-unit": "nix-unit", "nixpkgs": [ "nixpkgs" ], - "pre-commit-hooks": "pre-commit-hooks" + "purescript-overlay": "purescript-overlay", + "pyproject-nix": "pyproject-nix" }, "locked": { - "lastModified": 1695717405, - "narHash": "sha256-MvHrU3h0Bw57s2p+wCUnSZliR4wvvPi3xkW+MRWB5HU=", + "lastModified": 1710268378, + "narHash": "sha256-O61PtxUHbmwI6Ltjn9jY3QY2hRPPz7pe3BHhIYK4QkU=", "owner": "nix-community", "repo": "dream2nix", - "rev": "6dbd59e4a47bd916a655c4425a3e730c6aeae033", + "rev": "cd782df677aad08f7193c97376d615943c3cd4c9", "type": "github" }, "original": { @@ -41,71 +22,16 @@ "type": "github" } }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1673956053, - "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": [ - "dream2nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1675933616, - "narHash": "sha256-/rczJkJHtx16IFxMmAWu5nNYcSXNg1YYXTHoGjLrLUA=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "47478a4a003e745402acf63be7f9a092d51b83d7", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, "flake-utils": { "inputs": { "systems": "systems" }, "locked": { - "lastModified": 1689068808, - "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "flake-utils", - "type": "github" - } - }, - "flake-utils_2": { - "inputs": { - "systems": "systems_2" - }, - "locked": { - "lastModified": 1694529238, - "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", - "owner": "numtide", - "repo": "flake-utils", - "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", "type": "github" }, "original": { @@ -139,62 +65,13 @@ "type": "github" } }, - "nix-github-actions": { - "inputs": { - "nixpkgs": [ - "dream2nix", - "nix-unit", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1688870561, - "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", - "owner": "nix-community", - "repo": "nix-github-actions", - "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "nix-github-actions", - "type": "github" - } - }, - "nix-unit": { - "inputs": { - "flake-parts": [ - "dream2nix", - "flake-parts" - ], - "nix-github-actions": "nix-github-actions", - "nixpkgs": [ - "dream2nix", - "nixpkgs" - ], - "treefmt-nix": "treefmt-nix" - }, - "locked": { - "lastModified": 1690289081, - "narHash": "sha256-PCXQAQt8+i2pkUym9P1JY4JGoeZJLzzxWBhprHDdItM=", - "owner": "adisbladis", - "repo": "nix-unit", - "rev": "a9d6f33e50d4dcd9cfc0c92253340437bbae282b", - "type": "github" - }, - "original": { - "owner": "adisbladis", - "repo": "nix-unit", - "type": "github" - } - }, "nixpkgs": { "locked": { - "lastModified": 1695644571, - "narHash": "sha256-asS9dCCdlt1lPq0DLwkVBbVoEKuEuz+Zi3DG7pR/RxA=", + "lastModified": 1709961763, + "narHash": "sha256-6H95HGJHhEZtyYA3rIQpvamMKAGoa8Yh2rFV29QnuGw=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "6500b4580c2a1f3d0f980d32d285739d8e156d92", + "rev": "3030f185ba6a4bf4f18b87f345f104e6a6961f34", "type": "github" }, "original": { @@ -238,36 +115,75 @@ "type": "github" } }, - "pre-commit-hooks": { + "purescript-overlay": { "inputs": { - "flake-utils": "flake-utils", "nixpkgs": [ "dream2nix", "nixpkgs" - ] + ], + "slimlock": "slimlock" }, "locked": { - "lastModified": 1646153636, - "narHash": "sha256-AlWHMzK+xJ1mG267FdT8dCq/HvLCA6jwmx2ZUy5O8tY=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "b6bc0b21e1617e2b07d8205e7fae7224036dfa4b", + "lastModified": 1696022621, + "narHash": "sha256-eMjFmsj2G1E0Q5XiibUNgFjTiSz0GxIeSSzzVdoN730=", + "owner": "thomashoneyman", + "repo": "purescript-overlay", + "rev": "047c7933abd6da8aa239904422e22d190ce55ead", "type": "github" }, "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", + "owner": "thomashoneyman", + "repo": "purescript-overlay", + "type": "github" + } + }, + "pyproject-nix": { + "flake": false, + "locked": { + "lastModified": 1702448246, + "narHash": "sha256-hFg5s/hoJFv7tDpiGvEvXP0UfFvFEDgTdyHIjDVHu1I=", + "owner": "davhau", + "repo": "pyproject.nix", + "rev": "5a06a2697b228c04dd2f35659b4b659ca74f7aeb", + "type": "github" + }, + "original": { + "owner": "davhau", + "ref": "dream2nix", + "repo": "pyproject.nix", "type": "github" } }, "root": { "inputs": { "dream2nix": "dream2nix", - "flake-utils": "flake-utils_2", + "flake-utils": "flake-utils", "mk-node-package": "mk-node-package", "nixpkgs": "nixpkgs" } }, + "slimlock": { + "inputs": { + "nixpkgs": [ + "dream2nix", + "purescript-overlay", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688610262, + "narHash": "sha256-Wg0ViDotFWGWqKIQzyYCgayeH8s4U1OZcTiWTQYdAp4=", + "owner": "thomashoneyman", + "repo": "slimlock", + "rev": "b5c6cdcaf636ebbebd0a1f32520929394493f1a6", + "type": "github" + }, + "original": { + "owner": "thomashoneyman", + "repo": "slimlock", + "type": "github" + } + }, "systems": { "locked": { "lastModified": 1681028828, @@ -282,43 +198,6 @@ "repo": "default", "type": "github" } - }, - "systems_2": { - "locked": { - "lastModified": 1681028828, - "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", - "owner": "nix-systems", - "repo": "default", - "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default", - "type": "github" - } - }, - "treefmt-nix": { - "inputs": { - "nixpkgs": [ - "dream2nix", - "nix-unit", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1689620039, - "narHash": "sha256-BtNwghr05z7k5YMdq+6nbue+nEalvDepuA7qdQMAKoQ=", - "owner": "numtide", - "repo": "treefmt-nix", - "rev": "719c2977f958c41fa60a928e2fbc50af14844114", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "treefmt-nix", - "type": "github" - } } }, "root": "root", diff --git a/flake.nix b/flake.nix index e61dad51..43d760ef 100644 --- a/flake.nix +++ b/flake.nix @@ -39,7 +39,10 @@ pkgs = import nixpkgs {inherit system;}; mkNodePackage = mk-node-package.lib."${system}".mkNodePackage; - php81WithExtensions = with pkgs; (php81.buildEnv { + php = pkgs.php; # PHP 8.2 + phpPackages = pkgs.phpPackages; # PHP 8.2 + + phpWithExtensions = php.buildEnv { extensions = { enabled, all, @@ -52,8 +55,8 @@ extraConfig = '' xdebug.mode=debug ''; - }); - composer = with pkgs; (php81Packages.composer.override {php = php81WithExtensions;}); + }; + composer = phpPackages.composer.override {php = phpWithExtensions;}; caCertificates = pkgs.runCommand "ca-certificates" {} '' mkdir -p $out/etc/ssl/certs $out/etc/pki/tls/certs @@ -201,7 +204,7 @@ }; in { defaultPackage = panel; - devShell = import ./shell.nix {inherit composer php81WithExtensions pkgs;}; + devShell = import ./shell.nix {inherit composer phpWithExtensions pkgs;}; packages = { inherit panel; @@ -224,7 +227,7 @@ mysql80 nodejs_18 nodePackages.yarn - php81WithExtensions + phpWithExtensions ]; pathsToLink = ["/bin" "/etc"]; }; @@ -242,7 +245,7 @@ caCertificates caddy configs - php81WithExtensions + phpWithExtensions panel ]; diff --git a/public/themes/pterodactyl/js/admin/new-server.js b/public/themes/pterodactyl/js/admin/new-server.js index db138cbd..1437c04e 100644 --- a/public/themes/pterodactyl/js/admin/new-server.js +++ b/public/themes/pterodactyl/js/admin/new-server.js @@ -88,7 +88,7 @@ $('#pEggId').on('change', function (event) { for (let i = 0; i < keys.length; i++) { let opt = document.createElement('option'); opt.value = images[keys[i]]; - opt.innerHTML = keys[i] + " (" + images[keys[i]] + ")"; + opt.innerText = keys[i] + " (" + images[keys[i]] + ")"; $('#pDefaultContainer').append(opt); } @@ -109,6 +109,12 @@ $('#pEggId').on('change', function (event) { ), }); + function escapeHtml(str) { + var div = document.createElement('div'); + div.appendChild(document.createTextNode(str)); + return div.innerHTML; + } + const variableIds = {}; $('#appendVariablesTo').html(''); $.each(_.get(objectChain, 'variables', []), function (i, item) { @@ -117,11 +123,11 @@ $('#pEggId').on('change', function (event) { let isRequired = (item.required === 1) ? 'Required ' : ''; let dataAppend = ' \
\ - \ - \ -

' + item.description + '
\ - Access in Startup: {{' + item.env_variable + '}}
\ - Validation Rules: ' + item.rules + '

\ + \ + \ +

' + escapeHtml(item.description) + '
\ + Access in Startup: {{' + escapeHtml(item.env_variable) + '}}
\ + Validation Rules: ' + escapeHtml(item.rules) + '

\
\ '; $('#appendVariablesTo').append(dataAppend); diff --git a/resources/scripts/api/server/types.d.ts b/resources/scripts/api/server/types.d.ts index 0816d7e8..c4a01e92 100644 --- a/resources/scripts/api/server/types.d.ts +++ b/resources/scripts/api/server/types.d.ts @@ -23,7 +23,7 @@ export interface ServerEggVariable { description: string; envVariable: string; defaultValue: string; - serverValue: string; + serverValue: string | null; isEditable: boolean; rules: string[]; } diff --git a/resources/scripts/api/transformers.ts b/resources/scripts/api/transformers.ts index f2bea86d..602ac217 100644 --- a/resources/scripts/api/transformers.ts +++ b/resources/scripts/api/transformers.ts @@ -40,6 +40,7 @@ export const rawDataToFileObject = (data: FractalResponseData): FileObject => ({ 'application/x-xz', // .tar.xz, .xz 'application/zstd', // .tar.zst, .zst 'application/zip', // .zip + 'application/x-7z-compressed', // .7z ].indexOf(this.mimetype) >= 0 ); }, diff --git a/resources/scripts/components/server/features/eula/EulaModalFeature.tsx b/resources/scripts/components/server/features/eula/EulaModalFeature.tsx index fd7afe1d..574a6aac 100644 --- a/resources/scripts/components/server/features/eula/EulaModalFeature.tsx +++ b/resources/scripts/components/server/features/eula/EulaModalFeature.tsx @@ -72,7 +72,7 @@ const EulaModalFeature = () => { target={'_blank'} css={tw`text-primary-300 underline transition-colors duration-150 hover:text-primary-400`} rel={'noreferrer noopener'} - href='https://account.mojang.com/documents/minecraft_eula' + href='https://www.minecraft.net/eula' > Minecraft® EULA diff --git a/resources/scripts/components/server/startup/VariableBox.tsx b/resources/scripts/components/server/startup/VariableBox.tsx index ad73615c..ba3a4fe4 100644 --- a/resources/scripts/components/server/startup/VariableBox.tsx +++ b/resources/scripts/components/server/startup/VariableBox.tsx @@ -5,7 +5,6 @@ import { usePermissions } from '@/plugins/usePermissions'; import InputSpinner from '@/components/elements/InputSpinner'; import Input from '@/components/elements/Input'; import Switch from '@/components/elements/Switch'; -import tw from 'twin.macro'; import { debounce } from 'debounce'; import updateStartupVariable from '@/api/server/updateStartupVariable'; import useFlash from '@/plugins/useFlash'; @@ -61,15 +60,15 @@ const VariableBox = ({ variable }: Props) => { return ( +

{!variable.isEditable && ( - Read Only + Read Only )} {variable.name}

} > - + {useSwitch ? ( <> @@ -97,7 +96,7 @@ const VariableBox = ({ variable }: Props) => {