From e15a80163b772f25fefd904ea33259ecff2f03ca Mon Sep 17 00:00:00 2001 From: "Harry (hjbdev)" Date: Mon, 7 Apr 2025 12:16:11 +0100 Subject: [PATCH] ran pint --- .../FirewallRules/InstallFirewallRule.php | 1 + .../FirewallRules/UninstallFirewallRule.php | 1 + app/Actions/GenerateRandomSlug.php | 4 +-- app/Actions/GetProviderService.php | 4 +-- app/Console/Commands/CreateServiceCommand.php | 8 +++--- app/Console/Commands/GenerateJSEnums.php | 26 +++++++++---------- app/Console/Commands/Setup/GenerateSshKey.php | 9 ++++--- app/Console/Commands/Setup/Setup.php | 1 + app/Data/Deployments/Plan.php | 4 +-- app/Data/Deployments/PlannedStep.php | 6 +++-- app/Data/ServerProviders/CreatedServer.php | 2 +- app/Data/ServerProviders/Image.php | 2 +- app/Data/ServerProviders/Location.php | 2 +- app/Data/ServerProviders/ServerType.php | 10 +++---- app/Drivers/DatabaseDriver.php | 6 ++++- app/Drivers/Driver.php | 4 ++- app/Drivers/Postgres/Postgres17Driver.php | 21 ++++++++------- app/Enums/Concerns/Arrayable.php | 2 +- app/Enums/DeploymentStatus.php | 4 +-- app/Enums/FirewallRuleStatus.php | 2 +- app/Enums/FirewallRuleType.php | 2 +- app/Enums/NetworkType.php | 4 +-- app/Enums/RepositoryType.php | 2 +- app/Enums/ServerStatus.php | 2 +- app/Enums/ServiceCategory.php | 8 +++--- app/Enums/ServiceStatus.php | 4 +-- app/Enums/ServiceType.php | 3 ++- .../Controllers/ApplicationController.php | 1 + .../Controllers/EnvironmentController.php | 1 + .../Controllers/OrganisationController.php | 2 -- app/Http/Controllers/ServerController.php | 10 +++---- app/Http/Controllers/ServiceController.php | 1 + .../Connectors/HetznerConnector.php | 4 +-- .../Hetzner/Images/GetImagesRequest.php | 1 - .../ServerTypes/GetServerTypesRequest.php | 2 +- app/Http/Middleware/HandleAppearance.php | 2 +- app/Jobs/Servers/ProvisionServer.php | 5 ++-- app/Jobs/Servers/WaitForServerToConnect.php | 5 ++-- app/Jobs/Services/DeployService.php | 5 ++-- app/Jobs/Services/RunStep.php | 10 +++---- app/Models/FirewallRule.php | 10 +++---- app/Models/Network.php | 2 +- app/Models/Organisation.php | 3 ++- app/Models/Server.php | 6 ++--- app/Models/Service.php | 6 ++--- .../ServerProviders/ServerProviderService.php | 2 +- config/keystone.php | 4 +-- config/services.php | 2 +- database/factories/OrganisationFactory.php | 1 + database/seeders/DatabaseSeeder.php | 4 +-- routes/web.php | 15 ++++++----- tests/Feature/Auth/AuthenticationTest.php | 2 +- tests/Feature/Auth/EmailVerificationTest.php | 2 +- .../Feature/Auth/PasswordConfirmationTest.php | 2 +- tests/Feature/Auth/PasswordResetTest.php | 2 +- tests/Feature/Auth/RegistrationTest.php | 2 +- tests/Feature/DashboardTest.php | 2 +- tests/Feature/ExampleTest.php | 2 +- tests/Feature/ServerControllerTest.php | 12 ++++----- tests/Feature/Settings/PasswordUpdateTest.php | 2 +- tests/Feature/Settings/ProfileUpdateTest.php | 2 +- tests/Unit/ExampleTest.php | 2 +- 62 files changed, 149 insertions(+), 131 deletions(-) diff --git a/app/Actions/FirewallRules/InstallFirewallRule.php b/app/Actions/FirewallRules/InstallFirewallRule.php index a4b3f25..2202af2 100644 --- a/app/Actions/FirewallRules/InstallFirewallRule.php +++ b/app/Actions/FirewallRules/InstallFirewallRule.php @@ -20,6 +20,7 @@ class InstallFirewallRule $firewallRule->update([ 'status' => FirewallRuleStatus::FAILED, ]); + return; } diff --git a/app/Actions/FirewallRules/UninstallFirewallRule.php b/app/Actions/FirewallRules/UninstallFirewallRule.php index f0d1880..6c445fc 100644 --- a/app/Actions/FirewallRules/UninstallFirewallRule.php +++ b/app/Actions/FirewallRules/UninstallFirewallRule.php @@ -20,6 +20,7 @@ class UninstallFirewallRule $firewallRule->update([ 'status' => FirewallRuleStatus::FAILED, ]); + return; } diff --git a/app/Actions/GenerateRandomSlug.php b/app/Actions/GenerateRandomSlug.php index 5e8f687..052e61f 100644 --- a/app/Actions/GenerateRandomSlug.php +++ b/app/Actions/GenerateRandomSlug.php @@ -12,11 +12,11 @@ class GenerateRandomSlug $slug = ''; for ($i = 0; $i < $adjectiveCount; $i++) { - $slug .= $adjectives[array_rand($adjectives)] . '-'; + $slug .= $adjectives[array_rand($adjectives)].'-'; } $slug .= $nouns[array_rand($nouns)]; return $slug; } -} \ No newline at end of file +} diff --git a/app/Actions/GetProviderService.php b/app/Actions/GetProviderService.php index 2999f32..d67ae76 100644 --- a/app/Actions/GetProviderService.php +++ b/app/Actions/GetProviderService.php @@ -7,10 +7,10 @@ use App\Services\ServerProviders\ServerProviderService; class GetProviderService { - public function execute(string $provider): ServerProviderService|null + public function execute(string $provider): ?ServerProviderService { return match ($provider) { - 'hetzner' => new HetznerService(), + 'hetzner' => new HetznerService, default => null, }; } diff --git a/app/Console/Commands/CreateServiceCommand.php b/app/Console/Commands/CreateServiceCommand.php index 1e45822..0d2708f 100644 --- a/app/Console/Commands/CreateServiceCommand.php +++ b/app/Console/Commands/CreateServiceCommand.php @@ -11,6 +11,7 @@ use Illuminate\Console\Command; class CreateServiceCommand extends Command { protected $signature = 'service:create'; + protected $description = 'Create a service'; public function handle() @@ -18,17 +19,18 @@ class CreateServiceCommand extends Command $serverId = $this->components->ask('Enter the server ID'); $server = Server::find($serverId); - if (!$server) { + if (! $server) { $this->components->error('Server not found'); + return; } $serviceType = $this->components->choice('select the service you want to install', [ - 'postgres-17' + 'postgres-17', ]); $serviceName = $this->components->ask('Enter the service name'); - list ($type, $version) = explode('-', $serviceType); + [$type, $version] = explode('-', $serviceType); $service = app(CreateService::class)->execute( server: $server, diff --git a/app/Console/Commands/GenerateJSEnums.php b/app/Console/Commands/GenerateJSEnums.php index b6caa11..dfe3632 100644 --- a/app/Console/Commands/GenerateJSEnums.php +++ b/app/Console/Commands/GenerateJSEnums.php @@ -40,10 +40,10 @@ class GenerateJSEnums extends Command } foreach ((new Finder)->in($paths)->files() as $enum) { - $enum = 'App\\' . str_replace( + $enum = 'App\\'.str_replace( ['/', '.php'], ['\\', ''], - Str::after($enum->getRealPath(), realpath(app_path()) . DIRECTORY_SEPARATOR) + Str::after($enum->getRealPath(), realpath(app_path()).DIRECTORY_SEPARATOR) ); if (! class_exists($enum)) { @@ -51,36 +51,36 @@ class GenerateJSEnums extends Command } $js = "// This is a generated file. \n"; - $js .= '// Published at ' . now()->format('Y-m-d H:i:s') . "\n"; + $js .= '// Published at '.now()->format('Y-m-d H:i:s')."\n"; $js .= "\n"; $js .= 'export default '; - $js .= json_encode($enum::toArray(), JSON_PRETTY_PRINT) . "\n"; + $js .= json_encode($enum::toArray(), JSON_PRETTY_PRINT)."\n"; $js .= "\n"; if (method_exists($enum, 'getLabels')) { $labels = $enum::getLabels(); $js .= 'export const LabelMap = '; - $js .= json_encode($labels, JSON_PRETTY_PRINT) . "\n"; + $js .= json_encode($labels, JSON_PRETTY_PRINT)."\n"; $js .= "\n"; - $labelSelect = array_map(fn($key) => ['title' => $labels[$key], 'id' => $key], array_keys($labels)); + $labelSelect = array_map(fn ($key) => ['title' => $labels[$key], 'id' => $key], array_keys($labels)); $js .= 'export const LabelSelectMap = '; - $js .= json_encode($labelSelect, JSON_PRETTY_PRINT) . "\n"; + $js .= json_encode($labelSelect, JSON_PRETTY_PRINT)."\n"; $js .= "\n"; } if (method_exists($enum, 'getDescription')) { $values = $enum::toArray(); - $descriptions = array_map(fn($key) => $enum::getDescription($key), $values); + $descriptions = array_map(fn ($key) => $enum::getDescription($key), $values); $js .= 'export const DescriptionMap = '; - $js .= json_encode($descriptions, JSON_PRETTY_PRINT) . "\n"; + $js .= json_encode($descriptions, JSON_PRETTY_PRINT)."\n"; $js .= "\n"; } if (method_exists($enum, 'colours')) { $colours = $enum::colours(); $js .= 'export const ColourMap = '; - $js .= json_encode($colours, JSON_PRETTY_PRINT) . "\n"; + $js .= json_encode($colours, JSON_PRETTY_PRINT)."\n"; $js .= "\n"; } @@ -88,10 +88,10 @@ class GenerateJSEnums extends Command // Skip format, JS date formats are different to PHP ones. if ($name !== 'Format') { - file_put_contents(base_path('resources/js/Enums/' . $name . '.js'), $js); - $this->info('Stored ' . $enum); + file_put_contents(base_path('resources/js/Enums/'.$name.'.js'), $js); + $this->info('Stored '.$enum); } else { - $this->info('Skipped ' . $name . 's'); + $this->info('Skipped '.$name.'s'); } } } diff --git a/app/Console/Commands/Setup/GenerateSshKey.php b/app/Console/Commands/Setup/GenerateSshKey.php index 17013ea..a3d7abc 100644 --- a/app/Console/Commands/Setup/GenerateSshKey.php +++ b/app/Console/Commands/Setup/GenerateSshKey.php @@ -8,27 +8,30 @@ use Illuminate\Support\Facades\Process; class GenerateSshKey extends Command { protected $signature = 'setup:generate-ssh-key'; + protected $description = 'Generates an SSH key pair for the application.'; public function handle() { if (file_exists(storage_path('app/private/ssh/id_ed25519'))) { $this->components->info('SSH key pair already exists.'); + return; } - + $this->components->info('Generating SSH key pair...'); - if (!file_exists(storage_path('app/private/ssh'))) { + if (! file_exists(storage_path('app/private/ssh'))) { $this->components->info('ssh directory does not exist. Creating it now...'); mkdir(storage_path('app/private/ssh'), 0755, true); } $result = Process::run(['ssh-keygen', '-t', 'ed25519', '-f', storage_path('app/private/ssh/id_ed25519'), '-N', '']); - if (!$result->successful()) { + if (! $result->successful()) { $this->components->error('Failed to generate SSH key pair.'); $this->line($result->output()); $this->line($result->errorOutput()); + return; } diff --git a/app/Console/Commands/Setup/Setup.php b/app/Console/Commands/Setup/Setup.php index 736501b..2ad4f0f 100644 --- a/app/Console/Commands/Setup/Setup.php +++ b/app/Console/Commands/Setup/Setup.php @@ -7,6 +7,7 @@ use Illuminate\Console\Command; class Setup extends Command { protected $signature = 'setup'; + protected $description = 'Initialize the application.'; public function handle() diff --git a/app/Data/Deployments/Plan.php b/app/Data/Deployments/Plan.php index 0153463..9eb2670 100644 --- a/app/Data/Deployments/Plan.php +++ b/app/Data/Deployments/Plan.php @@ -5,11 +5,11 @@ namespace App\Data\Deployments; class Plan { /** - * @param PlannedStep[] $steps + * @param PlannedStep[] $steps */ public function __construct( public array $steps = [], ) { // } -} \ No newline at end of file +} diff --git a/app/Data/Deployments/PlannedStep.php b/app/Data/Deployments/PlannedStep.php index 343c70f..041cffa 100644 --- a/app/Data/Deployments/PlannedStep.php +++ b/app/Data/Deployments/PlannedStep.php @@ -18,12 +18,13 @@ class PlannedStep } } - public function getSafeScript(): string + public function getSafeScript(): string { $script = $this->script; foreach ($this->secrets as $key => $value) { $script = str_replace("[!{$key}]", '********', $script); } + return $script; } @@ -33,6 +34,7 @@ class PlannedStep foreach ($this->secrets as $key => $value) { $script = str_replace("[!{$key}]", $value, $script); } + return $script; } -} \ No newline at end of file +} diff --git a/app/Data/ServerProviders/CreatedServer.php b/app/Data/ServerProviders/CreatedServer.php index b08c273..3d7d5fa 100644 --- a/app/Data/ServerProviders/CreatedServer.php +++ b/app/Data/ServerProviders/CreatedServer.php @@ -12,4 +12,4 @@ class CreatedServer public string $ipv4, public string $ipv6, ) {} -} \ No newline at end of file +} diff --git a/app/Data/ServerProviders/Image.php b/app/Data/ServerProviders/Image.php index 78450ab..760a87b 100644 --- a/app/Data/ServerProviders/Image.php +++ b/app/Data/ServerProviders/Image.php @@ -10,4 +10,4 @@ class Image public string $osFlavor, public string $osVersion, ) {} -} \ No newline at end of file +} diff --git a/app/Data/ServerProviders/Location.php b/app/Data/ServerProviders/Location.php index 06d9548..bf89768 100644 --- a/app/Data/ServerProviders/Location.php +++ b/app/Data/ServerProviders/Location.php @@ -10,4 +10,4 @@ class Location public string $country, public string $city, ) {} -} \ No newline at end of file +} diff --git a/app/Data/ServerProviders/ServerType.php b/app/Data/ServerProviders/ServerType.php index 19ae6f4..57d4aa4 100644 --- a/app/Data/ServerProviders/ServerType.php +++ b/app/Data/ServerProviders/ServerType.php @@ -5,10 +5,10 @@ namespace App\Data\ServerProviders; class ServerType { /** - * @param string $name The name of the server type - * @param int $cores The number of cores - * @param int $memory The amount of memory in GB - * @param int $disk The amount of disk space in GB + * @param string $name The name of the server type + * @param int $cores The number of cores + * @param int $memory The amount of memory in GB + * @param int $disk The amount of disk space in GB */ public function __construct( public string $id, @@ -19,4 +19,4 @@ class ServerType public float $priceMonthly, public float $priceHourly, ) {} -} \ No newline at end of file +} diff --git a/app/Drivers/DatabaseDriver.php b/app/Drivers/DatabaseDriver.php index 9d10822..d4d0f35 100644 --- a/app/Drivers/DatabaseDriver.php +++ b/app/Drivers/DatabaseDriver.php @@ -5,9 +5,13 @@ namespace App\Drivers; abstract class DatabaseDriver extends Driver { public string $defaultUser = 'keystone'; + public string $defaultDb = 'keystone'; + public ?string $containerName; + public ?string $containerId; + public ?string $defaultPassword; abstract public function __construct( @@ -15,4 +19,4 @@ abstract class DatabaseDriver extends Driver ?string $containerId = null, ?string $defaultPassword = null, ); -} \ No newline at end of file +} diff --git a/app/Drivers/Driver.php b/app/Drivers/Driver.php index 5e935aa..d1bdda9 100644 --- a/app/Drivers/Driver.php +++ b/app/Drivers/Driver.php @@ -7,11 +7,13 @@ use App\Data\Deployments\Plan; abstract class Driver { public Plan $deploymentPlan; + public ?string $containerName; + public ?string $containerId; abstract public function __construct( ?string $containerName = null, ?string $containerId = null, ); -} \ No newline at end of file +} diff --git a/app/Drivers/Postgres/Postgres17Driver.php b/app/Drivers/Postgres/Postgres17Driver.php index be310aa..66a9824 100644 --- a/app/Drivers/Postgres/Postgres17Driver.php +++ b/app/Drivers/Postgres/Postgres17Driver.php @@ -9,15 +9,16 @@ use App\Drivers\DatabaseDriver; class Postgres17Driver extends DatabaseDriver { public Plan $deploymentPlan; + public string $defaultUser = 'keystone'; + public string $defaultDb = 'keystone'; public function __construct( public ?string $containerName = null, public ?string $containerId = null, public ?string $defaultPassword = null, - ) - { + ) { $this->deploymentPlan = new Plan(steps: [ new Step( name: 'Run the docker image', @@ -27,17 +28,17 @@ class Postgres17Driver extends DatabaseDriver script: function () { $script = collect(); if ($this->containerName) { - $script->push('docker stop ' . $this->containerName . ' || true'); - } else if ($this->containerId) { - $script->push('docker stop ' . $this->containerId . ' || true'); + $script->push('docker stop '.$this->containerName.' || true'); + } elseif ($this->containerId) { + $script->push('docker stop '.$this->containerId.' || true'); } - $runCommand = "docker run -d"; + $runCommand = 'docker run -d'; if ($this->containerName) { $runCommand .= " --name {$this->containerName}"; } if ($this->defaultPassword) { - $runCommand .= " -e POSTGRES_PASSWORD=[!defaultPassword!]"; + $runCommand .= ' -e POSTGRES_PASSWORD=[!defaultPassword!]'; } if ($this->defaultUser) { $runCommand .= " -e POSTGRES_USER={$this->defaultUser}"; @@ -46,7 +47,7 @@ class Postgres17Driver extends DatabaseDriver $runCommand .= " -e POSTGRES_DB={$this->defaultDb}"; } - $runCommand .= " -p 5432:5432 postgres:17"; + $runCommand .= ' -p 5432:5432 postgres:17'; return $runCommand; } @@ -54,7 +55,7 @@ class Postgres17Driver extends DatabaseDriver new Step( name: 'Configure firewall', script: 'ufw allow 5432/tcp || true', - ) + ), ]); } -} \ No newline at end of file +} diff --git a/app/Enums/Concerns/Arrayable.php b/app/Enums/Concerns/Arrayable.php index c14cc96..c2fe299 100644 --- a/app/Enums/Concerns/Arrayable.php +++ b/app/Enums/Concerns/Arrayable.php @@ -11,4 +11,4 @@ trait Arrayable return array_combine($names, $values); } -} \ No newline at end of file +} diff --git a/app/Enums/DeploymentStatus.php b/app/Enums/DeploymentStatus.php index 8dd0ae7..ccd1492 100644 --- a/app/Enums/DeploymentStatus.php +++ b/app/Enums/DeploymentStatus.php @@ -7,10 +7,10 @@ use App\Enums\Concerns\Arrayable; enum DeploymentStatus: string { use Arrayable; - + case PENDING = 'pending'; case IN_PROGRESS = 'in-progress'; case COMPLETED = 'completed'; case CANCELLED = 'canceled'; case FAILED = 'failed'; -} \ No newline at end of file +} diff --git a/app/Enums/FirewallRuleStatus.php b/app/Enums/FirewallRuleStatus.php index f545284..66262c6 100644 --- a/app/Enums/FirewallRuleStatus.php +++ b/app/Enums/FirewallRuleStatus.php @@ -12,4 +12,4 @@ enum FirewallRuleStatus: string case INSTALLED = 'installed'; case FAILED = 'failed'; case REMOVED = 'removed'; -} \ No newline at end of file +} diff --git a/app/Enums/FirewallRuleType.php b/app/Enums/FirewallRuleType.php index de080c4..e883a51 100644 --- a/app/Enums/FirewallRuleType.php +++ b/app/Enums/FirewallRuleType.php @@ -6,4 +6,4 @@ enum FirewallRuleType: string { case ALLOW = 'allow'; case DENY = 'deny'; -} \ No newline at end of file +} diff --git a/app/Enums/NetworkType.php b/app/Enums/NetworkType.php index c7bb056..0acd2eb 100644 --- a/app/Enums/NetworkType.php +++ b/app/Enums/NetworkType.php @@ -7,7 +7,7 @@ use App\Enums\Concerns\Arrayable; enum NetworkType: string { use Arrayable; - + case EXTERNAL = 'external'; // managed by provider case INTERNAL = 'internal'; // managed by keystone -} \ No newline at end of file +} diff --git a/app/Enums/RepositoryType.php b/app/Enums/RepositoryType.php index 304d1df..73c3151 100644 --- a/app/Enums/RepositoryType.php +++ b/app/Enums/RepositoryType.php @@ -9,4 +9,4 @@ enum RepositoryType: string use Arrayable; case GIT = 'git'; -} \ No newline at end of file +} diff --git a/app/Enums/ServerStatus.php b/app/Enums/ServerStatus.php index d8fd841..bc7c4e8 100644 --- a/app/Enums/ServerStatus.php +++ b/app/Enums/ServerStatus.php @@ -7,7 +7,7 @@ use App\Enums\Concerns\Arrayable; enum ServerStatus: string { use Arrayable; - + case WAITING_FOR_PROVIDER = 'waiting-for-provider'; case PROVIDER_TIMEOUT = 'provider-timeout'; case UNPROVISIONED = 'unprovisioned'; diff --git a/app/Enums/ServiceCategory.php b/app/Enums/ServiceCategory.php index 7e71e3b..ef802f0 100644 --- a/app/Enums/ServiceCategory.php +++ b/app/Enums/ServiceCategory.php @@ -7,20 +7,22 @@ use App\Enums\Concerns\Arrayable; enum ServiceCategory: string { use Arrayable; - + case DATABASE = 'database'; case APPLICATION = 'application'; case GATEWAY = 'gateway'; case STORAGE = 'storage'; case CACHE = 'cache'; - public static function getDescription(ServiceCategory|string $category) { + public static function getDescription(ServiceCategory|string $category) + { if (is_string($category)) { $category = ServiceCategory::from($category); } if (! $category instanceof ServiceCategory) { throw new \InvalidArgumentException('Invalid category provided'); } + return match ($category) { self::APPLICATION => 'The base container image for your application', self::DATABASE => 'Postgres or MySQL', @@ -29,4 +31,4 @@ enum ServiceCategory: string self::CACHE => 'Redis, Memcached or similar', }; } -} \ No newline at end of file +} diff --git a/app/Enums/ServiceStatus.php b/app/Enums/ServiceStatus.php index 029068d..fcd0841 100644 --- a/app/Enums/ServiceStatus.php +++ b/app/Enums/ServiceStatus.php @@ -7,11 +7,11 @@ use App\Enums\Concerns\Arrayable; enum ServiceStatus: string { use Arrayable; - + case NOT_INSTALLED = 'not-installed'; case INSTALLING = 'installing'; case RUNNING = 'running'; case STOPPED = 'stopped'; case ERROR = 'error'; case UNKNOWN = 'unknown'; -} \ No newline at end of file +} diff --git a/app/Enums/ServiceType.php b/app/Enums/ServiceType.php index 1f14cc1..dd7c0aa 100644 --- a/app/Enums/ServiceType.php +++ b/app/Enums/ServiceType.php @@ -4,7 +4,8 @@ namespace App\Enums; use App\Enums\Concerns\Arrayable; -enum ServiceType: string { +enum ServiceType: string +{ use Arrayable; case FRANKENPHP = 'frankenphp'; diff --git a/app/Http/Controllers/ApplicationController.php b/app/Http/Controllers/ApplicationController.php index 79ab770..504b1de 100644 --- a/app/Http/Controllers/ApplicationController.php +++ b/app/Http/Controllers/ApplicationController.php @@ -9,6 +9,7 @@ class ApplicationController extends Controller public function show(Request $request) { $id = $request->route('application'); + return inertia('applications/Show'); } } diff --git a/app/Http/Controllers/EnvironmentController.php b/app/Http/Controllers/EnvironmentController.php index cda7286..a9a6657 100644 --- a/app/Http/Controllers/EnvironmentController.php +++ b/app/Http/Controllers/EnvironmentController.php @@ -10,6 +10,7 @@ class EnvironmentController extends Controller public function show(Request $request) { $id = $request->route('environment'); + return inertia('environments/Show', [ 'environment' => Environment::findOrFail($id), ]); diff --git a/app/Http/Controllers/OrganisationController.php b/app/Http/Controllers/OrganisationController.php index 0deb625..f0cebc6 100644 --- a/app/Http/Controllers/OrganisationController.php +++ b/app/Http/Controllers/OrganisationController.php @@ -2,8 +2,6 @@ namespace App\Http\Controllers; -use Illuminate\Http\Request; - class OrganisationController extends Controller { public function show() diff --git a/app/Http/Controllers/ServerController.php b/app/Http/Controllers/ServerController.php index 293277b..154b272 100644 --- a/app/Http/Controllers/ServerController.php +++ b/app/Http/Controllers/ServerController.php @@ -8,11 +8,9 @@ use App\Enums\ServerProvider; use App\Enums\ServerStatus; use App\Jobs\Servers\WaitForServerToConnect; use App\Models\Organisation; -use App\Services\ServerProviders\HetznerService; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Str; -use NunoMaduro\Collision\Provider; class ServerController extends Controller { @@ -35,13 +33,13 @@ class ServerController extends Controller $providerService = app(GetProviderService::class)->execute($request->provider); if ($providerService) { - $locations = Cache::remember($request->provider . '.locations', now()->addHour(), function () use ($providerService) { + $locations = Cache::remember($request->provider.'.locations', now()->addHour(), function () use ($providerService) { return $providerService->getLocations(); }); - $serverTypes = Cache::remember($request->provider . '.serverTypes', now()->addHour(), function () use ($providerService) { + $serverTypes = Cache::remember($request->provider.'.serverTypes', now()->addHour(), function () use ($providerService) { return $providerService->getServerTypes(); }); - $images = Cache::remember($request->provider . '.images', now()->addHour(), function () use ($providerService) { + $images = Cache::remember($request->provider.'.images', now()->addHour(), function () use ($providerService) { return $providerService->getImages(); }); } @@ -59,7 +57,7 @@ class ServerController extends Controller $sudoPassword = Str::random(32); $providerService = app(GetProviderService::class)->execute($request->provider); - if (!$providerService) { + if (! $providerService) { return back()->with('error', 'Invalid provider'); } diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php index 63653e7..a796237 100644 --- a/app/Http/Controllers/ServiceController.php +++ b/app/Http/Controllers/ServiceController.php @@ -9,6 +9,7 @@ class ServiceController extends Controller public function create(Request $request) { $server = $request->route('server'); + return inertia('services/Create', [ 'server' => $server, ]); diff --git a/app/Http/Integrations/Connectors/HetznerConnector.php b/app/Http/Integrations/Connectors/HetznerConnector.php index c542ae1..1def6fe 100644 --- a/app/Http/Integrations/Connectors/HetznerConnector.php +++ b/app/Http/Integrations/Connectors/HetznerConnector.php @@ -8,7 +8,7 @@ class HetznerConnector extends Connector { public function resolveBaseUrl(): string { - return "https://api.hetzner.cloud/v1"; + return 'https://api.hetzner.cloud/v1'; } protected function defaultHeaders(): array @@ -16,7 +16,7 @@ class HetznerConnector extends Connector return [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', - 'Authorization' => 'Bearer ' . config('services.hetzner.key'), + 'Authorization' => 'Bearer '.config('services.hetzner.key'), ]; } } diff --git a/app/Http/Integrations/Requests/Hetzner/Images/GetImagesRequest.php b/app/Http/Integrations/Requests/Hetzner/Images/GetImagesRequest.php index 530ff7e..6c72829 100644 --- a/app/Http/Integrations/Requests/Hetzner/Images/GetImagesRequest.php +++ b/app/Http/Integrations/Requests/Hetzner/Images/GetImagesRequest.php @@ -4,7 +4,6 @@ namespace App\Http\Integrations\Requests\Hetzner\Images; use Saloon\Enums\Method; use Saloon\Http\Request; -use Saloon\Traits\Body\HasJsonBody; class GetImagesRequest extends Request { diff --git a/app/Http/Integrations/Requests/Hetzner/ServerTypes/GetServerTypesRequest.php b/app/Http/Integrations/Requests/Hetzner/ServerTypes/GetServerTypesRequest.php index f6f93d5..dc028df 100644 --- a/app/Http/Integrations/Requests/Hetzner/ServerTypes/GetServerTypesRequest.php +++ b/app/Http/Integrations/Requests/Hetzner/ServerTypes/GetServerTypesRequest.php @@ -13,4 +13,4 @@ class GetServerTypesRequest extends Request { return '/server_types'; } -} \ No newline at end of file +} diff --git a/app/Http/Middleware/HandleAppearance.php b/app/Http/Middleware/HandleAppearance.php index c4ed399..f1a02bb 100644 --- a/app/Http/Middleware/HandleAppearance.php +++ b/app/Http/Middleware/HandleAppearance.php @@ -20,4 +20,4 @@ class HandleAppearance return $next($request); } -} \ No newline at end of file +} diff --git a/app/Jobs/Servers/ProvisionServer.php b/app/Jobs/Servers/ProvisionServer.php index 85a4ec9..80519cd 100644 --- a/app/Jobs/Servers/ProvisionServer.php +++ b/app/Jobs/Servers/ProvisionServer.php @@ -9,7 +9,7 @@ use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Queue\Queueable; use Spatie\Ssh\Ssh; -class ProvisionServer implements ShouldQueue, ShouldBeEncrypted +class ProvisionServer implements ShouldBeEncrypted, ShouldQueue { use Queueable; @@ -37,7 +37,7 @@ class ProvisionServer implements ShouldQueue, ShouldBeEncrypted // Download the provision script and execute it // The script will run in the background $result = $ssh->execute([ - 'wget --quiet --output-document=provision.sh "' . $provisionScriptUrl . '"', + 'wget --quiet --output-document=provision.sh "'.$provisionScriptUrl.'"', 'chmod +x provision.sh', 'nohup ./provision.sh > /dev/null 2>&1 &', ]); @@ -46,6 +46,7 @@ class ProvisionServer implements ShouldQueue, ShouldBeEncrypted $this->server->update([ 'status' => ServerStatus::PROVISIONING_FAILED, ]); + return; } diff --git a/app/Jobs/Servers/WaitForServerToConnect.php b/app/Jobs/Servers/WaitForServerToConnect.php index 0fd3fca..8d9d6c8 100644 --- a/app/Jobs/Servers/WaitForServerToConnect.php +++ b/app/Jobs/Servers/WaitForServerToConnect.php @@ -7,14 +7,14 @@ use App\Models\Server; use Illuminate\Contracts\Queue\ShouldBeEncrypted; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Queue\Queueable; -use Illuminate\Support\Str; use Spatie\Ssh\Ssh; -class WaitForServerToConnect implements ShouldQueue, ShouldBeEncrypted +class WaitForServerToConnect implements ShouldBeEncrypted, ShouldQueue { use Queueable; public int $retryAfter = 15; + public int $tries = 40; public function __construct( @@ -35,6 +35,7 @@ class WaitForServerToConnect implements ShouldQueue, ShouldBeEncrypted if (! $process->isSuccessful()) { $this->release(15); + return; } diff --git a/app/Jobs/Services/DeployService.php b/app/Jobs/Services/DeployService.php index b9afbff..22d2fa4 100644 --- a/app/Jobs/Services/DeployService.php +++ b/app/Jobs/Services/DeployService.php @@ -18,8 +18,7 @@ class DeployService implements ShouldQueue public function __construct( public Service $service, public ?string $defaultPassword = null, - ) - { + ) { // } @@ -27,7 +26,7 @@ class DeployService implements ShouldQueue { $driver = $this->service->driver($this->defaultPassword); $this->service->update([ - 'status' => ServiceStatus::INSTALLING + 'status' => ServiceStatus::INSTALLING, ]); $this->deployment = $this->service->deployments()->create([ 'status' => DeploymentStatus::PENDING, diff --git a/app/Jobs/Services/RunStep.php b/app/Jobs/Services/RunStep.php index 13fd47c..9d19c4a 100644 --- a/app/Jobs/Services/RunStep.php +++ b/app/Jobs/Services/RunStep.php @@ -7,7 +7,6 @@ use App\Enums\ServiceStatus; use App\Models\Step; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Queue\Queueable; -use Spatie\Ssh\Ssh; class RunStep implements ShouldQueue { @@ -15,8 +14,7 @@ class RunStep implements ShouldQueue public function __construct( protected Step $step, - ) - { + ) { // } @@ -33,7 +31,7 @@ class RunStep implements ShouldQueue $ssh = $server->sshClient() ->onOutput(function ($output) { $this->step->update([ - 'logs' => $this->step->logs . "\n" . trim($output), + 'logs' => $this->step->logs."\n".trim($output), ]); }); @@ -43,7 +41,7 @@ class RunStep implements ShouldQueue $this->step->update([ 'status' => DeploymentStatus::FAILED, 'finished_at' => now(), - 'logs' => $this->step->logs . "\n" . trim($result->getErrorOutput()), + 'logs' => $this->step->logs."\n".trim($result->getErrorOutput()), ]); return; @@ -74,7 +72,7 @@ class RunStep implements ShouldQueue $this->step->update([ 'status' => DeploymentStatus::FAILED, 'finished_at' => now(), - 'logs' => $this->step->logs . "\n" . trim($exception->getMessage()), + 'logs' => $this->step->logs."\n".trim($exception->getMessage()), ]); $this->step->deployment->steps()->where('order', '>', $this->step->order)->update([ diff --git a/app/Models/FirewallRule.php b/app/Models/FirewallRule.php index faffb34..4a5b442 100644 --- a/app/Models/FirewallRule.php +++ b/app/Models/FirewallRule.php @@ -36,21 +36,21 @@ class FirewallRule extends Model public function command(bool $delete = false): string { - $command = "ufw"; + $command = 'ufw'; if ($delete) { - $command .= " delete"; + $command .= ' delete'; } if ($this->type === 'allow') { - $command .= " allow"; + $command .= ' allow'; } elseif ($this->type === 'deny') { - $command .= " deny"; + $command .= ' deny'; } if ($this->from) { $command .= " from {$this->from}"; - $command .= " to any port"; + $command .= ' to any port'; } $command .= " {$this->ports}"; diff --git a/app/Models/Network.php b/app/Models/Network.php index 32e13b5..c6a864a 100644 --- a/app/Models/Network.php +++ b/app/Models/Network.php @@ -29,7 +29,7 @@ class Network extends Model { return $this->hasMany(Server::class, 'external_network_id'); } - + public function organisation(): BelongsTo { return $this->belongsTo(Organisation::class); diff --git a/app/Models/Organisation.php b/app/Models/Organisation.php index df1bc11..fc4bebf 100644 --- a/app/Models/Organisation.php +++ b/app/Models/Organisation.php @@ -45,8 +45,9 @@ class Organisation extends Model $slug = Str::slug($name); $count = 2; while (Organisation::where('slug', $slug)->exists()) { - $slug = Str::slug($name) . '-' . $count++; + $slug = Str::slug($name).'-'.$count++; } + return $slug; } } diff --git a/app/Models/Server.php b/app/Models/Server.php index 191a867..235c095 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -33,11 +33,11 @@ class Server extends Model $existingServer = Server::whereOrganisationId($server->organisation_id) ->orderByDesc('internal_ip_ending') ->first(); - + $server->internal_ip_ending = $existingServer ? $existingServer->internal_ip_ending + 1 : 2; - $server->internal_ip = config('keystone.internal_ip_base') . $server->internal_ip_ending; + $server->internal_ip = config('keystone.internal_ip_base').$server->internal_ip_ending; }); } @@ -45,7 +45,7 @@ class Server extends Model { return $this->belongsTo(Network::class, 'external_network_id'); } - + public function internalNetwork(): BelongsTo { return $this->belongsTo(Network::class, 'internal_network_id'); diff --git a/app/Models/Service.php b/app/Models/Service.php index 6c7718b..8409662 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -41,12 +41,12 @@ class Service extends Model public function driver( ?string $defaultPassword = null, - ): Driver - { + ): Driver { $class = config("keystone.drivers.{$this->driver_name}"); - if (!class_exists($class)) { + if (! class_exists($class)) { throw new \Exception("Driver class {$class} not found"); } + return new $class($this->container_name, $this->container_id, defaultPassword: $defaultPassword); } } diff --git a/app/Services/ServerProviders/ServerProviderService.php b/app/Services/ServerProviders/ServerProviderService.php index f4ae1f6..cf9af0d 100644 --- a/app/Services/ServerProviders/ServerProviderService.php +++ b/app/Services/ServerProviders/ServerProviderService.php @@ -22,4 +22,4 @@ abstract class ServerProviderService abstract public function getLocations(): Collection; abstract public function getImages(): Collection; -} \ No newline at end of file +} diff --git a/config/keystone.php b/config/keystone.php index 98cfff6..7e3a8cb 100644 --- a/config/keystone.php +++ b/config/keystone.php @@ -6,7 +6,7 @@ return [ 'drivers' => [ 'postgres' => [ '17' => Postgres17Driver::class, - ] + ], ], 'internal_ip_base' => env('INTERNAL_IP_BASE', '192.168.2.'), -]; \ No newline at end of file +]; diff --git a/config/services.php b/config/services.php index 839d401..a9c2aef 100644 --- a/config/services.php +++ b/config/services.php @@ -37,6 +37,6 @@ return [ 'hetzner' => [ 'key' => env('HETZNER_KEY'), - ] + ], ]; diff --git a/database/factories/OrganisationFactory.php b/database/factories/OrganisationFactory.php index 96e178c..a6ff992 100644 --- a/database/factories/OrganisationFactory.php +++ b/database/factories/OrganisationFactory.php @@ -20,6 +20,7 @@ class OrganisationFactory extends Factory { $name = $this->faker->company(); $owner = User::inRandomOrder()->first() ?: User::factory()->create(); + return [ 'name' => $this->faker->company(), 'slug' => Organisation::createUniqueSlug($name), diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 13e5a09..ffce97d 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -36,7 +36,7 @@ class DatabaseSeeder extends Seeder $organisation->servers()->saveMany($servers); - $organisation->members()->attach($user, ['role' => OrganisationRole::ADMIN]); + $organisation->members()->attach($user, ['role' => OrganisationRole::ADMIN]); $application = $organisation->applications()->create([ 'name' => 'ClipBin', @@ -48,7 +48,7 @@ class DatabaseSeeder extends Seeder 'name' => 'Dev', 'branch' => 'main', 'url' => 'https://dev.clipbin.hjb.dev', - 'status' => 'active' + 'status' => 'active', ]); } } diff --git a/routes/web.php b/routes/web.php index 1200f4d..7abd4d6 100644 --- a/routes/web.php +++ b/routes/web.php @@ -35,7 +35,7 @@ Route::middleware(['auth', 'verified'])->group(function () { ->name('create', 'services.create') ->name('store', 'services.store'); }); - + Route::resource('applications', ApplicationController::class) ->only('show') ->name('show', 'applications.show'); @@ -87,10 +87,11 @@ Route::post('/provision-callback', function (Request $request) { if (! $isValidIp) { logger('someone tried to callback from an invalid IP'); - logger(' server ip: ' . $server->ipv4); - logger(' server ipv6: ' . $server->ipv6); - logger(' callback ip: ' . $request->ip()); - logger(' server id: ' . $server->id); + logger(' server ip: '.$server->ipv4); + logger(' server ipv6: '.$server->ipv6); + logger(' callback ip: '.$request->ip()); + logger(' server id: '.$server->id); + return response('Unauthorized', 401); } @@ -101,5 +102,5 @@ Route::post('/provision-callback', function (Request $request) { return response('OK', 200); })->name('provision.callback'); -require __DIR__ . '/settings.php'; -require __DIR__ . '/auth.php'; +require __DIR__.'/settings.php'; +require __DIR__.'/auth.php'; diff --git a/tests/Feature/Auth/AuthenticationTest.php b/tests/Feature/Auth/AuthenticationTest.php index 7d08f50..a272b9d 100644 --- a/tests/Feature/Auth/AuthenticationTest.php +++ b/tests/Feature/Auth/AuthenticationTest.php @@ -38,4 +38,4 @@ test('users can logout', function () { $this->assertGuest(); $response->assertRedirect('/'); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Auth/EmailVerificationTest.php b/tests/Feature/Auth/EmailVerificationTest.php index e303f41..f282dff 100644 --- a/tests/Feature/Auth/EmailVerificationTest.php +++ b/tests/Feature/Auth/EmailVerificationTest.php @@ -43,4 +43,4 @@ test('email is not verified with invalid hash', function () { $this->actingAs($user)->get($verificationUrl); expect($user->fresh()->hasVerifiedEmail())->toBeFalse(); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Auth/PasswordConfirmationTest.php b/tests/Feature/Auth/PasswordConfirmationTest.php index d5894f1..8a42902 100644 --- a/tests/Feature/Auth/PasswordConfirmationTest.php +++ b/tests/Feature/Auth/PasswordConfirmationTest.php @@ -29,4 +29,4 @@ test('password is not confirmed with invalid password', function () { ]); $response->assertSessionHasErrors(); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Auth/PasswordResetTest.php b/tests/Feature/Auth/PasswordResetTest.php index 4d243b4..0504276 100644 --- a/tests/Feature/Auth/PasswordResetTest.php +++ b/tests/Feature/Auth/PasswordResetTest.php @@ -57,4 +57,4 @@ test('password can be reset with valid token', function () { return true; }); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Auth/RegistrationTest.php b/tests/Feature/Auth/RegistrationTest.php index 5c184ea..d7af995 100644 --- a/tests/Feature/Auth/RegistrationTest.php +++ b/tests/Feature/Auth/RegistrationTest.php @@ -22,4 +22,4 @@ test('new users can register', function () { assertTrue(auth()->user()->ownedOrganisations()->count() === 1); $response->assertRedirect(route('dashboard', absolute: false)); -}); \ No newline at end of file +}); diff --git a/tests/Feature/DashboardTest.php b/tests/Feature/DashboardTest.php index 437eb09..df63dd2 100644 --- a/tests/Feature/DashboardTest.php +++ b/tests/Feature/DashboardTest.php @@ -13,4 +13,4 @@ test('authenticated users can visit the dashboard', function () { $response = $this->get('/dashboard'); $response->assertStatus(200); -}); \ No newline at end of file +}); diff --git a/tests/Feature/ExampleTest.php b/tests/Feature/ExampleTest.php index b63b781..1e2a000 100644 --- a/tests/Feature/ExampleTest.php +++ b/tests/Feature/ExampleTest.php @@ -4,4 +4,4 @@ test('returns a successful response', function () { $response = $this->get('/'); $response->assertStatus(200); -}); \ No newline at end of file +}); diff --git a/tests/Feature/ServerControllerTest.php b/tests/Feature/ServerControllerTest.php index 8926184..5fc8cd0 100644 --- a/tests/Feature/ServerControllerTest.php +++ b/tests/Feature/ServerControllerTest.php @@ -5,8 +5,6 @@ use App\Data\ServerProviders\CreatedServer; use App\Models\Organisation; use App\Models\Server; use App\Models\User; -use Illuminate\Support\Facades\Cache; -use Illuminate\Support\Facades\Session; use Illuminate\Support\Str; use Inertia\Testing\AssertableInertia; @@ -27,7 +25,7 @@ test('index route displays servers for an organisation', function () { $response = $this->get(route('servers.index', ['organisation' => $organisation->id])); $response->assertStatus(200); - $response->assertInertia(fn(AssertableInertia $page) => $page + $response->assertInertia(fn (AssertableInertia $page) => $page ->component('servers/Index')); }); @@ -35,7 +33,7 @@ test('create route returns inertia view', function () { $organisation = Organisation::factory()->create(); $response = $this->get(route('servers.create', ['organisation' => $organisation->id])); $response->assertStatus(200); - $response->assertInertia(fn(AssertableInertia $page) => $page + $response->assertInertia(fn (AssertableInertia $page) => $page ->component('servers/Create')); }); @@ -67,7 +65,7 @@ test('store route creates a server with valid data', function () { ipv6: '::1', status: 'running', rootPassword: Str::random(16), - ) + ) ); $mock->shouldReceive('execute')->andReturn($providerMock); @@ -95,10 +93,10 @@ test('show route displays a single server', function () { $response = $this->get(route('servers.show', [ 'organisation' => $organisation->id, - 'server' => $server->id + 'server' => $server->id, ])); $response->assertStatus(200); - $response->assertInertia(fn(AssertableInertia $page) => $page + $response->assertInertia(fn (AssertableInertia $page) => $page ->component('servers/Show')); }); diff --git a/tests/Feature/Settings/PasswordUpdateTest.php b/tests/Feature/Settings/PasswordUpdateTest.php index f4566fc..16533df 100644 --- a/tests/Feature/Settings/PasswordUpdateTest.php +++ b/tests/Feature/Settings/PasswordUpdateTest.php @@ -37,4 +37,4 @@ test('correct password must be provided to update password', function () { $response ->assertSessionHasErrors('current_password') ->assertRedirect('/settings/password'); -}); \ No newline at end of file +}); diff --git a/tests/Feature/Settings/ProfileUpdateTest.php b/tests/Feature/Settings/ProfileUpdateTest.php index 500271c..5dd02b0 100644 --- a/tests/Feature/Settings/ProfileUpdateTest.php +++ b/tests/Feature/Settings/ProfileUpdateTest.php @@ -100,4 +100,4 @@ test('correct password must be provided to delete account', function () { ->assertRedirect('/settings/profile'); expect($user->fresh())->not->toBeNull(); -}); \ No newline at end of file +}); diff --git a/tests/Unit/ExampleTest.php b/tests/Unit/ExampleTest.php index 27f3f87..44a4f33 100644 --- a/tests/Unit/ExampleTest.php +++ b/tests/Unit/ExampleTest.php @@ -2,4 +2,4 @@ test('that true is true', function () { expect(true)->toBeTrue(); -}); \ No newline at end of file +});