Compare commits

..

41 Commits

Author SHA1 Message Date
Angelillo15 c332151c9a Merge branch 'release/v1.11.7' of https://github.com/pterodactyl/panel into release/v1.11.5 2024-05-11 17:11:39 +02:00
Angelillo15 235e1007f7
Update README.md 2024-05-08 16:18:24 +02:00
Pterodactyl CI 62b8a53165 ci(release): bump version 2024-05-08 04:17:09 +00:00
Matthew Penner 3a0b7d13a9
Update CHANGELOG.md 2024-05-07 22:13:13 -06:00
Matthew Penner a96d87cf23
Update README.md 2024-05-07 22:12:15 -06:00
Daniel Barton 049ad838e3
egg(minecraft): add Java 21 to image list (#5093) 2024-05-07 21:52:33 -06:00
Daniel Barton dbd7f31c41
Update Minecraft Eula link (#5090)
Co-authored-by: Alan Escarcha <alanescarcha11@gmail.com>
2024-05-06 18:50:06 -06:00
Daniel Barton 2ffe019675
ui(server): support for decompressing .7z files (#5016) 2024-05-04 17:16:00 -06:00
Matthew Penner 7bfc265a7e
api(remote): fix use of missing `node_id` field
Fixes #5088
2024-05-04 16:06:13 -06:00
Matthew Penner b7b2413f3d
Update CHANGELOG.md 2024-05-02 13:37:18 -06:00
Matthew Penner 96e6c66040
Update README.md 2024-05-02 13:22:31 -06:00
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
Angelillo15 6592e8e1cb
release 1.11.5 2024-01-16 19:44:02 +01:00
Angelillo15 a5c52e1af5
Update docker.yaml 2024-01-16 18:58:28 +01:00
Matthew Penner f0489f677b
Update README.md 2023-12-29 22:09:21 -07:00
Matthew Penner 8abf2d8106
ui(server): fix defaultValue not being used with VariableBox select 2023-10-20 19:30:25 -06:00
Matthew Penner 341eda7855
egg(rust): change ordering of mod frameworks 2023-10-20 19:29:21 -06:00
Angelillo15 9678ae0037 Bump version 2023-10-17 22:33:15 +02:00
Angelillo15 d4ac089be8 Fix height 2023-10-17 22:32:54 +02:00
Angelillo15 7dcfb4426a Add release script 2023-10-17 22:25:08 +02:00
Angelillo15 7d58952a9b Put fork version 2023-10-17 21:51:44 +02:00
Angelillo15 5cea017833 Change branding in admin 2023-10-17 21:51:34 +02:00
Angelillo15 9979521c3a Change wheelchar -> cogs 2023-10-17 21:51:21 +02:00
Angelillo15 6b9dd72815 Fix progess bar 2023-10-17 21:51:04 +02:00
Angelillo15 fae1ac5ae8 Fix ProgressBar 2023-10-17 21:50:57 +02:00
Angelillo15 9c054b7af3 Change branding 2023-10-17 21:49:21 +02:00
Angelillo15 5694e2ae0c Make sidebar toggle button to only appear in sidebar pages 2023-10-17 21:49:14 +02:00
Angelillo15 7935e9f4a8 Fix sidebar css 2023-10-17 21:48:35 +02:00
Angelillo15 91364425ad Add NookTheme version 2023-10-17 21:48:24 +02:00
Angelillo15 f6cf39fb99 Disable host check 2023-10-17 21:48:15 +02:00
Angelillo15 54b1793e2d Merge remote-tracking branch 'upstream/release/v1.11.5' into release/v1.11.5 2023-10-16 16:32:56 +02:00
Pterodactyl CI 22629f4ab8 ci(release): bump version 2023-10-12 20:00:25 +00:00
Matthew Penner 742e352c67
Update CHANGELOG.md 2023-10-12 13:55:53 -06:00
Matthew Penner a62e8b1a67
egg(rust): use yolk image instead of the deprecated one 2023-10-12 13:54:42 -06:00
41 changed files with 308 additions and 272 deletions

View File

@ -5,6 +5,7 @@ on:
branches:
- develop
- 1.0-develop
- release/v1.11.5
pull_request:
branches:
- develop
@ -26,7 +27,7 @@ jobs:
id: docker_meta
uses: docker/metadata-action@v4
with:
images: ghcr.io/pterodactyl/panel
images: ghcr.io/nookure/nooktheme
flavor: |
latest=false
tags: |

1
.gitignore vendored
View File

@ -34,3 +34,4 @@ resources/lang/locales.js
/public/hot
result
docker-compose.yaml
release

View File

@ -3,6 +3,36 @@ 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.
## v1.11.4
### Added
* Added support for the `server.queryport` option on the Rust egg.

View File

@ -114,6 +114,16 @@ php artisan up
* [Community Guides](https://pterodactyl.io/community/about.html)
* Or, get additional help [via Discord](https://discord.nookure.com/)
## Star History
<a href="https://star-history.com/#Nookure/NookTheme&Timeline">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=Nookure/NookTheme&type=Timeline&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=Nookure/NookTheme&type=Timeline" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=Nookure/NookTheme&type=Timeline" />
</picture>
</a>
## License
Pterodactyl® Copyright © 2015 - 2023 Dane Everitt and contributors.

View File

@ -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: |

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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,

View File

@ -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.');

View File

@ -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',

View File

@ -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',
];
}

View File

@ -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))],
];
}
}

