mirror of
https://github.com/pelican-dev/panel.git
synced 2025-05-20 00:34:44 +02:00
Merge branch 'main' into lance/phpstan-return-types
This commit is contained in:
commit
81c75f7966
@ -11,11 +11,8 @@ class CheckEggUpdatesCommand extends Command
|
|||||||
{
|
{
|
||||||
protected $signature = 'p:egg:check-updates';
|
protected $signature = 'p:egg:check-updates';
|
||||||
|
|
||||||
public function handle(): void
|
public function handle(EggExporterService $exporterService): void
|
||||||
{
|
{
|
||||||
/** @var EggExporterService $exporterService */
|
|
||||||
$exporterService = app(EggExporterService::class);
|
|
||||||
|
|
||||||
$eggs = Egg::all();
|
$eggs = Egg::all();
|
||||||
foreach ($eggs as $egg) {
|
foreach ($eggs as $egg) {
|
||||||
try {
|
try {
|
||||||
|
@ -64,6 +64,7 @@ class DisplayException extends PanelException implements HttpExceptionInterface
|
|||||||
return response()->json(Handler::toArray($this), $this->getStatusCode(), $this->getHeaders());
|
return response()->json(Handler::toArray($this), $this->getStatusCode(), $this->getHeaders());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
app(AlertsMessageBag::class)->danger($this->getMessage())->flash();
|
app(AlertsMessageBag::class)->danger($this->getMessage())->flash();
|
||||||
|
|
||||||
return redirect()->back()->withInput();
|
return redirect()->back()->withInput();
|
||||||
|
@ -273,6 +273,7 @@ class Handler extends ExceptionHandler
|
|||||||
*/
|
*/
|
||||||
public static function toArray(\Throwable $e): array
|
public static function toArray(\Throwable $e): array
|
||||||
{
|
{
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return (new self(app()))->convertExceptionToArray($e);
|
return (new self(app()))->convertExceptionToArray($e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,16 +28,20 @@ class Dashboard extends Page
|
|||||||
|
|
||||||
public string $activeTab = 'nodes';
|
public string $activeTab = 'nodes';
|
||||||
|
|
||||||
|
private SoftwareVersionService $softwareVersionService;
|
||||||
|
|
||||||
|
public function mount(SoftwareVersionService $softwareVersionService): void
|
||||||
|
{
|
||||||
|
$this->softwareVersionService = $softwareVersionService;
|
||||||
|
}
|
||||||
|
|
||||||
public function getViewData(): array
|
public function getViewData(): array
|
||||||
{
|
{
|
||||||
/** @var SoftwareVersionService $softwareVersionService */
|
|
||||||
$softwareVersionService = app(SoftwareVersionService::class);
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'inDevelopment' => config('app.version') === 'canary',
|
'inDevelopment' => config('app.version') === 'canary',
|
||||||
'version' => $softwareVersionService->versionData()['version'],
|
'version' => $this->softwareVersionService->versionData()['version'],
|
||||||
'latestVersion' => $softwareVersionService->getPanel(),
|
'latestVersion' => $this->softwareVersionService->getPanel(),
|
||||||
'isLatest' => $softwareVersionService->isLatestPanel(),
|
'isLatest' => $this->softwareVersionService->isLatestPanel(),
|
||||||
'eggsCount' => Egg::query()->count(),
|
'eggsCount' => Egg::query()->count(),
|
||||||
'nodesList' => ListNodes::getUrl(),
|
'nodesList' => ListNodes::getUrl(),
|
||||||
'nodesCount' => Node::query()->count(),
|
'nodesCount' => Node::query()->count(),
|
||||||
@ -67,7 +71,7 @@ class Dashboard extends Page
|
|||||||
CreateAction::make()
|
CreateAction::make()
|
||||||
->label(trans('dashboard/index.sections.intro-support.button_donate'))
|
->label(trans('dashboard/index.sections.intro-support.button_donate'))
|
||||||
->icon('tabler-cash')
|
->icon('tabler-cash')
|
||||||
->url($softwareVersionService->getDonations(), true)
|
->url($this->softwareVersionService->getDonations(), true)
|
||||||
->color('success'),
|
->color('success'),
|
||||||
],
|
],
|
||||||
'helpActions' => [
|
'helpActions' => [
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Filament\Pages\Installer;
|
namespace App\Filament\Pages\Installer;
|
||||||
|
|
||||||
|
use App\Filament\Pages\Dashboard;
|
||||||
use App\Filament\Pages\Installer\Steps\AdminUserStep;
|
use App\Filament\Pages\Installer\Steps\AdminUserStep;
|
||||||
use App\Filament\Pages\Installer\Steps\CompletedStep;
|
use App\Filament\Pages\Installer\Steps\CompletedStep;
|
||||||
use App\Filament\Pages\Installer\Steps\DatabaseStep;
|
use App\Filament\Pages\Installer\Steps\DatabaseStep;
|
||||||
@ -13,7 +14,6 @@ use App\Services\Users\UserCreationService;
|
|||||||
use App\Traits\CheckMigrationsTrait;
|
use App\Traits\CheckMigrationsTrait;
|
||||||
use App\Traits\EnvironmentWriterTrait;
|
use App\Traits\EnvironmentWriterTrait;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Filament\Facades\Filament;
|
|
||||||
use Filament\Forms\Components\Actions\Action;
|
use Filament\Forms\Components\Actions\Action;
|
||||||
use Filament\Forms\Components\Wizard;
|
use Filament\Forms\Components\Wizard;
|
||||||
use Filament\Forms\Concerns\InteractsWithForms;
|
use Filament\Forms\Concerns\InteractsWithForms;
|
||||||
@ -104,7 +104,7 @@ class PanelInstaller extends SimplePage implements HasForms
|
|||||||
auth()->guard()->login($this->user, true);
|
auth()->guard()->login($this->user, true);
|
||||||
|
|
||||||
// Redirect to admin panel
|
// Redirect to admin panel
|
||||||
return redirect(Filament::getPanel('admin')->getUrl());
|
return redirect(Dashboard::getUrl());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function writeToEnv(string $key): void
|
public function writeToEnv(string $key): void
|
||||||
@ -160,12 +160,12 @@ class PanelInstaller extends SimplePage implements HasForms
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createAdminUser(): void
|
public function createAdminUser(UserCreationService $userCreationService): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$userData = array_get($this->data, 'user');
|
$userData = array_get($this->data, 'user');
|
||||||
$userData['root_admin'] = true;
|
$userData['root_admin'] = true;
|
||||||
$this->user = app(UserCreationService::class)->handle($userData);
|
$this->user = $userCreationService->handle($userData);
|
||||||
} catch (Exception $exception) {
|
} catch (Exception $exception) {
|
||||||
report($exception);
|
report($exception);
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace App\Filament\Pages\Installer\Steps;
|
namespace App\Filament\Pages\Installer\Steps;
|
||||||
|
|
||||||
use App\Filament\Pages\Installer\PanelInstaller;
|
use App\Filament\Pages\Installer\PanelInstaller;
|
||||||
|
use App\Services\Users\UserCreationService;
|
||||||
use Filament\Forms\Components\TextInput;
|
use Filament\Forms\Components\TextInput;
|
||||||
use Filament\Forms\Components\Wizard\Step;
|
use Filament\Forms\Components\Wizard\Step;
|
||||||
|
|
||||||
@ -28,6 +29,6 @@ class AdminUserStep
|
|||||||
->password()
|
->password()
|
||||||
->revealable(),
|
->revealable(),
|
||||||
])
|
])
|
||||||
->afterValidation(fn () => $installer->createAdminUser());
|
->afterValidation(fn (UserCreationService $service) => $installer->createAdminUser($service));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@ use PDOException;
|
|||||||
|
|
||||||
class CreateDatabaseHost extends CreateRecord
|
class CreateDatabaseHost extends CreateRecord
|
||||||
{
|
{
|
||||||
|
private HostCreationService $service;
|
||||||
|
|
||||||
protected static string $resource = DatabaseHostResource::class;
|
protected static string $resource = DatabaseHostResource::class;
|
||||||
|
|
||||||
protected ?string $heading = 'Database Hosts';
|
protected ?string $heading = 'Database Hosts';
|
||||||
@ -26,6 +28,11 @@ class CreateDatabaseHost extends CreateRecord
|
|||||||
|
|
||||||
protected ?string $subheading = '(database servers that can have individual databases)';
|
protected ?string $subheading = '(database servers that can have individual databases)';
|
||||||
|
|
||||||
|
public function boot(HostCreationService $service)
|
||||||
|
{
|
||||||
|
$this->service = $service;
|
||||||
|
}
|
||||||
|
|
||||||
public function form(Form $form): Form
|
public function form(Form $form): Form
|
||||||
{
|
{
|
||||||
return $form
|
return $form
|
||||||
@ -96,7 +103,7 @@ class CreateDatabaseHost extends CreateRecord
|
|||||||
|
|
||||||
protected function handleRecordCreation(array $data): Model
|
protected function handleRecordCreation(array $data): Model
|
||||||
{
|
{
|
||||||
return resolve(HostCreationService::class)->handle($data);
|
return $this->service->handle($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exception(Exception $e, Closure $stopPropagation): void
|
public function exception(Exception $e, Closure $stopPropagation): void
|
||||||
|
@ -23,6 +23,13 @@ class EditDatabaseHost extends EditRecord
|
|||||||
{
|
{
|
||||||
protected static string $resource = DatabaseHostResource::class;
|
protected static string $resource = DatabaseHostResource::class;
|
||||||
|
|
||||||
|
private HostUpdateService $hostUpdateService;
|
||||||
|
|
||||||
|
public function boot(HostUpdateService $hostUpdateService)
|
||||||
|
{
|
||||||
|
$this->hostUpdateService = $hostUpdateService;
|
||||||
|
}
|
||||||
|
|
||||||
public function form(Form $form): Form
|
public function form(Form $form): Form
|
||||||
{
|
{
|
||||||
return $form
|
return $form
|
||||||
@ -105,7 +112,7 @@ class EditDatabaseHost extends EditRecord
|
|||||||
return $record;
|
return $record;
|
||||||
}
|
}
|
||||||
|
|
||||||
return resolve(HostUpdateService::class)->handle($record, $data);
|
return $this->hostUpdateService->handle($record, $data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function exception(Exception $e, Closure $stopPropagation): void
|
public function exception(Exception $e, Closure $stopPropagation): void
|
||||||
|
@ -280,10 +280,7 @@ class EditEgg extends EditRecord
|
|||||||
->contained(false),
|
->contained(false),
|
||||||
|
|
||||||
])
|
])
|
||||||
->action(function (array $data, Egg $egg): void {
|
->action(function (array $data, Egg $egg, EggImporterService $eggImportService): void {
|
||||||
/** @var EggImporterService $eggImportService */
|
|
||||||
$eggImportService = resolve(EggImporterService::class);
|
|
||||||
|
|
||||||
if (!empty($data['egg'])) {
|
if (!empty($data['egg'])) {
|
||||||
try {
|
try {
|
||||||
$eggImportService->fromFile($data['egg'], $egg);
|
$eggImportService->fromFile($data['egg'], $egg);
|
||||||
|
@ -66,9 +66,10 @@ class ListEggs extends ListRecords
|
|||||||
->modalDescription('If you made any changes to the egg they will be overwritten!')
|
->modalDescription('If you made any changes to the egg they will be overwritten!')
|
||||||
->modalIconColor('danger')
|
->modalIconColor('danger')
|
||||||
->modalSubmitAction(fn (Actions\StaticAction $action) => $action->color('danger'))
|
->modalSubmitAction(fn (Actions\StaticAction $action) => $action->color('danger'))
|
||||||
->action(function (Egg $egg) {
|
->action(function (Egg $egg, EggImporterService $eggImporterService) {
|
||||||
try {
|
try {
|
||||||
app(EggImporterService::class)->fromUrl($egg->update_url, $egg);
|
$eggImporterService->fromUrl($egg->update_url, $egg);
|
||||||
|
|
||||||
cache()->forget("eggs.{$egg->uuid}.update");
|
cache()->forget("eggs.{$egg->uuid}.update");
|
||||||
} catch (Exception $exception) {
|
} catch (Exception $exception) {
|
||||||
Notification::make()
|
Notification::make()
|
||||||
@ -129,10 +130,7 @@ class ListEggs extends ListRecords
|
|||||||
->contained(false),
|
->contained(false),
|
||||||
|
|
||||||
])
|
])
|
||||||
->action(function (array $data): void {
|
->action(function (array $data, EggImporterService $eggImportService): void {
|
||||||
/** @var EggImporterService $eggImportService */
|
|
||||||
$eggImportService = resolve(EggImporterService::class);
|
|
||||||
|
|
||||||
if (!empty($data['egg'])) {
|
if (!empty($data['egg'])) {
|
||||||
/** @var TemporaryUploadedFile[] $eggFile */
|
/** @var TemporaryUploadedFile[] $eggFile */
|
||||||
$eggFile = $data['egg'];
|
$eggFile = $data['egg'];
|
||||||
|
@ -398,7 +398,7 @@ class CreateNode extends CreateRecord
|
|||||||
protected function getRedirectUrlParameters(): array
|
protected function getRedirectUrlParameters(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'tab' => '-configuration-tab',
|
'tab' => '-configuration-file-tab',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ class AllocationsRelationManager extends RelationManager
|
|||||||
->splitKeys(['Tab', ' ', ','])
|
->splitKeys(['Tab', ' ', ','])
|
||||||
->required(),
|
->required(),
|
||||||
])
|
])
|
||||||
->action(fn (array $data) => resolve(AssignmentService::class)->handle($this->getOwnerRecord(), $data)),
|
->action(fn (array $data, AssignmentService $service) => $service->handle($this->getOwnerRecord(), $data)),
|
||||||
])
|
])
|
||||||
->bulkActions([
|
->bulkActions([
|
||||||
BulkActionGroup::make([
|
BulkActionGroup::make([
|
||||||
|
@ -49,6 +49,13 @@ class CreateServer extends CreateRecord
|
|||||||
|
|
||||||
public ?Node $node = null;
|
public ?Node $node = null;
|
||||||
|
|
||||||
|
private ServerCreationService $serverCreationService;
|
||||||
|
|
||||||
|
public function boot(ServerCreationService $serverCreationService)
|
||||||
|
{
|
||||||
|
$this->serverCreationService = $serverCreationService;
|
||||||
|
}
|
||||||
|
|
||||||
public function form(Form $form): Form
|
public function form(Form $form): Form
|
||||||
{
|
{
|
||||||
return $form
|
return $form
|
||||||
@ -118,8 +125,9 @@ class CreateServer extends CreateRecord
|
|||||||
->hintIconTooltip('Providing a user password is optional. New user email will prompt users to create a password the first time they login.')
|
->hintIconTooltip('Providing a user password is optional. New user email will prompt users to create a password the first time they login.')
|
||||||
->password(),
|
->password(),
|
||||||
])
|
])
|
||||||
->createOptionUsing(function ($data) {
|
->createOptionUsing(function ($data, UserCreationService $service) {
|
||||||
resolve(UserCreationService::class)->handle($data);
|
$service->handle($data);
|
||||||
|
|
||||||
$this->refreshForm();
|
$this->refreshForm();
|
||||||
})
|
})
|
||||||
->required(),
|
->required(),
|
||||||
@ -262,9 +270,9 @@ class CreateServer extends CreateRecord
|
|||||||
->splitKeys(['Tab', ' ', ','])
|
->splitKeys(['Tab', ' ', ','])
|
||||||
->required(),
|
->required(),
|
||||||
])
|
])
|
||||||
->createOptionUsing(function (array $data, Get $get): int {
|
->createOptionUsing(function (array $data, Get $get, AssignmentService $assignmentService): int {
|
||||||
return collect(
|
return collect(
|
||||||
resolve(AssignmentService::class)->handle(Node::find($get('node_id')), $data)
|
$assignmentService->handle(Node::find($get('node_id')), $data)
|
||||||
)->first();
|
)->first();
|
||||||
})
|
})
|
||||||
->required(),
|
->required(),
|
||||||
@ -825,10 +833,7 @@ class CreateServer extends CreateRecord
|
|||||||
{
|
{
|
||||||
$data['allocation_additional'] = collect($data['allocation_additional'])->filter()->all();
|
$data['allocation_additional'] = collect($data['allocation_additional'])->filter()->all();
|
||||||
|
|
||||||
/** @var ServerCreationService $service */
|
return $this->serverCreationService->handle($data);
|
||||||
$service = resolve(ServerCreationService::class);
|
|
||||||
|
|
||||||
return $service->handle($data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function shouldHideComponent(Get $get, Component $component): bool
|
private function shouldHideComponent(Get $get, Component $component): bool
|
||||||
|
@ -749,8 +749,8 @@ class EditServer extends EditRecord
|
|||||||
->color('danger')
|
->color('danger')
|
||||||
->label('Delete')
|
->label('Delete')
|
||||||
->requiresConfirmation()
|
->requiresConfirmation()
|
||||||
->action(function (Server $server) {
|
->action(function (Server $server, ServerDeletionService $service) {
|
||||||
resolve(ServerDeletionService::class)->handle($server);
|
$service->handle($server);
|
||||||
|
|
||||||
return redirect(ListServers::getUrl());
|
return redirect(ListServers::getUrl());
|
||||||
})
|
})
|
||||||
|
@ -144,7 +144,7 @@ class AllocationsRelationManager extends RelationManager
|
|||||||
->splitKeys(['Tab', ' ', ','])
|
->splitKeys(['Tab', ' ', ','])
|
||||||
->required(),
|
->required(),
|
||||||
])
|
])
|
||||||
->action(fn (array $data) => resolve(AssignmentService::class)->handle($this->getOwnerRecord()->node, $data, $this->getOwnerRecord())),
|
->action(fn (array $data, AssignmentService $service) => $service->handle($this->getOwnerRecord()->node, $data, $this->getOwnerRecord())),
|
||||||
AssociateAction::make()
|
AssociateAction::make()
|
||||||
->multiple()
|
->multiple()
|
||||||
->associateAnother(false)
|
->associateAnother(false)
|
||||||
|
@ -40,6 +40,13 @@ use Illuminate\Validation\Rules\Password;
|
|||||||
*/
|
*/
|
||||||
class EditProfile extends \Filament\Pages\Auth\EditProfile
|
class EditProfile extends \Filament\Pages\Auth\EditProfile
|
||||||
{
|
{
|
||||||
|
private ToggleTwoFactorService $toggleTwoFactorService;
|
||||||
|
|
||||||
|
public function boot(ToggleTwoFactorService $toggleTwoFactorService): void
|
||||||
|
{
|
||||||
|
$this->toggleTwoFactorService = $toggleTwoFactorService;
|
||||||
|
}
|
||||||
|
|
||||||
protected function getForms(): array
|
protected function getForms(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
@ -108,7 +115,7 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile
|
|||||||
|
|
||||||
Tab::make('2FA')
|
Tab::make('2FA')
|
||||||
->icon('tabler-shield-lock')
|
->icon('tabler-shield-lock')
|
||||||
->schema(function () {
|
->schema(function (TwoFactorSetupService $setupService) {
|
||||||
if ($this->getUser()->use_totp) {
|
if ($this->getUser()->use_totp) {
|
||||||
return [
|
return [
|
||||||
Placeholder::make('2fa-already-enabled')
|
Placeholder::make('2fa-already-enabled')
|
||||||
@ -126,8 +133,6 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile
|
|||||||
->helperText('Enter your current 2FA code to disable Two Factor Authentication'),
|
->helperText('Enter your current 2FA code to disable Two Factor Authentication'),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
/** @var TwoFactorSetupService */
|
|
||||||
$setupService = app(TwoFactorSetupService::class);
|
|
||||||
|
|
||||||
['image_url_data' => $url, 'secret' => $secret] = cache()->remember(
|
['image_url_data' => $url, 'secret' => $secret] = cache()->remember(
|
||||||
"users.{$this->getUser()->id}.2fa.state",
|
"users.{$this->getUser()->id}.2fa.state",
|
||||||
@ -283,20 +288,14 @@ class EditProfile extends \Filament\Pages\Auth\EditProfile
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($token = $data['2facode'] ?? null) {
|
if ($token = $data['2facode'] ?? null) {
|
||||||
/** @var ToggleTwoFactorService $service */
|
$tokens = $this->toggleTwoFactorService->handle($record, $token, true);
|
||||||
$service = resolve(ToggleTwoFactorService::class);
|
|
||||||
|
|
||||||
$tokens = $service->handle($record, $token, true);
|
|
||||||
cache()->set("users.$record->id.2fa.tokens", implode("\n", $tokens), now()->addSeconds(15));
|
cache()->set("users.$record->id.2fa.tokens", implode("\n", $tokens), now()->addSeconds(15));
|
||||||
|
|
||||||
$this->redirectRoute('filament.admin.auth.profile', ['tab' => '-2fa-tab']);
|
$this->redirectRoute('filament.admin.auth.profile', ['tab' => '-2fa-tab']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($token = $data['2fa-disable-code'] ?? null) {
|
if ($token = $data['2fa-disable-code'] ?? null) {
|
||||||
/** @var ToggleTwoFactorService $service */
|
$this->toggleTwoFactorService->handle($record, $token, false);
|
||||||
$service = resolve(ToggleTwoFactorService::class);
|
|
||||||
|
|
||||||
$service->handle($record, $token, false);
|
|
||||||
|
|
||||||
cache()->forget("users.$record->id.2fa.state");
|
cache()->forget("users.$record->id.2fa.state");
|
||||||
}
|
}
|
||||||
|
@ -110,13 +110,11 @@ class ListUsers extends ListRecords
|
|||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
->successRedirectUrl(route('filament.admin.resources.users.index'))
|
->successRedirectUrl(route('filament.admin.resources.users.index'))
|
||||||
->action(function (array $data) {
|
->action(function (array $data, UserCreationService $creationService) {
|
||||||
$roles = $data['roles'];
|
$roles = $data['roles'];
|
||||||
$roles = collect($roles)->map(fn ($role) => Role::findById($role));
|
$roles = collect($roles)->map(fn ($role) => Role::findById($role));
|
||||||
unset($data['roles']);
|
unset($data['roles']);
|
||||||
|
|
||||||
/** @var UserCreationService $creationService */
|
|
||||||
$creationService = resolve(UserCreationService::class);
|
|
||||||
$user = $creationService->handle($data);
|
$user = $creationService->handle($data);
|
||||||
|
|
||||||
$user->syncRoles($roles);
|
$user->syncRoles($roles);
|
||||||
|
@ -32,18 +32,18 @@ class ServersRelationManager extends RelationManager
|
|||||||
)
|
)
|
||||||
->label('Suspend All Servers')
|
->label('Suspend All Servers')
|
||||||
->color('warning')
|
->color('warning')
|
||||||
->action(function () use ($user) {
|
->action(function (SuspensionService $suspensionService) use ($user) {
|
||||||
foreach ($user->servers()->whereNot('status', ServerState::Suspended)->get() as $server) {
|
foreach ($user->servers()->whereNot('status', ServerState::Suspended)->get() as $server) {
|
||||||
resolve(SuspensionService::class)->toggle($server);
|
$suspensionService->toggle($server);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
Actions\Action::make('toggleUnsuspend')
|
Actions\Action::make('toggleUnsuspend')
|
||||||
->hidden(fn () => $user->servers()->where('status', ServerState::Suspended)->count() === 0)
|
->hidden(fn () => $user->servers()->where('status', ServerState::Suspended)->count() === 0)
|
||||||
->label('Unsuspend All Servers')
|
->label('Unsuspend All Servers')
|
||||||
->color('primary')
|
->color('primary')
|
||||||
->action(function () use ($user) {
|
->action(function (SuspensionService $suspensionService) use ($user) {
|
||||||
foreach ($user->servers()->where('status', ServerState::Suspended)->get() as $server) {
|
foreach ($user->servers()->where('status', ServerState::Suspended)->get() as $server) {
|
||||||
resolve(SuspensionService::class)->toggle($server, SuspensionService::ACTION_UNSUSPEND);
|
$suspensionService->toggle($server, SuspensionService::ACTION_UNSUSPEND);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
@ -3,23 +3,26 @@
|
|||||||
namespace App\Http\Middleware;
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
use GuzzleHttp\Client;
|
use GuzzleHttp\Client;
|
||||||
|
use Illuminate\Foundation\Application;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use App\Events\Auth\FailedCaptcha;
|
use App\Events\Auth\FailedCaptcha;
|
||||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||||
|
|
||||||
class VerifyReCaptcha
|
readonly class VerifyReCaptcha
|
||||||
{
|
{
|
||||||
/**
|
public function __construct(private Application $app)
|
||||||
* Handle an incoming request.
|
{
|
||||||
*/
|
|
||||||
|
}
|
||||||
|
|
||||||
public function handle(Request $request, \Closure $next): mixed
|
public function handle(Request $request, \Closure $next): mixed
|
||||||
{
|
{
|
||||||
if (!config('recaptcha.enabled')) {
|
if (!config('recaptcha.enabled')) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app()->isLocal()) {
|
if ($this->app->isLocal()) {
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,6 +295,7 @@ class Node extends Model
|
|||||||
{
|
{
|
||||||
return once(function () {
|
return once(function () {
|
||||||
try {
|
try {
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return resolve(DaemonConfigurationRepository::class)
|
return resolve(DaemonConfigurationRepository::class)
|
||||||
->setNode($this)
|
->setNode($this)
|
||||||
->getSystemInformation(connectTimeout: 3);
|
->getSystemInformation(connectTimeout: 3);
|
||||||
|
38
app/PHPStan/ForbiddenGlobalFunctionsRule.php
Normal file
38
app/PHPStan/ForbiddenGlobalFunctionsRule.php
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\PHPStan;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Expr\FuncCall;
|
||||||
|
use PHPStan\Analyser\Scope;
|
||||||
|
use PHPStan\Rules\Rule;
|
||||||
|
|
||||||
|
class ForbiddenGlobalFunctionsRule implements Rule
|
||||||
|
{
|
||||||
|
private array $forbiddenFunctions;
|
||||||
|
|
||||||
|
public function __construct(array $forbiddenFunctions = ['app', 'resolve'])
|
||||||
|
{
|
||||||
|
$this->forbiddenFunctions = $forbiddenFunctions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getNodeType(): string
|
||||||
|
{
|
||||||
|
return FuncCall::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function processNode(Node $node, Scope $scope): array
|
||||||
|
{
|
||||||
|
/** @var FuncCall $node */
|
||||||
|
if ($node->name instanceof Node\Name) {
|
||||||
|
$functionName = (string) $node->name;
|
||||||
|
if (in_array($functionName, $this->forbiddenFunctions, true)) {
|
||||||
|
return [
|
||||||
|
sprintf('Usage of global function "%s" is forbidden.', $functionName),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ use Dedoc\Scramble\Support\Generator\SecurityScheme;
|
|||||||
use Filament\Support\Colors\Color;
|
use Filament\Support\Colors\Color;
|
||||||
use Filament\Support\Facades\FilamentColor;
|
use Filament\Support\Facades\FilamentColor;
|
||||||
use Illuminate\Database\Eloquent\Relations\Relation;
|
use Illuminate\Database\Eloquent\Relations\Relation;
|
||||||
|
use Illuminate\Foundation\Application;
|
||||||
use Illuminate\Pagination\Paginator;
|
use Illuminate\Pagination\Paginator;
|
||||||
use Illuminate\Support\Facades\Broadcast;
|
use Illuminate\Support\Facades\Broadcast;
|
||||||
use Illuminate\Support\Facades\Event;
|
use Illuminate\Support\Facades\Event;
|
||||||
@ -29,7 +30,7 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
/**
|
/**
|
||||||
* Bootstrap any application services.
|
* Bootstrap any application services.
|
||||||
*/
|
*/
|
||||||
public function boot(): void
|
public function boot(Application $app): void
|
||||||
{
|
{
|
||||||
// TODO: remove when old admin area gets yeeted
|
// TODO: remove when old admin area gets yeeted
|
||||||
View::share('appVersion', config('app.version'));
|
View::share('appVersion', config('app.version'));
|
||||||
@ -64,7 +65,7 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
->asJson()
|
->asJson()
|
||||||
->withToken($node->daemon_token)
|
->withToken($node->daemon_token)
|
||||||
->withHeaders($headers)
|
->withHeaders($headers)
|
||||||
->withOptions(['verify' => (bool) app()->environment('production')])
|
->withOptions(['verify' => (bool) $app->environment('production')])
|
||||||
->timeout(config('panel.guzzle.timeout'))
|
->timeout(config('panel.guzzle.timeout'))
|
||||||
->connectTimeout(config('panel.guzzle.connect_timeout'))
|
->connectTimeout(config('panel.guzzle.connect_timeout'))
|
||||||
->baseUrl($node->getConnectionAddress())
|
->baseUrl($node->getConnectionAddress())
|
||||||
|
@ -12,7 +12,7 @@ trait CheckMigrationsTrait
|
|||||||
protected function hasCompletedMigrations(): bool
|
protected function hasCompletedMigrations(): bool
|
||||||
{
|
{
|
||||||
/** @var Migrator $migrator */
|
/** @var Migrator $migrator */
|
||||||
$migrator = app()->make('migrator');
|
$migrator = app()->make('migrator'); // @phpstan-ignore-line
|
||||||
|
|
||||||
$files = $migrator->getMigrationFiles(database_path('migrations'));
|
$files = $migrator->getMigrationFiles(database_path('migrations'));
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ trait AvailableLanguages
|
|||||||
*/
|
*/
|
||||||
private function getFilesystemInstance(): Filesystem
|
private function getFilesystemInstance(): Filesystem
|
||||||
{
|
{
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return $this->filesystem = $this->filesystem ?: app()->make(Filesystem::class);
|
return $this->filesystem = $this->filesystem ?: app()->make(Filesystem::class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ abstract class BaseTransformer extends TransformerAbstract
|
|||||||
*/
|
*/
|
||||||
public static function fromRequest(Request $request): self
|
public static function fromRequest(Request $request): self
|
||||||
{
|
{
|
||||||
|
// @phpstan-ignore-next-line
|
||||||
return app(static::class)->setRequest($request);
|
return app(static::class)->setRequest($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
includes:
|
includes:
|
||||||
- vendor/larastan/larastan/extension.neon
|
- vendor/larastan/larastan/extension.neon
|
||||||
|
|
||||||
|
rules:
|
||||||
|
- App\PHPStan\ForbiddenGlobalFunctionsRule
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user