mirror of
https://github.com/pelican-dev/panel.git
synced 2025-05-19 23:24:46 +02:00
Merge branch 'pelican-dev:main' into feature/node-sftp-alias
This commit is contained in:
commit
0156456919
4
.github/workflows/ci.yaml
vendored
4
.github/workflows/ci.yaml
vendored
@ -59,7 +59,7 @@ jobs:
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: bcmath, cli, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip
|
||||
extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
|
||||
@ -119,7 +119,7 @@ jobs:
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: ${{ matrix.php }}
|
||||
extensions: bcmath, cli, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip
|
||||
extensions: bcmath, curl, gd, mbstring, mysql, openssl, pdo, tokenizer, xml, zip
|
||||
tools: composer:v2
|
||||
coverage: none
|
||||
|
||||
|
@ -98,7 +98,7 @@ class DatabaseSettingsCommand extends Command
|
||||
} elseif ($this->variables['DB_CONNECTION'] === 'sqlite') {
|
||||
$this->variables['DB_DATABASE'] = $this->option('database') ?? $this->ask(
|
||||
'Database Path',
|
||||
config('database.connections.sqlite.database', 'database.sqlite')
|
||||
env('DB_DATABASE', 'database.sqlite')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ class ProcessRunnableCommand extends Command
|
||||
->whereRelation('server', fn (Builder $builder) => $builder->whereNull('status'))
|
||||
->where('is_active', true)
|
||||
->where('is_processing', false)
|
||||
->whereDate('next_run_at', '<=', Carbon::now()->toDateString())
|
||||
->whereDate('next_run_at', '<=', Carbon::now()->toDateTimeString())
|
||||
->get();
|
||||
|
||||
if ($schedules->count() < 1) {
|
||||
|
@ -6,9 +6,9 @@ use App\Exceptions\DisplayException;
|
||||
|
||||
class TwoFactorAuthenticationTokenInvalid extends DisplayException
|
||||
{
|
||||
/**
|
||||
* TwoFactorAuthenticationTokenInvalid constructor.
|
||||
*/
|
||||
public string $title = 'Invalid 2FA Code';
|
||||
public string $icon = 'tabler-2fa';
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct('The provided two-factor authentication token was not valid.');
|
||||
|
@ -8,6 +8,7 @@ use App\Services\Eggs\Sharing\EggImporterService;
|
||||
use Exception;
|
||||
use Filament\Actions;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\Tabs;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
use Filament\Tables\Table;
|
||||
@ -62,21 +63,58 @@ class ListEggs extends ListRecords
|
||||
Actions\Action::make('import')
|
||||
->label('Import')
|
||||
->form([
|
||||
Forms\Components\FileUpload::make('egg')
|
||||
->acceptedFileTypes(['application/json'])
|
||||
->storeFiles(false)
|
||||
->multiple(),
|
||||
Tabs::make('Tabs')
|
||||
->tabs([
|
||||
Tabs\Tab::make('From File')
|
||||
->icon('tabler-file-upload')
|
||||
->schema([
|
||||
Forms\Components\FileUpload::make('egg')
|
||||
->label('Egg')
|
||||
->hint('This should be the json file ( egg-minecraft.json )')
|
||||
->acceptedFileTypes(['application/json'])
|
||||
->storeFiles(false)
|
||||
->multiple(),
|
||||
]),
|
||||
Tabs\Tab::make('From URL')
|
||||
->icon('tabler-world-upload')
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('url')
|
||||
->label('URL')
|
||||
->hint('This URL should point to a single json file')
|
||||
->url(),
|
||||
]),
|
||||
])
|
||||
->contained(false),
|
||||
|
||||
])
|
||||
->action(function (array $data): void {
|
||||
/** @var TemporaryUploadedFile $eggFile */
|
||||
$eggFile = $data['egg'];
|
||||
|
||||
/** @var EggImporterService $eggImportService */
|
||||
$eggImportService = resolve(EggImporterService::class);
|
||||
|
||||
foreach ($eggFile as $file) {
|
||||
if (!empty($data['egg'])) {
|
||||
/** @var TemporaryUploadedFile[] $eggFile */
|
||||
$eggFile = $data['egg'];
|
||||
|
||||
foreach ($eggFile as $file) {
|
||||
try {
|
||||
$eggImportService->fromFile($file);
|
||||
} catch (Exception $exception) {
|
||||
Notification::make()
|
||||
->title('Import Failed')
|
||||
->danger()
|
||||
->send();
|
||||
|
||||
report($exception);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($data['url'])) {
|
||||
try {
|
||||
$eggImportService->handle($file);
|
||||
$eggImportService->fromUrl($data['url']);
|
||||
} catch (Exception $exception) {
|
||||
Notification::make()
|
||||
->title('Import Failed')
|
||||
|
@ -371,19 +371,20 @@ class CreateServer extends CreateRecord
|
||||
$text = Forms\Components\TextInput::make('variable_value')
|
||||
->hidden($this->shouldHideComponent(...))
|
||||
->maxLength(191)
|
||||
->rules([
|
||||
->required(fn (Forms\Get $get) => in_array('required', explode('|', $get('rules'))))
|
||||
->rules(
|
||||
fn (Forms\Get $get): Closure => function (string $attribute, $value, Closure $fail) use ($get) {
|
||||
$validator = Validator::make(['validatorkey' => $value], [
|
||||
'validatorkey' => $get('rules'),
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
$message = str($validator->errors()->first())->replace('validatorkey', $get('name'));
|
||||
$message = str($validator->errors()->first())->replace('validatorkey', $get('name'))->toString();
|
||||
|
||||
$fail($message);
|
||||
}
|
||||
},
|
||||
]);
|
||||
);
|
||||
|
||||
$select = Forms\Components\Select::make('variable_value')
|
||||
->hidden($this->shouldHideComponent(...))
|
||||
|
@ -576,6 +576,7 @@ class EditServer extends EditRecord
|
||||
->options(fn (Server $server) => $server->node->mounts->mapWithKeys(fn ($mount) => [$mount->id => $mount->name]))
|
||||
->descriptions(fn (Server $server) => $server->node->mounts->mapWithKeys(fn ($mount) => [$mount->id => "$mount->source -> $mount->target"]))
|
||||
->label('Mounts')
|
||||
->helperText(fn (Server $server) => $server->node->mounts->isNotEmpty() ? '' : 'No Mounts exist for this Node')
|
||||
->columnSpanFull(),
|
||||
]),
|
||||
Tabs\Tab::make('Databases')
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Filament\Resources\UserResource\Pages;
|
||||
|
||||
use App\Filament\Resources\UserResource;
|
||||
use App\Services\Exceptions\FilamentExceptionHandler;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
use App\Models\User;
|
||||
@ -77,4 +78,9 @@ class EditUser extends EditRecord
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
public function exception($exception, $stopPropagation): void
|
||||
{
|
||||
(new FilamentExceptionHandler())->handle($exception, $stopPropagation);
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ class EggShareController extends Controller
|
||||
*/
|
||||
public function import(EggImportFormRequest $request): RedirectResponse
|
||||
{
|
||||
$egg = $this->importerService->handle($request->file('import_file'));
|
||||
$egg = $this->importerService->fromFile($request->file('import_file'));
|
||||
$this->alert->success(trans('admin/eggs.notices.imported'))->flash();
|
||||
|
||||
return redirect()->route('admin.eggs.view', ['egg' => $egg->id]);
|
||||
@ -61,7 +61,7 @@ class EggShareController extends Controller
|
||||
*/
|
||||
public function update(EggImportFormRequest $request, Egg $egg): RedirectResponse
|
||||
{
|
||||
$this->updateImporterService->handle($egg, $request->file('import_file'));
|
||||
$this->updateImporterService->fromFile($egg, $request->file('import_file'));
|
||||
$this->alert->success(trans('admin/eggs.notices.updated_via_import'))->flash();
|
||||
|
||||
return redirect()->route('admin.eggs.view', ['egg' => $egg]);
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace App\Http\Controllers\Admin\Nodes;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Node;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use App\Http\Controllers\Controller;
|
||||
@ -13,7 +12,7 @@ class NodeController extends Controller
|
||||
/**
|
||||
* Returns a listing of nodes on the system.
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
public function index(): View
|
||||
{
|
||||
$nodes = QueryBuilder::for(
|
||||
Node::query()->withCount('servers')
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace App\Http\Controllers\Admin\Nodes;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Node;
|
||||
use Illuminate\Support\Collection;
|
||||
use App\Models\Allocation;
|
||||
@ -29,16 +28,10 @@ class NodeViewController extends Controller
|
||||
/**
|
||||
* Returns index view for a specific node on the system.
|
||||
*/
|
||||
public function index(Request $request, Node $node): View
|
||||
public function index(Node $node): View
|
||||
{
|
||||
$node->loadCount('servers');
|
||||
|
||||
$stats = Node::query()
|
||||
->selectRaw('IFNULL(SUM(servers.memory), 0) as sum_memory, IFNULL(SUM(servers.disk), 0) as sum_disk')
|
||||
->join('servers', 'servers.node_id', '=', 'nodes.id')
|
||||
->where('node_id', '=', $node->id)
|
||||
->first();
|
||||
|
||||
return view('admin.nodes.view.index', [
|
||||
'node' => $node,
|
||||
'version' => $this->versionService,
|
||||
@ -48,7 +41,7 @@ class NodeViewController extends Controller
|
||||
/**
|
||||
* Returns the settings page for a specific node.
|
||||
*/
|
||||
public function settings(Request $request, Node $node): View
|
||||
public function settings(Node $node): View
|
||||
{
|
||||
return view('admin.nodes.view.settings', [
|
||||
'node' => $node,
|
||||
@ -58,7 +51,7 @@ class NodeViewController extends Controller
|
||||
/**
|
||||
* Return the node configuration page for a specific node.
|
||||
*/
|
||||
public function configuration(Request $request, Node $node): View
|
||||
public function configuration(Node $node): View
|
||||
{
|
||||
return view('admin.nodes.view.configuration', compact('node'));
|
||||
}
|
||||
@ -66,7 +59,7 @@ class NodeViewController extends Controller
|
||||
/**
|
||||
* Return the node allocation management page.
|
||||
*/
|
||||
public function allocations(Request $request, Node $node): View
|
||||
public function allocations(Node $node): View
|
||||
{
|
||||
$node->setRelation(
|
||||
'allocations',
|
||||
@ -92,7 +85,7 @@ class NodeViewController extends Controller
|
||||
/**
|
||||
* Return a listing of servers that exist for this specific node.
|
||||
*/
|
||||
public function servers(Request $request, Node $node): View
|
||||
public function servers(Node $node): View
|
||||
{
|
||||
$this->plainInject([
|
||||
'node' => Collection::wrap($node->makeVisible(['daemon_token_id', 'daemon_token']))
|
||||
|
@ -3,7 +3,6 @@
|
||||
namespace App\Http\Controllers\Admin\Servers;
|
||||
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Server;
|
||||
use Spatie\QueryBuilder\QueryBuilder;
|
||||
use Spatie\QueryBuilder\AllowedFilter;
|
||||
@ -16,7 +15,7 @@ class ServerController extends Controller
|
||||
* Returns all the servers that exist on the system using a paginated result set. If
|
||||
* a query is passed along in the request it is also passed to the repository function.
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
public function index(): View
|
||||
{
|
||||
$servers = QueryBuilder::for(Server::query()->with('node', 'user', 'allocation'))
|
||||
->allowedFilters([
|
||||
|
@ -37,7 +37,7 @@ class UserController extends Controller
|
||||
/**
|
||||
* Display user index page.
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
public function index(): View
|
||||
{
|
||||
$users = QueryBuilder::for(
|
||||
User::query()->select('users.*')
|
||||
|
@ -124,38 +124,6 @@ class EggConfigurationService
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the legacy modifies from eggs with their new counterpart. The legacy Daemon would
|
||||
* set SERVER_MEMORY, SERVER_IP, and SERVER_PORT with their respective values on the Daemon
|
||||
* side. Ensure that anything referencing those properly replaces them with the matching config
|
||||
* value.
|
||||
*/
|
||||
protected function replaceLegacyModifiers(string $key, string $value): string
|
||||
{
|
||||
switch ($key) {
|
||||
case 'config.docker.interface':
|
||||
$replace = 'config.docker.network.interface';
|
||||
break;
|
||||
case 'server.build.env.SERVER_MEMORY':
|
||||
case 'env.SERVER_MEMORY':
|
||||
$replace = 'server.build.memory';
|
||||
break;
|
||||
case 'server.build.env.SERVER_IP':
|
||||
case 'env.SERVER_IP':
|
||||
$replace = 'server.build.default.ip';
|
||||
break;
|
||||
case 'server.build.env.SERVER_PORT':
|
||||
case 'env.SERVER_PORT':
|
||||
$replace = 'server.build.default.port';
|
||||
break;
|
||||
default:
|
||||
// By default, we don't need to change anything, only if we ended up matching a specific legacy item.
|
||||
$replace = $key;
|
||||
}
|
||||
|
||||
return str_replace("{{{$key}}}", "{{{$replace}}}", $value);
|
||||
}
|
||||
|
||||
protected function matchAndReplaceKeys(mixed $value, array $structure): mixed
|
||||
{
|
||||
preg_match_all('/{{(?<key>[\w.-]*)}}/', $value, $matches);
|
||||
@ -175,8 +143,6 @@ class EggConfigurationService
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = $this->replaceLegacyModifiers($key, $value);
|
||||
|
||||
// We don't want to do anything with config keys since the Daemon will need to handle
|
||||
// that. For example, the Spigot egg uses "config.docker.interface" to identify the Docker
|
||||
// interface to proxy through, but the Panel would be unaware of that.
|
||||
@ -198,7 +164,7 @@ class EggConfigurationService
|
||||
// variable from the server configuration.
|
||||
$plucked = Arr::get(
|
||||
$structure,
|
||||
preg_replace('/^env\./', 'build.env.', $key),
|
||||
preg_replace('/^env\./', 'build.environment.', $key),
|
||||
''
|
||||
);
|
||||
|
||||
|
@ -10,6 +10,16 @@ use App\Exceptions\Service\InvalidFileUploadException;
|
||||
|
||||
class EggParserService
|
||||
{
|
||||
public const UPGRADE_VARIABLES = [
|
||||
'server.build.env.SERVER_IP' => 'server.allocations.default.ip',
|
||||
'server.build.default.ip' => 'server.allocations.default.ip',
|
||||
'server.build.env.SERVER_PORT' => 'server.allocations.default.port',
|
||||
'server.build.default.port' => 'server.allocations.default.port',
|
||||
'server.build.env.SERVER_MEMORY' => 'server.build.memory_limit',
|
||||
'server.build.memory' => 'server.build.memory_limit',
|
||||
'server.build.env' => 'server.build.environment',
|
||||
];
|
||||
|
||||
/**
|
||||
* Takes an uploaded file and parses out the egg configuration from within.
|
||||
*
|
||||
@ -26,11 +36,20 @@ class EggParserService
|
||||
|
||||
$version = $parsed['meta']['version'] ?? '';
|
||||
|
||||
return match ($version) {
|
||||
$parsed = match ($version) {
|
||||
'PTDL_v1' => $this->convertToV2($parsed),
|
||||
'PTDL_v2' => $parsed,
|
||||
default => throw new InvalidFileUploadException('The JSON file provided is not in a format that can be recognized.')
|
||||
};
|
||||
|
||||
// Make sure we only use recent variable format from now on
|
||||
$parsed['config']['files'] = str_replace(
|
||||
array_keys(self::UPGRADE_VARIABLES),
|
||||
array_values(self::UPGRADE_VARIABLES),
|
||||
$parsed['config']['files'] ?? '',
|
||||
);
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,6 +9,7 @@ use Illuminate\Http\UploadedFile;
|
||||
use App\Models\EggVariable;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use App\Services\Eggs\EggParserService;
|
||||
use Spatie\TemporaryDirectory\TemporaryDirectory;
|
||||
|
||||
class EggImporterService
|
||||
{
|
||||
@ -21,7 +22,7 @@ class EggImporterService
|
||||
*
|
||||
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
|
||||
*/
|
||||
public function handle(UploadedFile $file): Egg
|
||||
public function fromFile(UploadedFile $file): Egg
|
||||
{
|
||||
$parsed = $this->parser->handle($file);
|
||||
|
||||
@ -45,4 +46,20 @@ class EggImporterService
|
||||
return $egg;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Take an url and parse it into a new egg.
|
||||
*
|
||||
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
|
||||
*/
|
||||
public function fromUrl(string $url): Egg
|
||||
{
|
||||
$info = pathinfo($url);
|
||||
$tmpDir = TemporaryDirectory::make()->deleteWhenDestroyed();
|
||||
$tmpPath = $tmpDir->path($info['basename']);
|
||||
|
||||
file_put_contents($tmpPath, file_get_contents($url));
|
||||
|
||||
return $this->fromFile(new UploadedFile($tmpPath, $info['basename'], 'application/json'));
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use Illuminate\Support\Collection;
|
||||
use App\Models\EggVariable;
|
||||
use Illuminate\Database\ConnectionInterface;
|
||||
use App\Services\Eggs\EggParserService;
|
||||
use Spatie\TemporaryDirectory\TemporaryDirectory;
|
||||
|
||||
class EggUpdateImporterService
|
||||
{
|
||||
@ -23,7 +24,7 @@ class EggUpdateImporterService
|
||||
*
|
||||
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
|
||||
*/
|
||||
public function handle(Egg $egg, UploadedFile $file): Egg
|
||||
public function fromFile(Egg $egg, UploadedFile $file): Egg
|
||||
{
|
||||
$parsed = $this->parser->handle($file);
|
||||
|
||||
@ -47,4 +48,20 @@ class EggUpdateImporterService
|
||||
return $egg->refresh();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing Egg using an url.
|
||||
*
|
||||
* @throws \App\Exceptions\Service\InvalidFileUploadException|\Throwable
|
||||
*/
|
||||
public function fromUrl(Egg $egg, string $url): Egg
|
||||
{
|
||||
$info = pathinfo($url);
|
||||
$tmpDir = TemporaryDirectory::make()->deleteWhenDestroyed();
|
||||
$tmpPath = $tmpDir->path($info['basename']);
|
||||
|
||||
file_put_contents($tmpPath, file_get_contents($url));
|
||||
|
||||
return $this->fromFile($egg, new UploadedFile($tmpPath, $info['basename'], 'application/json'));
|
||||
}
|
||||
}
|
||||
|
24
app/Services/Exceptions/FilamentExceptionHandler.php
Normal file
24
app/Services/Exceptions/FilamentExceptionHandler.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use Filament\Notifications\Notification;
|
||||
|
||||
class FilamentExceptionHandler
|
||||
{
|
||||
public function handle(Exception $exception, callable $stopPropagation): void
|
||||
{
|
||||
Notification::make()
|
||||
->title($exception->title ?? null)
|
||||
->body($exception->body ?? $exception->getMessage())
|
||||
->color($exception->color ?? 'danger')
|
||||
->icon($exception->icon ?? 'tabler-x')
|
||||
->danger()
|
||||
->send();
|
||||
|
||||
if ($this->stopPropagation ?? true) {
|
||||
$stopPropagation();
|
||||
}
|
||||
}
|
||||
}
|
@ -27,6 +27,8 @@ class NodeUpdateService
|
||||
*/
|
||||
public function handle(Node $node, array $data, bool $resetToken = false): Node
|
||||
{
|
||||
$data['id'] = $node->id;
|
||||
|
||||
if ($resetToken) {
|
||||
$data['daemon_token'] = Str::random(Node::DAEMON_TOKEN_LENGTH);
|
||||
$data['daemon_token_id'] = Str::random(Node::DAEMON_TOKEN_ID_LENGTH);
|
||||
@ -35,15 +37,9 @@ class NodeUpdateService
|
||||
[$updated, $exception] = $this->connection->transaction(function () use ($data, $node) {
|
||||
/** @var \App\Models\Node $updated */
|
||||
$updated = $node->replicate();
|
||||
$updated->exists = true;
|
||||
$updated->forceFill($data)->save();
|
||||
try {
|
||||
// If we're changing the FQDN for the node, use the newly provided FQDN for the connection
|
||||
// address. This should alleviate issues where the node gets pointed to a "valid" FQDN that
|
||||
// isn't actually running the daemon software, and therefore you can't actually change it
|
||||
// back.
|
||||
//
|
||||
// This makes more sense anyways, because only the Panel uses the FQDN for connecting, the
|
||||
// node doesn't actually care about this.
|
||||
$node->fqdn = $updated->fqdn;
|
||||
|
||||
$this->configurationRepository->setNode($node)->update($updated);
|
||||
|
@ -9,10 +9,7 @@ return Application::configure(basePath: dirname(__DIR__))
|
||||
\Prologue\Alerts\AlertsServiceProvider::class,
|
||||
])
|
||||
->withRouting(
|
||||
web: __DIR__.'/../routes/web.php',
|
||||
// api: __DIR__.'/../routes/api.php',
|
||||
commands: __DIR__.'/../routes/console.php',
|
||||
// channels: __DIR__.'/../routes/channels.php',
|
||||
health: '/up',
|
||||
)
|
||||
->withMiddleware(function (Middleware $middleware) {
|
||||
|
@ -33,6 +33,7 @@
|
||||
"s1lentium/iptools": "~1.2.0",
|
||||
"spatie/laravel-fractal": "^6.2",
|
||||
"spatie/laravel-query-builder": "^5.8.1",
|
||||
"spatie/temporary-directory": "^2.2",
|
||||
"symfony/http-client": "^7.1",
|
||||
"symfony/mailgun-mailer": "^7.1",
|
||||
"symfony/postmark-mailer": "^7.0.7",
|
||||
|
65
composer.lock
generated
65
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "8feeafbeb16044bd6716510a73393fc0",
|
||||
"content-hash": "bf44faee3aae2b1d4c1b57893c1aba98",
|
||||
"packages": [
|
||||
{
|
||||
"name": "abdelhamiderrahmouni/filament-monaco-editor",
|
||||
@ -6990,6 +6990,67 @@
|
||||
],
|
||||
"time": "2024-05-10T08:19:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/temporary-directory",
|
||||
"version": "2.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/spatie/temporary-directory.git",
|
||||
"reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/spatie/temporary-directory/zipball/76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a",
|
||||
"reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Spatie\\TemporaryDirectory\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alex Vanderbist",
|
||||
"email": "alex@spatie.be",
|
||||
"homepage": "https://spatie.be",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Easily create, use and destroy temporary directories",
|
||||
"homepage": "https://github.com/spatie/temporary-directory",
|
||||
"keywords": [
|
||||
"php",
|
||||
"spatie",
|
||||
"temporary-directory"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/spatie/temporary-directory/issues",
|
||||
"source": "https://github.com/spatie/temporary-directory/tree/2.2.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://spatie.be/open-source/support-us",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/spatie",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2023-12-25T11:46:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/clock",
|
||||
"version": "v7.0.7",
|
||||
@ -13096,5 +13157,5 @@
|
||||
"ext-zip": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.6.0"
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
@ -75,10 +75,10 @@ class EggSeeder extends Seeder
|
||||
->first();
|
||||
|
||||
if ($egg instanceof Egg) {
|
||||
$this->updateImporterService->handle($egg, $file);
|
||||
$this->updateImporterService->fromFile($egg, $file);
|
||||
$this->command->info('Updated ' . $decoded['name']);
|
||||
} else {
|
||||
$this->importerService->handle($file);
|
||||
$this->importerService->fromFile($file);
|
||||
$this->command->comment('Created ' . $decoded['name']);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "PTDL_v2",
|
||||
"update_url": null
|
||||
},
|
||||
"exported_at": "2024-06-02T20:42:01+00:00",
|
||||
"exported_at": "2024-06-04T22:51:49+00:00",
|
||||
"name": "Bungeecord",
|
||||
"author": "panel@example.com",
|
||||
"uuid": "9e6b409e-4028-4947-aea8-50a2c404c271",
|
||||
@ -24,7 +24,7 @@
|
||||
"file_denylist": [],
|
||||
"startup": "java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}",
|
||||
"config": {
|
||||
"files": "{\r\n \"config.yml\": {\r\n \"parser\": \"yaml\",\r\n \"find\": {\r\n \"listeners[0].query_port\": \"{{server.build.default.port}}\",\r\n \"listeners[0].host\": \"0.0.0.0:{{server.build.default.port}}\",\r\n \"servers.*.address\": {\r\n \"regex:^(127\\\\.0\\\\.0\\\\.1|localhost)(:\\\\d{1,5})?$\": \"{{config.docker.interface}}$2\"\r\n }\r\n }\r\n }\r\n}",
|
||||
"files": "{\r\n \"config.yml\": {\r\n \"parser\": \"yaml\",\r\n \"find\": {\r\n \"listeners[0].query_port\": \"{{server.allocations.default.port}}\",\r\n \"listeners[0].host\": \"0.0.0.0:{{server.allocations.default.port}}\",\r\n \"servers.*.address\": {\r\n \"regex:^(127\\\\.0\\\\.0\\\\.1|localhost)(:\\\\d{1,5})?$\": \"{{config.docker.interface}}$2\"\r\n }\r\n }\r\n }\r\n}",
|
||||
"startup": "{\r\n \"done\": \"Listening on \"\r\n}",
|
||||
"logs": "{}",
|
||||
"stop": "end"
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "PTDL_v2",
|
||||
"update_url": null
|
||||
},
|
||||
"exported_at": "2024-06-02T20:42:02+00:00",
|
||||
"exported_at": "2024-06-04T22:51:58+00:00",
|
||||
"name": "Forge Minecraft",
|
||||
"author": "panel@example.com",
|
||||
"uuid": "ed072427-f209-4603-875c-f540c6dd5a65",
|
||||
@ -24,7 +24,7 @@
|
||||
"file_denylist": [],
|
||||
"startup": "java -Xms128M -XX:MaxRAMPercentage=95.0 -Dterminal.jline=false -Dterminal.ansi=true $( [[ ! -f unix_args.txt ]] && printf %s \"-jar {{SERVER_JARFILE}}\" || printf %s \"@unix_args.txt\" )",
|
||||
"config": {
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.build.default.port}}\",\r\n \"query.port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.allocations.default.port}}\",\r\n \"query.port\": \"{{server.allocations.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
"startup": "{\r\n \"done\": \")! For help, type \"\r\n}",
|
||||
"logs": "{}",
|
||||
"stop": "stop"
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "PTDL_v2",
|
||||
"update_url": null
|
||||
},
|
||||
"exported_at": "2024-06-02T20:42:02+00:00",
|
||||
"exported_at": "2024-06-04T22:51:57+00:00",
|
||||
"name": "Paper",
|
||||
"author": "parker@example.com",
|
||||
"uuid": "5da37ef6-58da-4169-90a6-e683e1721247",
|
||||
@ -24,7 +24,7 @@
|
||||
"file_denylist": [],
|
||||
"startup": "java -Xms128M -XX:MaxRAMPercentage=95.0 -Dterminal.jline=false -Dterminal.ansi=true -jar {{SERVER_JARFILE}}",
|
||||
"config": {
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.build.default.port}}\",\r\n \"query.port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.allocations.default.port}}\",\r\n \"query.port\": \"{{server.allocations.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
"startup": "{\r\n \"done\": \")! For help, type \"\r\n}",
|
||||
"logs": "{}",
|
||||
"stop": "stop"
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "PTDL_v2",
|
||||
"update_url": null
|
||||
},
|
||||
"exported_at": "2024-06-02T20:42:03+00:00",
|
||||
"exported_at": "2024-06-04T22:50:55+00:00",
|
||||
"name": "Sponge (SpongeVanilla)",
|
||||
"author": "panel@example.com",
|
||||
"uuid": "f0d2f88f-1ff3-42a0-b03f-ac44c5571e6d",
|
||||
@ -24,7 +24,7 @@
|
||||
"file_denylist": [],
|
||||
"startup": "java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}",
|
||||
"config": {
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.build.default.port}}\",\r\n \"query.port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.allocations.default.port}}\",\r\n \"query.port\": \"{{server.allocations.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
"startup": "{\r\n \"done\": \")! For help, type \"\r\n}",
|
||||
"logs": "{}",
|
||||
"stop": "stop"
|
||||
@ -60,4 +60,4 @@
|
||||
"field_type": "text"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "PTDL_v2",
|
||||
"update_url": null
|
||||
},
|
||||
"exported_at": "2024-06-02T20:42:03+00:00",
|
||||
"exported_at": "2024-06-04T22:51:16+00:00",
|
||||
"name": "Vanilla Minecraft",
|
||||
"author": "panel@example.com",
|
||||
"uuid": "9ac39f3d-0c34-4d93-8174-c52ab9e6c57b",
|
||||
@ -24,7 +24,7 @@
|
||||
"file_denylist": [],
|
||||
"startup": "java -Xms128M -XX:MaxRAMPercentage=95.0 -jar {{SERVER_JARFILE}}",
|
||||
"config": {
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.build.default.port}}\",\r\n \"query.port\": \"{{server.build.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
"files": "{\r\n \"server.properties\": {\r\n \"parser\": \"properties\",\r\n \"find\": {\r\n \"server-ip\": \"0.0.0.0\",\r\n \"server-port\": \"{{server.allocations.default.port}}\",\r\n \"query.port\": \"{{server.allocations.default.port}}\"\r\n }\r\n }\r\n}",
|
||||
"startup": "{\r\n \"done\": \")! For help, type \"\r\n}",
|
||||
"logs": "{}",
|
||||
"stop": "stop"
|
||||
|
@ -4,7 +4,7 @@
|
||||
"version": "PTDL_v2",
|
||||
"update_url": null
|
||||
},
|
||||
"exported_at": "2024-06-02T20:42:08+00:00",
|
||||
"exported_at": "2024-06-04T22:53:03+00:00",
|
||||
"name": "Mumble Server",
|
||||
"author": "panel@example.com",
|
||||
"uuid": "727ee758-7fb2-4979-972b-d3eba4e1e9f0",
|
||||
@ -16,7 +16,7 @@
|
||||
"file_denylist": [],
|
||||
"startup": "mumble-server -fg -ini murmur.ini",
|
||||
"config": {
|
||||
"files": "{\r\n \"murmur.ini\": {\r\n \"parser\": \"ini\",\r\n \"find\": {\r\n \"database\": \"\/home\/container\/murmur.sqlite\",\r\n \"logfile\": \"\/home\/container\/murmur.log\",\r\n \"port\": \"{{server.build.default.port}}\",\r\n \"host\": \"\",\r\n \"users\": \"{{server.build.env.MAX_USERS}}\"\r\n }\r\n }\r\n}",
|
||||
"files": "{\r\n \"murmur.ini\": {\r\n \"parser\": \"ini\",\r\n \"find\": {\r\n \"database\": \"\/home\/container\/murmur.sqlite\",\r\n \"logfile\": \"\/home\/container\/murmur.log\",\r\n \"port\": \"{{server.allocations.default.port}}\",\r\n \"host\": \"\",\r\n \"users\": \"{{server.environment.MAX_USERS}}\"\r\n }\r\n }\r\n}",
|
||||
"startup": "{\r\n \"done\": \"Server listening on\"\r\n}",
|
||||
"logs": "{}",
|
||||
"stop": "^C"
|
||||
|
@ -0,0 +1,92 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
$eggs = DB::table('eggs')->get();
|
||||
|
||||
foreach ($eggs as $egg) {
|
||||
$updatedPort = str_replace(
|
||||
'server.build.default.port',
|
||||
'server.allocations.default.port',
|
||||
$egg->config_files
|
||||
);
|
||||
|
||||
if ($updatedPort !== $egg->config_files) {
|
||||
$egg->config_files = $updatedPort;
|
||||
echo "Processed Port update with ID: {$egg->name}\n";
|
||||
}
|
||||
|
||||
$updatedIp = str_replace(
|
||||
'server.build.default.ip',
|
||||
'server.allocations.default.ip',
|
||||
$egg->config_files
|
||||
);
|
||||
|
||||
if ($updatedIp !== $egg->config_files) {
|
||||
$egg->config_files = $updatedIp;
|
||||
echo "Processed IP update with ID: {$egg->name}\n";
|
||||
}
|
||||
|
||||
$updatedEnv = str_replace(
|
||||
'server.build.env.',
|
||||
'server.environment.',
|
||||
$egg->config_files
|
||||
);
|
||||
|
||||
if ($updatedEnv !== $egg->config_files) {
|
||||
$egg->config_files = $updatedEnv;
|
||||
echo "Processed ENV update with ID: {$egg->name}\n";
|
||||
}
|
||||
|
||||
DB::table('eggs')
|
||||
->where('id', $egg->id)
|
||||
->update(['config_files' => $egg->config_files]);
|
||||
}
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
$eggs = DB::table('eggs')->get();
|
||||
|
||||
foreach ($eggs as $egg) {
|
||||
$revertedEnv = str_replace(
|
||||
'server.environment.',
|
||||
'server.build.env.',
|
||||
$egg->config_files
|
||||
);
|
||||
|
||||
if ($revertedEnv !== $egg->config_files) {
|
||||
$egg->config_files = $revertedEnv;
|
||||
}
|
||||
|
||||
$revertedIp = str_replace(
|
||||
'server.allocations.default.ip',
|
||||
'server.build.default.ip',
|
||||
$egg->config_files
|
||||
);
|
||||
|
||||
if ($revertedIp !== $egg->config_files) {
|
||||
$egg->config_files = $revertedIp;
|
||||
}
|
||||
|
||||
$revertedPort = str_replace(
|
||||
'server.allocations.default.port',
|
||||
'server.build.default.port',
|
||||
$egg->config_files
|
||||
);
|
||||
|
||||
if ($revertedPort !== $egg->config_files) {
|
||||
$egg->config_files = $revertedPort;
|
||||
}
|
||||
|
||||
DB::table('eggs')
|
||||
->where('id', $egg->id)
|
||||
->update(['config_files' => $egg->config_files]);
|
||||
}
|
||||
}
|
||||
};
|
58
readme.md
58
readme.md
@ -26,46 +26,20 @@ This gives you the power to run game servers without bloating machines with a ho
|
||||
|
||||
Some of our popular eggs include but are not limited to:
|
||||
|
||||
* [Minecraft](https://github.com/pelican-eggs/minecraft)
|
||||
* Paper
|
||||
* Sponge
|
||||
* Bungeecord
|
||||
* Waterfall
|
||||
* [SteamCMD](https://github.com/pelican-eggs/steamcmd)
|
||||
* 7 Days to Die
|
||||
* ARK: Survival
|
||||
* ARMA
|
||||
* Counter Strike
|
||||
* DayZ
|
||||
* Enshrouded
|
||||
* Left 4 Dead
|
||||
* Palworld
|
||||
* Project Zomboid
|
||||
* Sons of the Forest
|
||||
* [Other Games](https://github.com/pelican-eggs/games)
|
||||
* Among Us
|
||||
* Factorio
|
||||
* GTA
|
||||
* Rimworld
|
||||
* Terraria
|
||||
* [Discord Bots](https://github.com/pelican-eggs/chatbots)
|
||||
* Redbot
|
||||
* JMusicBot
|
||||
* SinusBot
|
||||
* Dynamica
|
||||
* [Software](https://github.com/pelican-eggs/software)
|
||||
* [Programming Languages](https://github.com/pelican-eggs/generic)
|
||||
* C#
|
||||
* Java
|
||||
* Lua
|
||||
* Node.js
|
||||
* Python
|
||||
* [Database](https://github.com/pelican-eggs/database)
|
||||
* Redis
|
||||
* MariaDB
|
||||
* PostgreSQL
|
||||
* [Voice Servers](https://github.com/pelican-eggs/voice)
|
||||
* [Storage](https://github.com/pelican-eggs/storage)
|
||||
* [Monitoring](https://github.com/pelican-eggs/monitoring)
|
||||
| Category | Eggs | | | |
|
||||
|----------------------------------------------------------------------|-----------------|---------------|--------------------|----------------|
|
||||
| [Minecraft](https://github.com/pelican-eggs/minecraft) | Paper | Sponge | Bungeecord | Waterfall |
|
||||
| [SteamCMD](https://github.com/pelican-eggs/steamcmd) | 7 Days to Die | ARK: Survival | Arma 3 | Counter Strike |
|
||||
| | DayZ | Enshrouded | Left 4 Dead | Palworld |
|
||||
| | Project Zomboid | Satisfactory | Sons of the Forest | Starbound |
|
||||
| [Standalone Games](https://github.com/pelican-eggs/games-standalone) | Among Us | Factorio | FTL | GTA |
|
||||
| | Kerbal Space | Mindustry | Rimworld | Terraria |
|
||||
| [Discord Bots](https://github.com/pelican-eggs/chatbots) | Redbot | JMusicBot | JMusicBot | Dynamica |
|
||||
| [Voice Servers](https://github.com/pelican-eggs/voice) | Mumble | Teamspeak | Lavalink | |
|
||||
| [Software](https://github.com/pelican-eggs/software) | Elasticsearch | Gitea | Grafana | RabbitMQ |
|
||||
| [Programming](https://github.com/pelican-eggs/generic) | Node.js | Python | Java | C# |
|
||||
| [Databases](https://github.com/pelican-eggs/database) | Redis | MariaDB | PostgreSQL | MongoDB |
|
||||
| [Storage](https://github.com/pelican-eggs/storage) | S3 | SFTP Share | | |
|
||||
| [Monitoring](https://github.com/pelican-eggs/monitoring) | Prometheus | Loki | | |
|
||||
|
||||
Copyright Pelican® 2024
|
||||
*Copyright Pelican® 2024*
|
||||
|
Loading…
x
Reference in New Issue
Block a user