View File

@ -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',

View File

@ -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',

View File

@ -11,7 +11,17 @@ return [
| change this value if you are not maintaining your own internal versions.
*/
'version' => '1.11.4',
'version' => '1.11.7',
/*
|--------------------------------------------------------------------------
| NookTheme Version
|--------------------------------------------------------------------------
| This value is set when creating a NookTheme release. You should not
| change this value if you are not maintaining your own internal versions.
*/
'fork-version' => '1.3.1',
/*
|--------------------------------------------------------------------------

View File

@ -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"
}
]
}
}

View File

@ -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"
}
]
}
}

View File

@ -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"
}
]
}
}

View File

@ -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"
}
]
}
}

View File

@ -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"
}
]
}
}

View File

@ -12,7 +12,7 @@
"steam_disk_space"
],
"docker_images": {
"quay.io\/pterodactyl\/core:rust": "quay.io\/pterodactyl\/core:rust"
"ghcr.io\/pterodactyl\/games:rust": "ghcr.io\/pterodactyl\/games:rust"
},
"file_denylist": [],
"startup": ".\/RustDedicated -batchmode +server.port {{SERVER_PORT}} +server.queryport {{QUERY_PORT}} +server.identity \"rust\" +rcon.port {{RCON_PORT}} +rcon.web true +server.hostname \\\"{{HOSTNAME}}\\\" +server.level \\\"{{LEVEL}}\\\" +server.description \\\"{{DESCRIPTION}}\\\" +server.url \\\"{{SERVER_URL}}\\\" +server.headerimage \\\"{{SERVER_IMG}}\\\" +server.logoimage \\\"{{SERVER_LOGO}}\\\" +server.maxplayers {{MAX_PLAYERS}} +rcon.password \\\"{{RCON_PASS}}\\\" +server.saveinterval {{SAVEINTERVAL}} +app.port {{APP_PORT}} $( [ -z ${MAP_URL} ] && printf %s \"+server.worldsize \\\"{{WORLD_SIZE}}\\\" +server.seed \\\"{{WORLD_SEED}}\\\"\" || printf %s \"+server.levelurl {{MAP_URL}}\" ) {{ADDITIONAL_ARGS}}",
@ -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"
},
{

View File

@ -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",

View File

@ -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
];

View File

@ -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) ? '<span class="label label-danger">Required</span> ' : '';
let dataAppend = ' \
<div class="form-group col-sm-6"> \
<label for="var_ref_' + item.id + '" class="control-label">' + isRequired + 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 + '" /> \
<p class="text-muted small">' + item.description + '<br /> \
<strong>Access in Startup:</strong> <code>{{' + item.env_variable + '}}</code><br /> \
<strong>Validation Rules:</strong> <code>' + item.rules + '</code></small></p> \
<label for="var_ref_' + escapeHtml(item.id) + '" class="control-label">' + isRequired + escapeHtml(item.name) + '</label> \
<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">' + escapeHtml(item.description) + '<br /> \
<strong>Access in Startup:</strong> <code>{{' + escapeHtml(item.env_variable) + '}}</code><br /> \
<strong>Validation Rules:</strong> <code>' + escapeHtml(item.rules) + '</code></small></p> \
</div> \
';
$('#appendVariablesTo').append(dataAppend);

41
release.sh Executable file
View File

@ -0,0 +1,41 @@
start=`date +%s`
# Build the panel
yarn build:production
# Mkdir and cd to tmp
mkdir tmp
cd tmp/
# Clone the repo
git clone https://github.com/Nookure/NookTheme.git
cd NookTheme
# Remove the .git folder
rm -rf .git
# Copy the Compiled files
cp -r ../../public .
# Create the tar and zip files
tar -czvf ./NookTheme.tar.gz .
zip -r ./NookTheme.zip .
rm -rf ../../release/*
# Create releases folder if it doesn't exist
mkdir ../../release
# Move the files to releases
mv ./NookTheme.tar.gz ../../release/panel.tar.gz
mv ./NookTheme.zip ../../release/panel.zip
# Remove the tmp folder
cd ../../
rm -rf tmp/
end=`date +%s`
# Done
echo "Build in `expr $end - $start` seconds"

View File

@ -23,7 +23,7 @@ export interface ServerEggVariable {
description: string;
envVariable: string;
defaultValue: string;
serverValue: string;
serverValue: string | null;
isEditable: boolean;
rules: string[];
}

View File

@ -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
);
},

View File

@ -35,7 +35,7 @@ You should have received a copy of the GNU General Public License along with Noo
.nav-bar {
display: none;
}
/* The side navigation menu */
.sidebar {
position: fixed;
margin: 0;
@ -43,10 +43,8 @@ You should have received a copy of the GNU General Public License along with Noo
width: var(--sidebar-size);
background-color: var(--color-tertiary);
overflow: auto;
z-index: 999999;
margin-top: 0;
top: 3.5rem;
height: 94vh;
z-index: 9999;
height: calc(100vh - 3.5rem);
}
.content-container {
@ -140,7 +138,7 @@ div.content {
left: 0;
margin-right: var(--sidebar-size);
width: var(--sidebar-size);
height: 100vh;
height: calc(100vh - 3.5rem);
}
.nav-bar {
@ -184,14 +182,11 @@ div.content {
}
.topbar {
position: fixed;
position: sticky;
margin-top: 0 !important;
top: 0;
width: 100%;
z-index: 10000;
z-index: 100;
height: 3.5rem;
overflow-y: hidden;
}
.nook-container {
margin-top: 5rem;
}

View File

@ -1,6 +1,6 @@
import * as React from 'react';
import { useState } from 'react';
import { Link, NavLink } from 'react-router-dom';
import { useState, useEffect } from 'react';
import { Link, NavLink, useLocation } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faBars, faCogs, faLayerGroup, faSignOutAlt } from '@fortawesome/free-solid-svg-icons';
import { useStoreState } from 'easy-peasy';
@ -38,14 +38,22 @@ const onTriggerNavButton = () => {
if (sidebar) {
sidebar.classList.toggle('active-nav');
}
console.log('triggered');
};
export default () => {
const name = useStoreState((state: ApplicationStore) => state.settings.data!.name);
const rootAdmin = useStoreState((state: ApplicationStore) => state.user.data!.rootAdmin);
const [isLoggingOut, setIsLoggingOut] = useState(false);
const location = useLocation();
const [showSidebar, setShowSidebar] = useState(false);
useEffect(() => {
if (location.pathname.startsWith('/server') || location.pathname.startsWith('/account')) {
setShowSidebar(true);
return;
}
setShowSidebar(false);
}, [location.pathname]);
const onTriggerLogout = () => {
setIsLoggingOut(true);
@ -59,7 +67,13 @@ export default () => {
<div className={'bg-neutral-700 shadow-md overflow-x-auto topbar'}>
<SpinnerOverlay visible={isLoggingOut} />
<div className={'mx-auto w-full flex items-center h-[3.5rem] max-w-[1200px]'}>
<FontAwesomeIcon icon={faBars} className='navbar-button' onClick={onTriggerNavButton}></FontAwesomeIcon>
{showSidebar && (
<FontAwesomeIcon
icon={faBars}
className='navbar-button'
onClick={onTriggerNavButton}
></FontAwesomeIcon>
)}
<div id={'logo'} className={'flex-1'}>
<Link

View File

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

View File

@ -5,15 +5,14 @@ import { randomInt } from '@/helpers';
import { CSSTransition } from 'react-transition-group';
import tw from 'twin.macro';
const BarFill = styled.div`
const BarFill = styled.div<{ style?: { top?: string } }>`
${tw`h-full bg-red-600`};
transition: 250ms ease-in-out;
margin-top: 0 !important;
box-shadow: 0 -2px 10px 2px hsl(9.090909090909092, 98.29787234042554%, 53.92156862745098%);
position: fixed;
height: 1px;
top: 3.5rem;
z-index: 999999999;
height: 2px;
`;
type Timer = ReturnType<typeof setTimeout>;

View File

@ -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&reg; EULA
</a>

View File

@ -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 (
<TitledGreyBox
title={
<p css={tw`text-sm uppercase`}>
<p className="text-sm uppercase">
{!variable.isEditable && (
<span css={tw`bg-neutral-700 text-xs py-1 px-2 rounded-full mr-2 mb-1`}>Read Only</span>
<span className="bg-neutral-700 text-xs py-1 px-2 rounded-full mr-2 mb-1">Read Only</span>
)}
{variable.name}
</p>
}
>
<FlashMessageRender byKey={FLASH_KEY} css={tw`mb-2 md:mb-4`} />
<FlashMessageRender byKey={FLASH_KEY} className="mb-2 md:mb-4" />
<InputSpinner visible={loading}>
{useSwitch ? (
<>
@ -97,7 +96,7 @@ const VariableBox = ({ variable }: Props) => {
<Select
onChange={(e) => setVariableValue(e.target.value)}
name={variable.envVariable}
defaultValue={variable.serverValue}
defaultValue={variable.serverValue ?? variable.defaultValue}
disabled={!canEdit || !variable.isEditable}
>
{selectValues.map((selectValue) => (
@ -120,7 +119,7 @@ const VariableBox = ({ variable }: Props) => {
}}
readOnly={!canEdit || !variable.isEditable}
name={variable.envVariable}
defaultValue={variable.serverValue}
defaultValue={variable.serverValue ?? ''}
placeholder={variable.defaultValue}
/>
</>
@ -128,7 +127,10 @@ const VariableBox = ({ variable }: Props) => {
</>
)}
</InputSpinner>
<p css={tw`mt-1 text-xs text-neutral-300`}>{variable.description}</p>
<p className="mt-1 text-xs text-neutral-300">
{variable.description}
</p>
</TitledGreyBox>
);
};

View File

@ -17,6 +17,7 @@ import ServerActivityLogContainer from '@/components/server/ServerActivityLogCon
import {
faBackward,
faClock,
faCogs,
faDatabase,
faEdit,
faFolder,
@ -27,7 +28,6 @@ import {
faPlayCircle,
faTerminal,
faUser,
faWheelchair,
} from '@fortawesome/free-solid-svg-icons';
// Each of the router files is already code split out appropriately — so
@ -164,7 +164,7 @@ export default {
permission: ['settings.*', 'file.sftp'],
name: 'Settings',
component: SettingsContainer,
iconProp: faWheelchair,
iconProp: faCogs,
},
{
path: '/activity',

View File

@ -27,9 +27,9 @@
</div>
<div class="box-body">
@if ($version->isLatestPanel())
You are running Pterodactyl Panel version <code>{{ config('app.version') }}</code>. Your panel is up-to-date!
You are running NookTheme <code>{{ config('app.fork-version') }}</code> based on Pterodactyl Panel version <code>{{ config('app.version') }}</code>. Your panel is up-to-date!
@else
Your panel is <strong>not up-to-date!</strong> The latest version is <a href="https://github.com/Pterodactyl/Panel/releases/v{{ $version->getPanel() }}" target="_blank"><code>{{ $version->getPanel() }}</code></a> and you are currently running version <code>{{ config('app.version') }}</code>.
Your panel is <strong>not up-to-date!</strong> The latest version is <a href="https://github.com/Nookure/NookTheme/releases/v{{ $version->getPanel() }}" target="_blank"><code>{{ $version->getPanel() }}</code></a> and you are currently running version <code>{{ config('app.version') }}</code>.
@endif
</div>
</div>

View File

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

View File

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

View File

@ -159,7 +159,7 @@
<strong><i class="fa fa-fw {{ $appIsGit ? 'fa-git-square' : 'fa-code-fork' }}"></i></strong> {{ $appVersion }}<br />
<strong><i class="fa fa-fw fa-clock-o"></i></strong> {{ round(microtime(true) - LARAVEL_START, 3) }}s
</div>
Copyright &copy; 2015 - {{ date('Y') }} <a href="https://pterodactyl.io/">Pterodactyl Software</a>.
Copyright &copy; 2022 - {{ date('Y') }} <a href="https://nookure.com/">Nookure</a>.
</footer>
</div>
@section('footer-scripts')

View File

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

View File

@ -151,7 +151,7 @@ module.exports = {
contentBase: path.join(__dirname, '/public'),
publicPath: process.env.WEBPACK_PUBLIC_PATH || '/assets/',
writeToDisk: true,
allowedHosts: ['localhost'],
disableHostCheck: true,
headers: {
'Access-Control-Allow-Origin': '*',
},