diff --git a/.env.example b/.env.example index eab42b85a..c91d26013 100644 --- a/.env.example +++ b/.env.example @@ -17,9 +17,6 @@ CACHE_STORE=file QUEUE_CONNECTION=database SESSION_DRIVER=file -HASHIDS_SALT= -HASHIDS_LENGTH=8 - MAIL_MAILER=log MAIL_HOST=smtp.example.com MAIL_PORT=25 diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index bcc56c1a7..998654549 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -34,7 +34,6 @@ jobs: MAIL_MAILER: array SESSION_DRIVER: array QUEUE_CONNECTION: sync - HASHIDS_SALT: alittlebitofsalt1234 DB_CONNECTION: mysql DB_HOST: 127.0.0.1 DB_DATABASE: testing @@ -97,7 +96,6 @@ jobs: MAIL_MAILER: array SESSION_DRIVER: array QUEUE_CONNECTION: sync - HASHIDS_SALT: alittlebitofsalt1234 DB_CONNECTION: sqlite DB_DATABASE: testing.sqlite steps: diff --git a/app/Console/Commands/Environment/AppSettingsCommand.php b/app/Console/Commands/Environment/AppSettingsCommand.php index 8a01437fa..ff75057a3 100644 --- a/app/Console/Commands/Environment/AppSettingsCommand.php +++ b/app/Console/Commands/Environment/AppSettingsCommand.php @@ -32,7 +32,6 @@ class AppSettingsCommand extends Command protected $description = 'Configure basic environment settings for the Panel.'; protected $signature = 'p:environment:setup - {--new-salt : Whether or not to generate a new salt for Hashids.} {--url= : The URL that this Panel is running on.} {--cache= : The cache driver backend to use.} {--session= : The session driver backend to use.} @@ -61,10 +60,6 @@ class AppSettingsCommand extends Command { $this->variables['APP_TIMEZONE'] = 'UTC'; - if (empty(config('hashids.salt')) || $this->option('new-salt')) { - $this->variables['HASHIDS_SALT'] = str_random(20); - } - $this->output->comment(__('commands.appsettings.comment.url')); $this->variables['APP_URL'] = $this->option('url') ?? $this->ask( 'Application URL', diff --git a/app/Console/Commands/Schedule/ProcessRunnableCommand.php b/app/Console/Commands/Schedule/ProcessRunnableCommand.php index 343328cc8..687752a2d 100644 --- a/app/Console/Commands/Schedule/ProcessRunnableCommand.php +++ b/app/Console/Commands/Schedule/ProcessRunnableCommand.php @@ -62,7 +62,7 @@ class ProcessRunnableCommand extends Command $this->line(trans('command/messages.schedule.output_line', [ 'schedule' => $schedule->name, - 'hash' => $schedule->hashid, + 'id' => $schedule->id, ])); } catch (\Throwable|\Exception $exception) { logger()->error($exception, ['schedule_id' => $schedule->id]); diff --git a/app/Contracts/Extensions/HashidsInterface.php b/app/Contracts/Extensions/HashidsInterface.php deleted file mode 100644 index 4f02d0bea..000000000 --- a/app/Contracts/Extensions/HashidsInterface.php +++ /dev/null @@ -1,15 +0,0 @@ -url())->contains('livewire')) { + if ($request->is('livewire/update')) { Notification::make() ->title(static::class) ->body($this->getMessage()) diff --git a/app/Extensions/Hashids.php b/app/Extensions/Hashids.php deleted file mode 100644 index 25ce002fc..000000000 --- a/app/Extensions/Hashids.php +++ /dev/null @@ -1,22 +0,0 @@ -decode($encoded); - if (!is_array($result)) { - return $default; - } - - return array_first($result, null, $default); - } -} diff --git a/app/Filament/Resources/NodeResource/Pages/CreateNode.php b/app/Filament/Resources/NodeResource/Pages/CreateNode.php index 899e7b3ab..1d506083e 100644 --- a/app/Filament/Resources/NodeResource/Pages/CreateNode.php +++ b/app/Filament/Resources/NodeResource/Pages/CreateNode.php @@ -337,6 +337,7 @@ class CreateNode extends CreateRecord ->suffix('%') ->columnSpan(2) ->numeric() + ->default(0) ->minValue(0), Forms\Components\TextInput::make('cpu_overallocate') ->dehydratedWhenHidden() @@ -346,6 +347,7 @@ class CreateNode extends CreateRecord ->hintIconTooltip('The % allowable to go over the set limit.') ->columnSpan(2) ->numeric() + ->default(0) ->minValue(-1) ->maxValue(100) ->suffix('%'), diff --git a/app/Filament/Resources/NodeResource/Pages/EditNode.php b/app/Filament/Resources/NodeResource/Pages/EditNode.php index a5126f694..ca0ac657f 100644 --- a/app/Filament/Resources/NodeResource/Pages/EditNode.php +++ b/app/Filament/Resources/NodeResource/Pages/EditNode.php @@ -6,9 +6,11 @@ use App\Filament\Resources\NodeResource; use App\Filament\Resources\NodeResource\Widgets\NodeMemoryChart; use App\Filament\Resources\NodeResource\Widgets\NodeStorageChart; use App\Models\Node; +use App\Services\Nodes\NodeUpdateService; use Filament\Actions; use Filament\Forms; use Filament\Forms\Components\Tabs; +use Filament\Notifications\Notification; use Filament\Resources\Pages\EditRecord; use Illuminate\Support\HtmlString; use Webbingbrasil\FilamentCopyActions\Forms\Actions\CopyAction; @@ -374,6 +376,18 @@ class EditNode extends EditRecord ->rows(19) ->hintAction(CopyAction::make()) ->columnSpanFull(), + Forms\Components\Actions::make([ + Forms\Components\Actions\Action::make('resetKey') + ->label('Reset Daemon Token') + ->color('danger') + ->requiresConfirmation() + ->modalHeading('Reset Daemon Token?') + ->modalDescription('Resetting the daemon token will void any request coming from the old token. This token is used for all sensitive operations on the daemon including server creation and deletion. We suggest changing this token regularly for security.') + ->action(fn (NodeUpdateService $nodeUpdateService, Node $node) => $nodeUpdateService->handle($node, [], true) + && Notification::make()->success()->title('Daemon Key Reset')->send() + && $this->fillForm() + ), + ]), ]), ]), ]); diff --git a/app/Http/Controllers/Api/Application/Nodes/NodeDeploymentController.php b/app/Http/Controllers/Api/Application/Nodes/NodeDeploymentController.php index f00c8d667..7a16fab01 100644 --- a/app/Http/Controllers/Api/Application/Nodes/NodeDeploymentController.php +++ b/app/Http/Controllers/Api/Application/Nodes/NodeDeploymentController.php @@ -24,8 +24,8 @@ class NodeDeploymentController extends ApplicationApiController $data = $request->validated(); $nodes = $this->viableNodesService->handle( - $data['disk'] ?? 0, $data['memory'] ?? 0, + $data['disk'] ?? 0, $data['cpu'] ?? 0, $data['tags'] ?? $data['location_ids'] ?? [], ); diff --git a/app/Http/Requests/Api/Application/Servers/StoreServerRequest.php b/app/Http/Requests/Api/Application/Servers/StoreServerRequest.php index fd735edf0..263b7c540 100644 --- a/app/Http/Requests/Api/Application/Servers/StoreServerRequest.php +++ b/app/Http/Requests/Api/Application/Servers/StoreServerRequest.php @@ -56,11 +56,10 @@ class StoreServerRequest extends ApplicationApiRequest // Automatic deployment rules 'deploy' => 'sometimes|required|array', 'deploy.locations' => 'array', - 'deploy.locations.*' => 'integer|min:1', + 'deploy.locations.*' => 'required_with:deploy.locations,integer|min:1', 'deploy.dedicated_ip' => 'required_with:deploy,boolean', 'deploy.port_range' => 'array', 'deploy.port_range.*' => 'string', - 'start_on_completion' => 'sometimes|boolean', ]; } diff --git a/app/Models/Allocation.php b/app/Models/Allocation.php index 6a7d45db7..33bc7f16d 100644 --- a/app/Models/Allocation.php +++ b/app/Models/Allocation.php @@ -22,7 +22,6 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; * @property bool $has_alias * @property \App\Models\Server|null $server * @property \App\Models\Node $node - * @property string $hashid * * @method static \Database\Factories\AllocationFactory factory(...$parameters) * @method static \Illuminate\Database\Eloquent\Builder|Allocation newModelQuery() @@ -88,14 +87,6 @@ class Allocation extends Model return $this->getKeyName(); } - /** - * Return a hashid encoded string to represent the ID of the allocation. - */ - public function getHashidAttribute(): string - { - return app()->make('hashids')->encode($this->id); - } - /** * Accessor to automatically provide the IP alias if defined. */ diff --git a/app/Models/Database.php b/app/Models/Database.php index 46a49ca35..bd6bc6de3 100644 --- a/app/Models/Database.php +++ b/app/Models/Database.php @@ -2,9 +2,7 @@ namespace App\Models; -use Illuminate\Container\Container; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use App\Contracts\Extensions\HashidsInterface; use Illuminate\Support\Facades\DB; /** @@ -73,26 +71,6 @@ class Database extends Model return $this->getKeyName(); } - /** - * Resolves the database using the ID by checking if the value provided is a HashID - * string value, or just the ID to the database itself. - * - * @param mixed $value - * @param string|null $field - * - * @throws \Illuminate\Contracts\Container\BindingResolutionException - */ - public function resolveRouteBinding($value, $field = null): ?\Illuminate\Database\Eloquent\Model - { - if (is_scalar($value) && ($field ?? $this->getRouteKeyName()) === 'id') { - $value = ctype_digit((string) $value) - ? $value - : Container::getInstance()->make(HashidsInterface::class)->decodeFirst($value); - } - - return $this->where($field ?? $this->getRouteKeyName(), $value)->firstOrFail(); - } - /** * Gets the host database server associated with a database. */ diff --git a/app/Models/Node.php b/app/Models/Node.php index 7a732ca7a..65aeaa0ea 100644 --- a/app/Models/Node.php +++ b/app/Models/Node.php @@ -63,10 +63,6 @@ class Node extends Model */ protected $hidden = ['daemon_token_id', 'daemon_token']; - public int $sum_memory; - public int $sum_disk; - public int $sum_cpu; - /** * Fields that are mass assignable. */ @@ -241,11 +237,28 @@ class Node extends Model */ public function isViable(int $memory, int $disk, int $cpu): bool { - $memoryLimit = $this->memory * (1 + ($this->memory_overallocate / 100)); - $diskLimit = $this->disk * (1 + ($this->disk_overallocate / 100)); - $cpuLimit = $this->cpu * (1 + ($this->cpu_overallocate / 100)); + if ($this->memory_overallocate >= 0) { + $memoryLimit = $this->memory * (1 + ($this->memory_overallocate / 100)); + if ($this->servers_sum_memory + $memory > $memoryLimit) { + return false; + } + } - return ($this->sum_memory + $memory) <= $memoryLimit && ($this->sum_disk + $disk) <= $diskLimit && ($this->sum_cpu + $cpu) <= $cpuLimit; + if ($this->disk_overallocate >= 0) { + $diskLimit = $this->disk * (1 + ($this->disk_overallocate / 100)); + if ($this->servers_sum_disk + $disk > $diskLimit) { + return false; + } + } + + if ($this->cpu_overallocate >= 0) { + $cpuLimit = $this->cpu * (1 + ($this->cpu_overallocate / 100)); + if ($this->servers_sum_cpu + $cpu > $cpuLimit) { + return false; + } + } + + return true; } public static function getForServerCreation() diff --git a/app/Models/Schedule.php b/app/Models/Schedule.php index 8fb3f4167..7042d25a4 100644 --- a/app/Models/Schedule.php +++ b/app/Models/Schedule.php @@ -4,10 +4,8 @@ namespace App\Models; use Cron\CronExpression; use Carbon\CarbonImmutable; -use Illuminate\Container\Container; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use App\Contracts\Extensions\HashidsInterface; /** * @property int $id @@ -25,7 +23,6 @@ use App\Contracts\Extensions\HashidsInterface; * @property \Carbon\Carbon|null $next_run_at * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at - * @property string $hashid * @property \App\Models\Server $server * @property \App\Models\Task[]|\Illuminate\Support\Collection $tasks */ @@ -124,14 +121,6 @@ class Schedule extends Model ); } - /** - * Return a hashid encoded string to represent the ID of the schedule. - */ - public function getHashidAttribute(): string - { - return Container::getInstance()->make(HashidsInterface::class)->encode($this->id); - } - /** * Return tasks belonging to a schedule. */ diff --git a/app/Models/Subuser.php b/app/Models/Subuser.php index 0c1f4d382..566c8a741 100644 --- a/app/Models/Subuser.php +++ b/app/Models/Subuser.php @@ -52,14 +52,6 @@ class Subuser extends Model ]; } - /** - * Return a hashid encoded string to represent the ID of the subuser. - */ - public function getHashidAttribute(): string - { - return app()->make('hashids')->encode($this->id); - } - /** * Gets the server associated with a subuser. */ diff --git a/app/Models/Task.php b/app/Models/Task.php index 591bfcfbb..6545ab5f5 100644 --- a/app/Models/Task.php +++ b/app/Models/Task.php @@ -2,10 +2,8 @@ namespace App\Models; -use Illuminate\Container\Container; use Illuminate\Database\Eloquent\Relations\HasOneThrough; use Illuminate\Database\Eloquent\Relations\BelongsTo; -use App\Contracts\Extensions\HashidsInterface; /** * @property int $id @@ -18,7 +16,6 @@ use App\Contracts\Extensions\HashidsInterface; * @property bool $continue_on_failure * @property \Carbon\Carbon $created_at * @property \Carbon\Carbon $updated_at - * @property string $hashid * @property \App\Models\Schedule $schedule * @property \App\Models\Server $server */ @@ -96,14 +93,6 @@ class Task extends Model return $this->getKeyName(); } - /** - * Return a hashid encoded string to represent the ID of the task. - */ - public function getHashidAttribute(): string - { - return Container::getInstance()->make(HashidsInterface::class)->encode($this->id); - } - /** * Return the schedule that a task belongs to. */ diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 575fa500b..60339c744 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -35,11 +35,13 @@ class AdminPanelProvider extends PanelProvider ->default() ->id('admin') ->path('admin') - ->topNavigation(config('panel.filament.top-navigation', false)) + ->topNavigation(config('panel.filament.top-navigation', true)) ->login() ->homeUrl('/') - ->favicon('/pelican.ico') - ->brandName('Pelican') + ->favicon(config('app.favicon', '/pelican.ico')) + ->brandName(config('app.name', 'Pelican')) + ->brandLogo(config('app.logo')) + ->brandLogoHeight('2rem') ->profile(EditProfile::class, false) ->colors([ 'danger' => Color::Red, diff --git a/app/Providers/HashidsServiceProvider.php b/app/Providers/HashidsServiceProvider.php deleted file mode 100644 index 4639bfaed..000000000 --- a/app/Providers/HashidsServiceProvider.php +++ /dev/null @@ -1,26 +0,0 @@ -app->singleton(HashidsInterface::class, function () { - return new Hashids( - config('hashids.salt', ''), - config('hashids.length', 0), - config('hashids.alphabet', 'abcdefghijkmlnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890') - ); - }); - - $this->app->alias(HashidsInterface::class, 'hashids'); - } -} diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 449a083c5..432ededc0 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -3,7 +3,6 @@ namespace App\Providers; use Illuminate\Http\Request; -use App\Models\Database; use Illuminate\Foundation\Http\Middleware\TrimStrings; use Illuminate\Support\Facades\Route; use Illuminate\Cache\RateLimiting\Limit; @@ -29,11 +28,6 @@ class RouteServiceProvider extends ServiceProvider return preg_match(self::FILE_PATH_REGEX, $request->getPathInfo()) === 1; }); - // This is needed to make use of the "resolveRouteBinding" functionality in the - // model. Without it you'll never trigger that logic flow thus resulting in a 404 - // error because we request databases with a HashID, and not with a normal ID. - Route::model('database', Database::class); - $this->routes(function () { Route::middleware('web')->group(function () { Route::middleware(['auth.session', RequireTwoFactorAuthentication::class]) diff --git a/app/Services/Deployment/FindViableNodesService.php b/app/Services/Deployment/FindViableNodesService.php index 9a51d1c6f..4cffc71d2 100644 --- a/app/Services/Deployment/FindViableNodesService.php +++ b/app/Services/Deployment/FindViableNodesService.php @@ -17,19 +17,17 @@ class FindViableNodesService * are tossed out, as are any nodes marked as non-public, meaning automatic * deployments should not be done against them. */ - public function handle(int $disk = 0, int $memory = 0, int $cpu = 0, $tags = []): Collection + public function handle(int $memory = 0, int $disk = 0, int $cpu = 0, $tags = []): Collection { $nodes = Node::query() - ->withSum('servers', 'disk') ->withSum('servers', 'memory') + ->withSum('servers', 'disk') ->withSum('servers', 'cpu') ->where('public', true) ->get(); return $nodes ->filter(fn (Node $node) => !$tags || collect($node->tags)->intersect($tags)) - ->filter(fn (Node $node) => $node->servers_sum_disk + $disk <= $node->disk * (1 + $node->disk_overallocate / 100)) - ->filter(fn (Node $node) => $node->servers_sum_memory + $memory <= $node->memory * (1 + $node->memory_overallocate / 100)) - ->filter(fn (Node $node) => $node->servers_sum_cpu + $cpu <= $node->cpu * (1 + $node->cpu_overallocate / 100)); + ->filter(fn (Node $node) => $node->isViable($memory, $disk, $cpu)); } } diff --git a/app/Services/Nodes/NodeUpdateService.php b/app/Services/Nodes/NodeUpdateService.php index c4f769f8a..f948686ed 100644 --- a/app/Services/Nodes/NodeUpdateService.php +++ b/app/Services/Nodes/NodeUpdateService.php @@ -34,8 +34,8 @@ class NodeUpdateService [$updated, $exception] = $this->connection->transaction(function () use ($data, $node) { /** @var \App\Models\Node $updated */ - $updated = $node->replicate()->forceFill($data)->save(); - + $updated = $node->replicate(); + $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 diff --git a/app/Services/Servers/ServerCreationService.php b/app/Services/Servers/ServerCreationService.php index 8953b1325..57d8ad086 100644 --- a/app/Services/Servers/ServerCreationService.php +++ b/app/Services/Servers/ServerCreationService.php @@ -109,8 +109,8 @@ class ServerCreationService { /** @var Collection<\App\Models\Node> $nodes */ $nodes = $this->findViableNodesService->handle( - Arr::get($data, 'disk', 0), Arr::get($data, 'memory', 0), + Arr::get($data, 'disk', 0), Arr::get($data, 'cpu', 0), Arr::get($data, 'tags', []), ); diff --git a/app/Services/Servers/TransferServerService.php b/app/Services/Servers/TransferServerService.php index 2cc34db70..72bac7dda 100644 --- a/app/Services/Servers/TransferServerService.php +++ b/app/Services/Servers/TransferServerService.php @@ -58,7 +58,9 @@ class TransferServerService // Check if the node is viable for the transfer. $node = Node::query() ->select(['nodes.id', 'nodes.fqdn', 'nodes.scheme', 'nodes.daemon_token', 'nodes.daemon_listen', 'nodes.memory', 'nodes.disk', 'nodes.cpu', 'nodes.memory_overallocate', 'nodes.disk_overallocate', 'nodes.cpu_overallocate']) - ->selectRaw('IFNULL(SUM(servers.memory), 0) as sum_memory, IFNULL(SUM(servers.disk), 0) as sum_disk, IFNULL(SUM(servers.cpu), 0) as sum_cpu') + ->withSum('servers', 'disk') + ->withSum('servers', 'memory') + ->withSum('servers', 'cpu') ->leftJoin('servers', 'servers.node_id', '=', 'nodes.id') ->where('nodes.id', $node_id) ->first(); diff --git a/app/Transformers/Api/Client/ActivityLogTransformer.php b/app/Transformers/Api/Client/ActivityLogTransformer.php index af666beb6..d02f95988 100644 --- a/app/Transformers/Api/Client/ActivityLogTransformer.php +++ b/app/Transformers/Api/Client/ActivityLogTransformer.php @@ -55,7 +55,7 @@ class ActivityLogTransformer extends BaseClientTransformer $properties = $model->properties ->mapWithKeys(function ($value, $key) use ($model) { - if ($key === 'ip' && !$model->actor->is($this->request->user())) { + if ($key === 'ip' && $model->actor && !$model->actor->is($this->request->user())) { return [$key => '[hidden]']; } diff --git a/app/Transformers/Api/Client/DatabaseTransformer.php b/app/Transformers/Api/Client/DatabaseTransformer.php index 2d3077976..1a3855939 100644 --- a/app/Transformers/Api/Client/DatabaseTransformer.php +++ b/app/Transformers/Api/Client/DatabaseTransformer.php @@ -6,22 +6,11 @@ use App\Models\Database; use League\Fractal\Resource\Item; use App\Models\Permission; use League\Fractal\Resource\NullResource; -use App\Contracts\Extensions\HashidsInterface; class DatabaseTransformer extends BaseClientTransformer { protected array $availableIncludes = ['password']; - private HashidsInterface $hashids; - - /** - * Handle dependency injection. - */ - public function handle(HashidsInterface $hashids) - { - $this->hashids = $hashids; - } - public function getResourceName(): string { return Database::RESOURCE_NAME; @@ -32,7 +21,7 @@ class DatabaseTransformer extends BaseClientTransformer $model->loadMissing('host'); return [ - 'id' => $this->hashids->encode($model->id), + 'id' => $model->id, 'host' => [ 'address' => $model->getRelation('host')->host, 'port' => $model->getRelation('host')->port, diff --git a/bootstrap/providers.php b/bootstrap/providers.php index 04b20a98c..80be25c8e 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -6,7 +6,6 @@ return [ App\Providers\BackupsServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\Filament\AdminPanelProvider::class, - App\Providers\HashidsServiceProvider::class, App\Providers\RouteServiceProvider::class, App\Providers\ViewComposerServiceProvider::class, ]; diff --git a/composer.json b/composer.json index 29ef59290..407c79890 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,6 @@ "doctrine/dbal": "~3.6.0", "filament/filament": "^3.2", "guzzlehttp/guzzle": "^7.8.1", - "hashids/hashids": "~5.0.0", "laracasts/utilities": "~3.2.2", "laravel/framework": "^11.7", "laravel/helpers": "^1.7", @@ -34,7 +33,8 @@ "s1lentium/iptools": "~1.2.0", "spatie/laravel-fractal": "^6.2", "spatie/laravel-query-builder": "^5.8.1", - "symfony/mailgun-mailer": "^7.0.7", + "symfony/http-client": "^7.1", + "symfony/mailgun-mailer": "^7.1", "symfony/postmark-mailer": "^7.0.7", "symfony/yaml": "^7.0.7", "webbingbrasil/filament-copyactions": "^3.0.1", diff --git a/composer.lock b/composer.lock index 7a8205f17..d92e3bd6f 100644 --- a/composer.lock +++ b/composer.lock @@ -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": "dc1c1e5ee766f2e31e84c50670fa0c98", + "content-hash": "328bdd29cb83793ec0a99b2210941740", "packages": [ { "name": "abdelhamiderrahmouni/filament-monaco-editor", @@ -2613,75 +2613,6 @@ ], "time": "2023-12-03T19:50:20+00:00" }, - { - "name": "hashids/hashids", - "version": "5.0.2", - "source": { - "type": "git", - "url": "https://github.com/vinkla/hashids.git", - "reference": "197171016b77ddf14e259e186559152eb3f8cf33" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/vinkla/hashids/zipball/197171016b77ddf14e259e186559152eb3f8cf33", - "reference": "197171016b77ddf14e259e186559152eb3f8cf33", - "shasum": "" - }, - "require": { - "ext-mbstring": "*", - "php": "^8.1" - }, - "require-dev": { - "phpunit/phpunit": "^10.0" - }, - "suggest": { - "ext-bcmath": "Required to use BC Math arbitrary precision mathematics (*).", - "ext-gmp": "Required to use GNU multiple precision mathematics (*)." - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, - "autoload": { - "psr-4": { - "Hashids\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Ivan Akimov", - "email": "ivan@barreleye.com" - }, - { - "name": "Vincent Klaiber", - "email": "hello@doubledip.se" - } - ], - "description": "Generate short, unique, non-sequential ids (like YouTube and Bitly) from numbers", - "homepage": "https://hashids.org/php", - "keywords": [ - "bitly", - "decode", - "encode", - "hash", - "hashid", - "hashids", - "ids", - "obfuscate", - "youtube" - ], - "support": { - "issues": "https://github.com/vinkla/hashids/issues", - "source": "https://github.com/vinkla/hashids/tree/5.0.2" - }, - "time": "2023-02-23T15:00:54+00:00" - }, { "name": "kirschbaum-development/eloquent-power-joins", "version": "3.5.6", @@ -7722,6 +7653,178 @@ ], "time": "2024-04-18T09:29:19+00:00" }, + { + "name": "symfony/http-client", + "version": "v7.1.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client.git", + "reference": "2266f9813ed7d8c84e04627edead7b7fd249d6e9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client/zipball/2266f9813ed7d8c84e04627edead7b7fd249d6e9", + "reference": "2266f9813ed7d8c84e04627edead7b7fd249d6e9", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/http-client-contracts": "^3.4.1", + "symfony/service-contracts": "^2.5|^3" + }, + "conflict": { + "php-http/discovery": "<1.15", + "symfony/http-foundation": "<6.4" + }, + "provide": { + "php-http/async-client-implementation": "*", + "php-http/client-implementation": "*", + "psr/http-client-implementation": "1.0", + "symfony/http-client-implementation": "3.0" + }, + "require-dev": { + "amphp/amp": "^2.5", + "amphp/http-client": "^4.2.1", + "amphp/http-tunnel": "^1.0", + "amphp/socket": "^1.1", + "guzzlehttp/promises": "^1.4|^2.0", + "nyholm/psr7": "^1.0", + "php-http/httplug": "^1.0|^2.0", + "psr/http-client": "^1.0", + "symfony/dependency-injection": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/messenger": "^6.4|^7.0", + "symfony/process": "^6.4|^7.0", + "symfony/rate-limiter": "^6.4|^7.0", + "symfony/stopwatch": "^6.4|^7.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", + "homepage": "https://symfony.com", + "keywords": [ + "http" + ], + "support": { + "source": "https://github.com/symfony/http-client/tree/v7.1.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-05-13T15:35:37+00:00" + }, + { + "name": "symfony/http-client-contracts", + "version": "v3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/http-client-contracts.git", + "reference": "20414d96f391677bf80078aa55baece78b82647d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/20414d96f391677bf80078aa55baece78b82647d", + "reference": "20414d96f391677bf80078aa55baece78b82647d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.5-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\HttpClient\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to HTTP clients", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2024-04-18T09:32:20+00:00" + }, { "name": "symfony/http-foundation", "version": "v7.0.7", @@ -7994,16 +8097,16 @@ }, { "name": "symfony/mailgun-mailer", - "version": "v7.0.7", + "version": "v7.1.0", "source": { "type": "git", "url": "https://github.com/symfony/mailgun-mailer.git", - "reference": "e9bb8fdbdd79334a8a88bdd233204315abd992c5" + "reference": "aa5afbe846bbc8bde6afe2602f0427834b872f55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/e9bb8fdbdd79334a8a88bdd233204315abd992c5", - "reference": "e9bb8fdbdd79334a8a88bdd233204315abd992c5", + "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/aa5afbe846bbc8bde6afe2602f0427834b872f55", + "reference": "aa5afbe846bbc8bde6afe2602f0427834b872f55", "shasum": "" }, "require": { @@ -8043,7 +8146,7 @@ "description": "Symfony Mailgun Mailer Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailgun-mailer/tree/v7.0.7" + "source": "https://github.com/symfony/mailgun-mailer/tree/v7.1.0" }, "funding": [ { @@ -8059,7 +8162,7 @@ "type": "tidelift" } ], - "time": "2024-04-18T09:29:19+00:00" + "time": "2024-04-18T09:32:20+00:00" }, { "name": "symfony/mime", @@ -13061,5 +13164,5 @@ "ext-zip": "*" }, "platform-dev": [], - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } diff --git a/config/hashids.php b/config/hashids.php deleted file mode 100644 index 199de1a32..000000000 --- a/config/hashids.php +++ /dev/null @@ -1,15 +0,0 @@ - env('HASHIDS_SALT'), - 'length' => env('HASHIDS_LENGTH', 8), - 'alphabet' => env('HASHIDS_ALPHABET', 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'), -]; diff --git a/lang/en/command/messages.php b/lang/en/command/messages.php index 4e640b3fa..50adf0fa3 100644 --- a/lang/en/command/messages.php +++ b/lang/en/command/messages.php @@ -23,7 +23,7 @@ return [ '2fa_disabled' => '2-Factor authentication has been disabled for :email.', ], 'schedule' => [ - 'output_line' => 'Dispatching job for first task in `:schedule` (:hash).', + 'output_line' => 'Dispatching job for first task in `:schedule` (:id).', ], 'maintenance' => [ 'deleting_service_backup' => 'Deleting service backup file :file.', diff --git a/readme.md b/readme.md index 192c2c3dd..b737a25aa 100644 --- a/readme.md +++ b/readme.md @@ -2,6 +2,10 @@ # Pelican Panel +![Total Downloads](https://img.shields.io/github/downloads/pelican-dev/panel/total?style=flat&label=Total%20Downloads&labelColor=rgba(0%2C%2070%2C%20114%2C%201)&color=rgba(255%2C%20255%2C%20255%2C%201)) +![Latest Release](https://img.shields.io/github/v/release/pelican-dev/panel?style=flat&label=Latest%20Release&labelColor=rgba(0%2C%2070%2C%20114%2C%201)&color=rgba(255%2C%20255%2C%20255%2C%201)) + + Pelican Panel is an open-source, web-based application designed for easy management of game servers. It offers a user-friendly interface for deploying, configuring, and managing servers, with features like real-time resource monitoring, Docker container isolation, and extensive customization options. Ideal for both individual gamers and hosting companies, it simplifies server administration without requiring deep technical knowledge. diff --git a/tests/Integration/Api/Client/Server/Database/DatabaseAuthorizationTest.php b/tests/Integration/Api/Client/Server/Database/DatabaseAuthorizationTest.php index 0b3b88cd9..b95778104 100644 --- a/tests/Integration/Api/Client/Server/Database/DatabaseAuthorizationTest.php +++ b/tests/Integration/Api/Client/Server/Database/DatabaseAuthorizationTest.php @@ -5,7 +5,6 @@ namespace App\Tests\Integration\Api\Client\Server\Database; use App\Models\Subuser; use App\Models\Database; use App\Models\DatabaseHost; -use App\Contracts\Extensions\HashidsInterface; use App\Services\Databases\DatabasePasswordService; use App\Services\Databases\DatabaseManagementService; use App\Tests\Integration\Api\Client\ClientApiIntegrationTestCase; @@ -39,23 +38,22 @@ class DatabaseAuthorizationTest extends ClientApiIntegrationTestCase ->expects($method === 'POST' ? 'handle' : 'delete') ->andReturn($method === 'POST' ? 'foo' : null); - $hashids = $this->app->make(HashidsInterface::class); // This is the only valid call for this test, accessing the database for the same // server that the API user is the owner of. - $this->actingAs($user)->json($method, $this->link($server1, '/databases/' . $hashids->encode($database1->id) . $endpoint)) + $this->actingAs($user)->json($method, $this->link($server1, '/databases/' . $database1->id . $endpoint)) ->assertStatus($method === 'DELETE' ? 204 : 200); // This request fails because the database is valid for that server but the user // making the request is not authorized to perform that action. - $this->actingAs($user)->json($method, $this->link($server2, '/databases/' . $hashids->encode($database2->id) . $endpoint))->assertForbidden(); + $this->actingAs($user)->json($method, $this->link($server2, '/databases/' . $database2->id . $endpoint))->assertForbidden(); // Both of these should report a 404 error due to the database being linked to // servers that are not the same as the server in the request, or are assigned // to a server for which the user making the request has no access to. - $this->actingAs($user)->json($method, $this->link($server1, '/databases/' . $hashids->encode($database2->id) . $endpoint))->assertNotFound(); - $this->actingAs($user)->json($method, $this->link($server1, '/databases/' . $hashids->encode($database3->id) . $endpoint))->assertNotFound(); - $this->actingAs($user)->json($method, $this->link($server2, '/databases/' . $hashids->encode($database3->id) . $endpoint))->assertNotFound(); - $this->actingAs($user)->json($method, $this->link($server3, '/databases/' . $hashids->encode($database3->id) . $endpoint))->assertNotFound(); + $this->actingAs($user)->json($method, $this->link($server1, '/databases/' . $database2->id . $endpoint))->assertNotFound(); + $this->actingAs($user)->json($method, $this->link($server1, '/databases/' . $database3->id . $endpoint))->assertNotFound(); + $this->actingAs($user)->json($method, $this->link($server2, '/databases/' . $database3->id . $endpoint))->assertNotFound(); + $this->actingAs($user)->json($method, $this->link($server3, '/databases/' . $database3->id . $endpoint))->assertNotFound(); } public static function methodDataProvider(): array