Compare commits

...

8 Commits

Author SHA1 Message Date
Matthew Penner
6dc85c731e chore: update SECURITY.md
ref; https://github.com/pterodactyl/panel/pull/5074 which targets the
wrong branch
2024-04-16 15:17:36 -06:00
Matthew Penner
0dad4c5a48 ui(admin): better handling of manual HTML rendering 2024-04-11 10:47:00 -06:00
Matthew Penner
b1fa3927c1 api(remote): fix oops in BackupStatusController 2024-04-11 10:42:18 -06:00
Matthew Penner
f671046947 admin: tweaks to validation and rendering 2024-04-10 18:13:25 -06:00
Matthew Penner
319ca683f8 api(remote): ensure requesting node is checked 2024-04-10 17:38:09 -06:00
Matthew Penner
1172d71d31 app: improve docker_image validation 2024-04-10 17:22:29 -06:00
Matthew Penner
2497819ca7 Update README.md 2024-03-16 14:02:07 -06:00
Matthew Penner
787bf34a59 nix: update to php 8.2 2024-03-16 14:01:51 -06:00
18 changed files with 137 additions and 222 deletions

View File

@@ -27,12 +27,14 @@ Stop settling for less. Make game servers a first class citizen on your platform
I would like to extend my sincere thanks to the following sponsors for helping fund Pterodactyl's development. I would like to extend my sincere thanks to the following sponsors for helping fund Pterodactyl's development.
[Interested in becoming a sponsor?](https://github.com/sponsors/matthewpi) [Interested in becoming a sponsor?](https://github.com/sponsors/matthewpi)
| Company | About | | Company | About |
|-----------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |-----------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| [**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. |
| [**BisectHosting**](https://www.bisecthosting.com/) | BisectHosting provides Minecraft, Valheim and other server hosting services with the highest reliability and lightning fast support since 2012. | | [**BisectHosting**](https://www.bisecthosting.com/) | BisectHosting provides Minecraft, Valheim and other server hosting services with the highest reliability and lightning fast support since 2012. |
| [**MineStrator**](https://minestrator.com/) | Looking for the most highend French hosting company for your minecraft server? More than 24,000 members on our discord trust us. Give us a try! | | [**MineStrator**](https://minestrator.com/) | Looking for the most highend French hosting company for your minecraft server? More than 24,000 members on our discord trust us. Give us a try! |
| [**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. |
| [**HostEZ**](https://hostez.io) | US & EU Rust & Minecraft Hosting. DDoS Protected bare metal, VPS and colocation with low latency, high uptime and maximum availability. EZ! |
| [**Blueprint**](https://blueprint.zip/?pterodactyl=true) | Create and install Pterodactyl addons and themes with the growing Blueprint framework - the package-manager for Pterodactyl. Use multiple modifications at once without worrying about conflicts and make use of the large extension ecosystem. |
### Supported Games ### Supported Games

View File

@@ -6,7 +6,6 @@ The following versions of Pterodactyl are receiving active support and maintenan
| Panel | Daemon | Supported | | Panel | Daemon | Supported |
|--------|--------------|--------------------| |--------|--------------|--------------------|
| 1.10.x | wings@1.7.x | :white_check_mark: |
| 1.11.x | wings@1.11.x | :white_check_mark: | | 1.11.x | wings@1.11.x | :white_check_mark: |
| 0.7.x | daemon@0.6.x | :x: | | 0.7.x | daemon@0.6.x | :x: |

View File

@@ -69,7 +69,7 @@ class EggVariableController extends Controller
{ {
$this->updateService->handle($variable, $request->normalize()); $this->updateService->handle($variable, $request->normalize());
$this->alert->success(trans('admin/nests.variables.notices.variable_updated', [ $this->alert->success(trans('admin/nests.variables.notices.variable_updated', [
'variable' => $variable->name, 'variable' => htmlspecialchars($variable->name),
]))->flash(); ]))->flash();
return redirect()->route('admin.nests.egg.variables', $egg->id); return redirect()->route('admin.nests.egg.variables', $egg->id);
@@ -82,7 +82,7 @@ class EggVariableController extends Controller
{ {
$this->variableRepository->delete($variable->id); $this->variableRepository->delete($variable->id);
$this->alert->success(trans('admin/nests.variables.notices.variable_deleted', [ $this->alert->success(trans('admin/nests.variables.notices.variable_deleted', [
'variable' => $variable->name, 'variable' => htmlspecialchars($variable->name),
]))->flash(); ]))->flash();
return redirect()->route('admin.nests.egg.variables', $egg); return redirect()->route('admin.nests.egg.variables', $egg);

View File

@@ -56,7 +56,7 @@ class NestController extends Controller
public function store(StoreNestFormRequest $request): RedirectResponse public function store(StoreNestFormRequest $request): RedirectResponse
{ {
$nest = $this->nestCreationService->handle($request->normalize()); $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); return redirect()->route('admin.nests.view', $nest->id);
} }

View File

@@ -131,7 +131,7 @@ class NodesController extends Controller
['ip', '=', $request->input('ip')], ['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(); ->flash();
return redirect()->route('admin.nodes.view.allocation', $node); return redirect()->route('admin.nodes.view.allocation', $node);

View File

@@ -32,6 +32,10 @@ class BackupRemoteUploadController extends Controller
*/ */
public function __invoke(Request $request, string $backup): JsonResponse 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. // Get the size query parameter.
$size = (int) $request->query('size'); $size = (int) $request->query('size');
if (empty($size)) { if (empty($size)) {
@@ -39,7 +43,10 @@ class BackupRemoteUploadController extends Controller
} }
/** @var \Pterodactyl\Models\Backup $backup */ /** @var \Pterodactyl\Models\Backup $backup */
$backup = Backup::query()->where('uuid', $backup)->firstOrFail(); $backup = Backup::query()
->where('node_id', $node->id)
->where('uuid', $backup)
->firstOrFail();
// Prevent backups that have already been completed from trying to // Prevent backups that have already been completed from trying to
// be uploaded again. // be uploaded again.

View File

@@ -30,8 +30,15 @@ class BackupStatusController extends Controller
*/ */
public function index(ReportBackupCompleteRequest $request, string $backup): JsonResponse 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 */ /** @var \Pterodactyl\Models\Backup $model */
$model = Backup::query()->where('uuid', $backup)->firstOrFail(); $model = Backup::query()
->where('node_id', $node->id)
->where('uuid', $backup)
->firstOrFail();
if ($model->is_successful) { if ($model->is_successful) {
throw new BadRequestHttpException('Cannot update the status of a backup that is already marked as completed.'); throw new BadRequestHttpException('Cannot update the status of a backup that is already marked as completed.');

View File

@@ -11,7 +11,7 @@ class EggFormRequest extends AdminFormRequest
$rules = [ $rules = [
'name' => 'required|string|max:191', 'name' => 'required|string|max:191',
'description' => 'nullable|string', 'description' => 'nullable|string',
'docker_images' => 'required|string', 'docker_images' => ['required', 'string', 'regex:/^[\w#\.\/\- ]*\|*[\w\.\/\-:@ ]*$/im'],
'force_outgoing_ip' => 'sometimes|boolean', 'force_outgoing_ip' => 'sometimes|boolean',
'file_denylist' => 'array', 'file_denylist' => 'array',
'startup' => 'required|string', 'startup' => 'required|string',

View File

@@ -9,7 +9,7 @@ class StoreNestFormRequest extends AdminFormRequest
public function rules(): array public function rules(): array
{ {
return [ return [
'name' => 'required|string|min:1|max:191', 'name' => 'required|string|min:1|max:191|regex:/^[\w\- ]+$/',
'description' => 'string|nullable', 'description' => 'string|nullable',
]; ];
} }

View File

@@ -24,7 +24,7 @@ class SetDockerImageRequest extends ClientApiRequest implements ClientPermission
Assert::isInstanceOf($server, Server::class); Assert::isInstanceOf($server, Server::class);
return [ 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))],
]; ];
} }
} }

View File

@@ -123,7 +123,7 @@ class Egg extends Model
'file_denylist' => 'array|nullable', 'file_denylist' => 'array|nullable',
'file_denylist.*' => 'string', 'file_denylist.*' => 'string',
'docker_images' => 'required|array|min:1', 'docker_images' => 'required|array|min:1',
'docker_images.*' => 'required|string', 'docker_images.*' => ['required', 'string', 'max:191', 'regex:/^[\w#\.\/\- ]*\|*[\w\.\/\-:@ ]*$/'],
'startup' => 'required|nullable|string', 'startup' => 'required|nullable|string',
'config_from' => 'sometimes|bail|nullable|numeric|exists:eggs,id', 'config_from' => 'sometimes|bail|nullable|numeric|exists:eggs,id',
'config_stop' => 'required_without:config_from|nullable|string|max:191', 'config_stop' => 'required_without:config_from|nullable|string|max:191',

View File

@@ -163,7 +163,7 @@ class Server extends Model
'egg_id' => 'required|exists:eggs,id', 'egg_id' => 'required|exists:eggs,id',
'startup' => 'required|string', 'startup' => 'required|string',
'skip_scripts' => 'sometimes|boolean', 'skip_scripts' => 'sometimes|boolean',
'image' => 'required|string|max:191', 'image' => ['required', 'string', 'max:191', 'regex:/^[\w\.\/\-:@ ]*$/'],
'database_limit' => 'present|nullable|integer|min:0', 'database_limit' => 'present|nullable|integer|min:0',
'allocation_limit' => 'sometimes|nullable|integer|min:0', 'allocation_limit' => 'sometimes|nullable|integer|min:0',
'backup_limit' => 'present|nullable|integer|min:0', 'backup_limit' => 'present|nullable|integer|min:0',

243
flake.lock generated
View File

@@ -1,38 +1,19 @@
{ {
"nodes": { "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": { "dream2nix": {
"inputs": { "inputs": {
"devshell": "devshell",
"flake-compat": "flake-compat",
"flake-parts": "flake-parts",
"nix-unit": "nix-unit",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"pre-commit-hooks": "pre-commit-hooks" "purescript-overlay": "purescript-overlay",
"pyproject-nix": "pyproject-nix"
}, },
"locked": { "locked": {
"lastModified": 1695717405, "lastModified": 1710268378,
"narHash": "sha256-MvHrU3h0Bw57s2p+wCUnSZliR4wvvPi3xkW+MRWB5HU=", "narHash": "sha256-O61PtxUHbmwI6Ltjn9jY3QY2hRPPz7pe3BHhIYK4QkU=",
"owner": "nix-community", "owner": "nix-community",
"repo": "dream2nix", "repo": "dream2nix",
"rev": "6dbd59e4a47bd916a655c4425a3e730c6aeae033", "rev": "cd782df677aad08f7193c97376d615943c3cd4c9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -41,71 +22,16 @@
"type": "github" "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": { "flake-utils": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems"
}, },
"locked": { "locked": {
"lastModified": 1689068808, "lastModified": 1710146030,
"narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"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",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -139,62 +65,13 @@
"type": "github" "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": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1695644571, "lastModified": 1709961763,
"narHash": "sha256-asS9dCCdlt1lPq0DLwkVBbVoEKuEuz+Zi3DG7pR/RxA=", "narHash": "sha256-6H95HGJHhEZtyYA3rIQpvamMKAGoa8Yh2rFV29QnuGw=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6500b4580c2a1f3d0f980d32d285739d8e156d92", "rev": "3030f185ba6a4bf4f18b87f345f104e6a6961f34",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -238,36 +115,75 @@
"type": "github" "type": "github"
} }
}, },
"pre-commit-hooks": { "purescript-overlay": {
"inputs": { "inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [ "nixpkgs": [
"dream2nix", "dream2nix",
"nixpkgs" "nixpkgs"
] ],
"slimlock": "slimlock"
}, },
"locked": { "locked": {
"lastModified": 1646153636, "lastModified": 1696022621,
"narHash": "sha256-AlWHMzK+xJ1mG267FdT8dCq/HvLCA6jwmx2ZUy5O8tY=", "narHash": "sha256-eMjFmsj2G1E0Q5XiibUNgFjTiSz0GxIeSSzzVdoN730=",
"owner": "cachix", "owner": "thomashoneyman",
"repo": "pre-commit-hooks.nix", "repo": "purescript-overlay",
"rev": "b6bc0b21e1617e2b07d8205e7fae7224036dfa4b", "rev": "047c7933abd6da8aa239904422e22d190ce55ead",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "cachix", "owner": "thomashoneyman",
"repo": "pre-commit-hooks.nix", "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" "type": "github"
} }
}, },
"root": { "root": {
"inputs": { "inputs": {
"dream2nix": "dream2nix", "dream2nix": "dream2nix",
"flake-utils": "flake-utils_2", "flake-utils": "flake-utils",
"mk-node-package": "mk-node-package", "mk-node-package": "mk-node-package",
"nixpkgs": "nixpkgs" "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": { "systems": {
"locked": { "locked": {
"lastModified": 1681028828, "lastModified": 1681028828,
@@ -282,43 +198,6 @@
"repo": "default", "repo": "default",
"type": "github" "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", "root": "root",

View File

@@ -39,7 +39,10 @@
pkgs = import nixpkgs {inherit system;}; pkgs = import nixpkgs {inherit system;};
mkNodePackage = mk-node-package.lib."${system}".mkNodePackage; 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 = { extensions = {
enabled, enabled,
all, all,
@@ -52,8 +55,8 @@
extraConfig = '' extraConfig = ''
xdebug.mode=debug xdebug.mode=debug
''; '';
}); };
composer = with pkgs; (php81Packages.composer.override {php = php81WithExtensions;}); composer = phpPackages.composer.override {php = phpWithExtensions;};
caCertificates = pkgs.runCommand "ca-certificates" {} '' caCertificates = pkgs.runCommand "ca-certificates" {} ''
mkdir -p $out/etc/ssl/certs $out/etc/pki/tls/certs mkdir -p $out/etc/ssl/certs $out/etc/pki/tls/certs
@@ -201,7 +204,7 @@
}; };
in { in {
defaultPackage = panel; defaultPackage = panel;
devShell = import ./shell.nix {inherit composer php81WithExtensions pkgs;}; devShell = import ./shell.nix {inherit composer phpWithExtensions pkgs;};
packages = { packages = {
inherit panel; inherit panel;
@@ -224,7 +227,7 @@
mysql80 mysql80
nodejs_18 nodejs_18
nodePackages.yarn nodePackages.yarn
php81WithExtensions phpWithExtensions
]; ];
pathsToLink = ["/bin" "/etc"]; pathsToLink = ["/bin" "/etc"];
}; };
@@ -242,7 +245,7 @@
caCertificates caCertificates
caddy caddy
configs configs
php81WithExtensions phpWithExtensions
panel panel
]; ];

View File

@@ -88,7 +88,7 @@ $('#pEggId').on('change', function (event) {
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
let opt = document.createElement('option'); let opt = document.createElement('option');
opt.value = images[keys[i]]; opt.value = images[keys[i]];
opt.innerHTML = keys[i] + " (" + images[keys[i]] + ")"; opt.innerText = keys[i] + " (" + images[keys[i]] + ")";
$('#pDefaultContainer').append(opt); $('#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 = {}; const variableIds = {};
$('#appendVariablesTo').html(''); $('#appendVariablesTo').html('');
$.each(_.get(objectChain, 'variables', []), function (i, item) { $.each(_.get(objectChain, 'variables', []), function (i, item) {
@@ -117,11 +123,11 @@ $('#pEggId').on('change', function (event) {
let isRequired = (item.required === 1) ? '<span class="label label-danger">Required</span> ' : ''; let isRequired = (item.required === 1) ? '<span class="label label-danger">Required</span> ' : '';
let dataAppend = ' \ let dataAppend = ' \
<div class="form-group col-sm-6"> \ <div class="form-group col-sm-6"> \
<label for="var_ref_' + item.id + '" class="control-label">' + isRequired + item.name + '</label> \ <label for="var_ref_' + escapeHtml(item.id) + '" class="control-label">' + isRequired + escapeHtml(item.name) + '</label> \
<input type="text" id="var_ref_' + item.id + '" autocomplete="off" name="environment[' + item.env_variable + ']" class="form-control" value="' + item.default_value + '" /> \ <input type="text" id="var_ref_' + escapeHtml(item.id) + '" autocomplete="off" name="environment[' + escapeHtml(item.env_variable) + ']" class="form-control" value="' + escapeHtml(item.default_value) + '" /> \
<p class="text-muted small">' + item.description + '<br /> \ <p class="text-muted small">' + escapeHtml(item.description) + '<br /> \
<strong>Access in Startup:</strong> <code>{{' + item.env_variable + '}}</code><br /> \ <strong>Access in Startup:</strong> <code>{{' + escapeHtml(item.env_variable) + '}}</code><br /> \
<strong>Validation Rules:</strong> <code>' + item.rules + '</code></small></p> \ <strong>Validation Rules:</strong> <code>' + escapeHtml(item.rules) + '</code></small></p> \
</div> \ </div> \
'; ';
$('#appendVariablesTo').append(dataAppend); $('#appendVariablesTo').append(dataAppend);

View File

@@ -145,14 +145,20 @@
@section('footer-scripts') @section('footer-scripts')
@parent @parent
<script> <script>
function escapeHtml(str) {
var div = document.createElement('div');
div.appendChild(document.createTextNode(str));
return div.innerHTML;
}
(function getInformation() { (function getInformation() {
$.ajax({ $.ajax({
method: 'GET', method: 'GET',
url: '/admin/nodes/view/{{ $node->id }}/system-information', url: '/admin/nodes/view/{{ $node->id }}/system-information',
timeout: 5000, timeout: 5000,
}).done(function (data) { }).done(function (data) {
$('[data-attr="info-version"]').html(data.version); $('[data-attr="info-version"]').html(escapeHtml(data.version));
$('[data-attr="info-system"]').html(data.system.type + ' (' + data.system.arch + ') <code>' + data.system.release + '</code>'); $('[data-attr="info-system"]').html(escapeHtml(data.system.type) + ' (' + escapeHtml(data.system.arch) + ') <code>' + escapeHtml(data.system.release) + '</code>');
$('[data-attr="info-cpus"]').html(data.system.cpus); $('[data-attr="info-cpus"]').html(data.system.cpus);
}).fail(function (jqXHR) { }).fail(function (jqXHR) {

View File

@@ -107,6 +107,12 @@
@parent @parent
{!! Theme::js('vendor/lodash/lodash.js') !!} {!! Theme::js('vendor/lodash/lodash.js') !!}
<script> <script>
function escapeHtml(str) {
var div = document.createElement('div');
div.appendChild(document.createTextNode(str));
return div.innerHTML;
}
$(document).ready(function () { $(document).ready(function () {
$('#pEggId').select2({placeholder: 'Select a Nest Egg'}).on('change', function () { $('#pEggId').select2({placeholder: 'Select a Nest Egg'}).on('change', function () {
var selectedEgg = _.isNull($(this).val()) ? $(this).find('option').first().val() : $(this).val(); var selectedEgg = _.isNull($(this).val()) ? $(this).find('option').first().val() : $(this).val();
@@ -119,7 +125,7 @@
for (let i = 0; i < keys.length; i++) { for (let i = 0; i < keys.length; i++) {
let opt = document.createElement('option'); let opt = document.createElement('option');
opt.value = images[keys[i]]; opt.value = images[keys[i]];
opt.innerHTML = keys[i] + " (" + images[keys[i]] + ")"; opt.innerText = keys[i] + " (" + images[keys[i]] + ")";
if (objectChain.id === parseInt(Pterodactyl.server.egg_id) && Pterodactyl.server.image == opt.value) { if (objectChain.id === parseInt(Pterodactyl.server.egg_id) && Pterodactyl.server.image == opt.value) {
opt.selected = true opt.selected = true
} }
@@ -149,15 +155,15 @@
<div class="col-xs-12"> \ <div class="col-xs-12"> \
<div class="box"> \ <div class="box"> \
<div class="box-header with-border"> \ <div class="box-header with-border"> \
<h3 class="box-title">' + isRequired + item.name + '</h3> \ <h3 class="box-title">' + isRequired + escapeHtml(item.name) + '</h3> \
</div> \ </div> \
<div class="box-body"> \ <div class="box-body"> \
<input name="environment[' + item.env_variable + ']" class="form-control" type="text" id="egg_variable_' + item.env_variable + '" /> \ <input name="environment[' + escapeHtml(item.env_variable) + ']" class="form-control" type="text" id="egg_variable_' + escapeHtml(item.env_variable) + '" /> \
<p class="no-margin small text-muted">' + item.description + '</p> \ <p class="no-margin small text-muted">' + escapeHtml(item.description) + '</p> \
</div> \ </div> \
<div class="box-footer"> \ <div class="box-footer"> \
<p class="no-margin text-muted small"><strong>Startup Command Variable:</strong> <code>' + item.env_variable + '</code></p> \ <p class="no-margin text-muted small"><strong>Startup Command Variable:</strong> <code>' + escapeHtml(item.env_variable) + '</code></p> \
<p class="no-margin text-muted small"><strong>Input Rules:</strong> <code>' + item.rules + '</code></p> \ <p class="no-margin text-muted small"><strong>Input Rules:</strong> <code>' + escapeHtml(item.rules) + '</code></p> \
</div> \ </div> \
</div> \ </div> \
</div>'; </div>';

View File

@@ -1,6 +1,6 @@
{ {
composer ? null, composer ? null,
php81WithExtensions ? null, phpWithExtensions ? null,
pkgs ? import <nixpkgs> {}, pkgs ? import <nixpkgs> {},
}: }:
with pkgs; with pkgs;
@@ -10,7 +10,7 @@ with pkgs;
composer composer
nodejs_18 nodejs_18
nodePackages.yarn nodePackages.yarn
php81WithExtensions phpWithExtensions
]; ];
shellHook = '' shellHook = ''