From 3c99f24b5ab752557eb963628a1c1aa797b5a544 Mon Sep 17 00:00:00 2001 From: Raymond Berger Date: Fri, 5 Jan 2024 15:10:30 +0100 Subject: [PATCH 01/15] fix small typo --- resources/views/livewire/project/new/select.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/project/new/select.blade.php b/resources/views/livewire/project/new/select.blade.php index 93ecc5a04..4ff231c8b 100644 --- a/resources/views/livewire/project/new/select.blade.php +++ b/resources/views/livewire/project/new/select.blade.php @@ -77,7 +77,7 @@ Based on an existing Docker Image
- You can deploy an existing Docker Image form any Registry, without Git. + You can deploy an existing Docker Image from any Registry, without Git.
From bf44b4b94920749275f0f5b7815649caa7dd2487 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Sun, 7 Jan 2024 13:34:47 +0100 Subject: [PATCH 02/15] version++ --- config/sentry.php | 2 +- config/version.php | 2 +- versions.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/sentry.php b/config/sentry.php index 17b924911..a7bbeb2d0 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.183', + 'release' => '4.0.0-beta.184', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index c36192445..edf3c27d0 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ Date: Sun, 7 Jan 2024 16:23:41 +0100 Subject: [PATCH 03/15] refactor routes --- app/Http/Controllers/Controller.php | 133 +++----- app/Http/Controllers/DatabaseController.php | 84 ----- app/Jobs/ContainerStatusJob.php | 6 +- app/Livewire/Boarding/Index.php | 2 +- app/Livewire/CommandCenter/Index.php | 18 ++ app/Livewire/ForcePasswordReset.php | 4 + app/Livewire/Profile/{Form.php => Index.php} | 8 +- app/Livewire/Project/AddEnvironment.php | 2 +- .../Project/Application/Configuration.php | 1 - .../{Deployments.php => Deployment/Index.php} | 29 +- .../Project/Application/Deployment/Show.php} | 66 ++-- .../Project/Application/DeploymentLogs.php | 27 -- app/Livewire/Project/Application/Heading.php | 8 +- app/Livewire/Project/Application/Previews.php | 2 +- app/Livewire/Project/Application/Rollback.php | 2 +- .../Project/{CloneProject.php => CloneMe.php} | 6 +- .../Project/Database/Backup/Execution.php | 41 +++ .../Project/Database/Backup/Index.php | 39 +++ app/Livewire/Project/Database/BackupEdit.php | 2 +- .../Project/Database/Configuration.php | 29 ++ app/Livewire/Project/DeleteProject.php | 2 +- app/Livewire/Project/Edit.php | 9 + app/Livewire/Project/Index.php | 21 ++ app/Livewire/Project/New/Select.php | 4 +- .../Project/Resource/Create.php} | 74 +---- app/Livewire/Project/Resource/Index.php | 29 ++ .../Project/Service/Configuration.php | 54 ++++ app/Livewire/Project/Service/Index.php | 68 ++-- app/Livewire/Project/Service/Show.php | 52 ---- app/Livewire/Project/Shared/Danger.php | 2 +- .../Shared/ExecuteContainerCommand.php | 1 - app/Livewire/Project/Show.php | 26 ++ .../{ => Security}/PrivateKey/Create.php | 2 +- .../PrivateKey/Show.php} | 5 +- app/Livewire/Server/Delete.php | 2 +- app/Livewire/Server/Destination/Show.php | 2 +- app/Livewire/Server/{All.php => Index.php} | 4 +- app/Livewire/Server/LogDrains.php | 2 +- app/Livewire/Server/PrivateKey/Show.php | 2 +- app/Livewire/Server/Proxy/Logs.php | 2 +- app/Livewire/Server/Proxy/Show.php | 2 +- app/Livewire/Server/Show.php | 2 +- app/Livewire/Settings/Index.php | 38 +++ .../License.php} | 18 +- .../Subscription/{Show.php => Index.php} | 4 +- app/Livewire/Team/Delete.php | 29 -- app/Livewire/Team/Form.php | 35 --- app/Livewire/Team/Index.php | 65 ++++ app/Livewire/Team/Member/Index.php | 20 ++ app/Livewire/Team/Notification/Index.php | 13 + app/Livewire/Team/Storage/Create.php | 2 +- app/Livewire/Team/Storage/Form.php | 2 +- app/Livewire/Team/Storage/Index.php | 18 ++ app/Livewire/Team/Storage/Show.php | 22 ++ app/Models/S3Storage.php | 2 +- .../Container/ContainerRestarted.php | 6 +- .../Container/ContainerStopped.php | 6 +- app/Providers/FortifyServiceProvider.php | 2 +- .../views/auth/force-password-reset.blade.php | 3 - .../components/applications/navbar.blade.php | 4 +- .../components/databases/navbar.blade.php | 4 +- .../resources/breadcrumbs.blade.php | 2 +- .../components/settings/navbar.blade.php | 4 +- .../views/components/team/navbar.blade.php | 10 +- .../application-deployment-failed.blade.php | 15 +- .../application-deployment-success.blade.php | 14 +- .../application-status-changes.blade.php | 8 +- .../views/emails/backup-failed.blade.php | 7 +- .../views/emails/backup-success.blade.php | 2 +- .../emails/before-trial-conversion.blade.php | 8 +- .../emails/container-restarted.blade.php | 14 +- .../views/emails/container-stopped.blade.php | 10 +- .../views/emails/email-verification.blade.php | 2 +- .../views/emails/high-disk-usage.blade.php | 9 +- .../views/emails/invitation-link.blade.php | 9 +- .../views/emails/reset-password.blade.php | 6 +- .../emails/s3-connection-error.blade.php | 5 +- .../emails/server-lost-connection.blade.php | 11 +- .../views/emails/server-revived.blade.php | 5 +- .../subscription-invoice-failed.blade.php | 5 +- resources/views/emails/test.blade.php | 2 +- resources/views/emails/trial-ended.blade.php | 7 +- .../views/emails/trial-ends-soon.blade.php | 7 +- resources/views/emails/updates.blade.php | 4 +- .../emails/waitlist-confirmation.blade.php | 9 +- .../emails/waitlist-invitation.blade.php | 2 +- .../views/livewire/check-license.blade.php | 24 -- .../livewire/command-center/index.blade.php | 12 + resources/views/livewire/dashboard.blade.php | 4 +- .../livewire/private-key/change.blade.php | 52 ---- .../views/livewire/profile/form.blade.php | 12 - .../views/livewire/profile/index.blade.php | 92 ++++++ .../application/deployment-logs.blade.php | 98 ------ .../application/deployment/index.blade.php | 105 +++++++ .../application/deployment/show.blade.php | 104 +++++++ .../project/application/deployments.blade.php | 99 ------ .../project/application/previews.blade.php | 2 +- ...e-project.blade.php => clone-me.blade.php} | 0 .../database/backup/execution.blade.php | 19 ++ .../project/database/backup/index.blade.php | 22 ++ .../project/database/configuration.blade.php | 82 +++++ .../database/scheduled-backups.blade.php | 2 +- .../project/environment-edit.blade.php | 2 +- .../project/index.blade.php} | 4 +- .../project/resource/create.blade.php | 17 + .../livewire/project/resource/index.blade.php | 97 ++++++ .../project/service/configuration.blade.php | 169 ++++++++++ .../livewire/project/service/index.blade.php | 207 +++---------- .../livewire/project/service/show.blade.php | 62 ---- .../{ => livewire}/project/show.blade.php | 6 +- .../private-key/create.blade.php | 2 + .../security/private-key/show.blade.php | 54 ++++ .../server/{all.blade.php => index.blade.php} | 0 .../server/show-private-key.blade.php | 2 +- .../views/livewire/settings/index.blade.php | 25 ++ .../views/livewire/settings/license.blade.php | 28 ++ .../{show.blade.php => index.blade.php} | 0 .../views/livewire/team/create.blade.php | 18 +- .../views/livewire/team/delete.blade.php | 60 ---- resources/views/livewire/team/form.blade.php | 12 - resources/views/livewire/team/index.blade.php | 89 ++++++ .../team/member/index.blade.php} | 4 +- .../team/notification/index.blade.php} | 4 +- .../team/storage/index.blade.php} | 4 +- .../team/storage}/show.blade.php | 4 +- .../livewire/team/storages/create.blade.php | 3 + resources/views/project/edit.blade.php | 3 - resources/views/project/resources.blade.php | 10 +- .../security/private-key/index.blade.php | 4 +- .../views/security/private-key/new.blade.php | 5 - .../views/security/private-key/show.blade.php | 4 - resources/views/team/create.blade.php | 5 - resources/views/team/index.blade.php | 18 -- .../views/team/storages/create.blade.php | 3 - routes/web.php | 290 +++++++++--------- 135 files changed, 1881 insertions(+), 1409 deletions(-) delete mode 100644 app/Http/Controllers/DatabaseController.php create mode 100644 app/Livewire/CommandCenter/Index.php rename app/Livewire/Profile/{Form.php => Index.php} (85%) rename app/Livewire/Project/Application/{Deployments.php => Deployment/Index.php} (56%) rename app/{Http/Controllers/ApplicationController.php => Livewire/Project/Application/Deployment/Show.php} (52%) delete mode 100644 app/Livewire/Project/Application/DeploymentLogs.php rename app/Livewire/Project/{CloneProject.php => CloneMe.php} (97%) create mode 100644 app/Livewire/Project/Database/Backup/Execution.php create mode 100644 app/Livewire/Project/Database/Backup/Index.php create mode 100644 app/Livewire/Project/Database/Configuration.php create mode 100644 app/Livewire/Project/Index.php rename app/{Http/Controllers/ProjectController.php => Livewire/Project/Resource/Create.php} (63%) create mode 100644 app/Livewire/Project/Resource/Index.php create mode 100644 app/Livewire/Project/Service/Configuration.php delete mode 100644 app/Livewire/Project/Service/Show.php create mode 100644 app/Livewire/Project/Show.php rename app/Livewire/{ => Security}/PrivateKey/Create.php (98%) rename app/Livewire/{PrivateKey/Change.php => Security/PrivateKey/Show.php} (87%) rename app/Livewire/Server/{All.php => Index.php} (80%) create mode 100644 app/Livewire/Settings/Index.php rename app/Livewire/{CheckLicense.php => Settings/License.php} (79%) rename app/Livewire/Subscription/{Show.php => Index.php} (86%) delete mode 100644 app/Livewire/Team/Delete.php delete mode 100644 app/Livewire/Team/Form.php create mode 100644 app/Livewire/Team/Index.php create mode 100644 app/Livewire/Team/Member/Index.php create mode 100644 app/Livewire/Team/Notification/Index.php create mode 100644 app/Livewire/Team/Storage/Index.php create mode 100644 app/Livewire/Team/Storage/Show.php delete mode 100644 resources/views/auth/force-password-reset.blade.php delete mode 100644 resources/views/livewire/check-license.blade.php create mode 100644 resources/views/livewire/command-center/index.blade.php delete mode 100644 resources/views/livewire/private-key/change.blade.php delete mode 100644 resources/views/livewire/profile/form.blade.php create mode 100644 resources/views/livewire/profile/index.blade.php delete mode 100644 resources/views/livewire/project/application/deployment-logs.blade.php create mode 100644 resources/views/livewire/project/application/deployment/index.blade.php create mode 100644 resources/views/livewire/project/application/deployment/show.blade.php delete mode 100644 resources/views/livewire/project/application/deployments.blade.php rename resources/views/livewire/project/{clone-project.blade.php => clone-me.blade.php} (100%) create mode 100644 resources/views/livewire/project/database/backup/execution.blade.php create mode 100644 resources/views/livewire/project/database/backup/index.blade.php create mode 100644 resources/views/livewire/project/database/configuration.blade.php rename resources/views/{projects.blade.php => livewire/project/index.blade.php} (99%) create mode 100644 resources/views/livewire/project/resource/create.blade.php create mode 100644 resources/views/livewire/project/resource/index.blade.php create mode 100644 resources/views/livewire/project/service/configuration.blade.php delete mode 100644 resources/views/livewire/project/service/show.blade.php rename resources/views/{ => livewire}/project/show.blade.php (95%) rename resources/views/livewire/{ => security}/private-key/create.blade.php (86%) create mode 100644 resources/views/livewire/security/private-key/show.blade.php rename resources/views/livewire/server/{all.blade.php => index.blade.php} (100%) create mode 100644 resources/views/livewire/settings/index.blade.php create mode 100644 resources/views/livewire/settings/license.blade.php rename resources/views/livewire/subscription/{show.blade.php => index.blade.php} (100%) delete mode 100644 resources/views/livewire/team/delete.blade.php delete mode 100644 resources/views/livewire/team/form.blade.php create mode 100644 resources/views/livewire/team/index.blade.php rename resources/views/{team/members.blade.php => livewire/team/member/index.blade.php} (98%) rename resources/views/{team/notifications.blade.php => livewire/team/notification/index.blade.php} (98%) rename resources/views/{team/storages/all.blade.php => livewire/team/storage/index.blade.php} (98%) rename resources/views/{team/storages => livewire/team/storage}/show.blade.php (85%) create mode 100644 resources/views/livewire/team/storages/create.blade.php delete mode 100644 resources/views/project/edit.blade.php delete mode 100644 resources/views/security/private-key/new.blade.php delete mode 100644 resources/views/security/private-key/show.blade.php delete mode 100644 resources/views/team/create.blade.php delete mode 100644 resources/views/team/index.blade.php delete mode 100644 resources/views/team/storages/create.blade.php diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 6338d7625..fcc570f30 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -2,11 +2,13 @@ namespace App\Http\Controllers; +use App\Events\TestEvent; use App\Models\InstanceSettings; use App\Models\S3Storage; use App\Models\StandalonePostgresql; use App\Models\TeamInvitation; use App\Models\User; +use App\Providers\RouteServiceProvider; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; @@ -14,11 +16,55 @@ use Illuminate\Support\Facades\Crypt; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; +use Laravel\Fortify\Fortify; +use Laravel\Fortify\Contracts\FailedPasswordResetLinkRequestResponse; +use Laravel\Fortify\Contracts\SuccessfulPasswordResetLinkRequestResponse; +use Illuminate\Support\Facades\Password; class Controller extends BaseController { use AuthorizesRequests, ValidatesRequests; + public function realtime_test() { + if (auth()->user()?->currentTeam()->id !== 0) { + return redirect(RouteServiceProvider::HOME); + } + TestEvent::dispatch(); + return 'Look at your other tab.'; + } + public function verify() { + return view('auth.verify-email'); + } + public function email_verify() { + request()->fulfill(); + $name = request()->user()?->name; + send_internal_notification("User {$name} verified their email address."); + return redirect(RouteServiceProvider::HOME); + } + public function forgot_password() { + if (is_transactional_emails_active()) { + $arrayOfRequest = request()->only(Fortify::email()); + request()->merge([ + 'email' => Str::lower($arrayOfRequest['email']), + ]); + $type = set_transanctional_email_settings(); + if (!$type) { + return response()->json(['message' => 'Transactional emails are not active'], 400); + } + request()->validate([Fortify::email() => 'required|email']); + $status = Password::broker(config('fortify.passwords'))->sendResetLink( + request()->only(Fortify::email()) + ); + if ($status == Password::RESET_LINK_SENT) { + return app(SuccessfulPasswordResetLinkRequestResponse::class, ['status' => $status]); + } + if ($status == Password::RESET_THROTTLED) { + return response('Already requested a password reset in the past minutes.', 400); + } + return app(FailedPasswordResetLinkRequestResponse::class, ['status' => $status]); + } + return response()->json(['message' => 'Transactional emails are not active'], 400); + } public function link() { $token = request()->get('token'); @@ -51,90 +97,7 @@ public function link() return redirect()->route('login')->with('error', 'Invalid credentials.'); } - public function license() - { - if (!isCloud()) { - abort(404); - } - return view('settings.license', [ - 'settings' => InstanceSettings::get(), - ]); - } - - public function force_passoword_reset() - { - return view('auth.force-password-reset'); - } - public function boarding() - { - if (currentTeam()->boarding || isDev()) { - return view('boarding'); - } else { - return redirect()->route('dashboard'); - } - } - - public function settings() - { - if (isInstanceAdmin()) { - $settings = InstanceSettings::get(); - $database = StandalonePostgresql::whereName('coolify-db')->first(); - if ($database) { - if ($database->status !== 'running') { - $database->status = 'running'; - $database->save(); - } - $s3s = S3Storage::whereTeamId(0)->get(); - } - return view('settings.configuration', [ - 'settings' => $settings, - 'database' => $database, - 's3s' => $s3s ?? [], - ]); - } else { - return redirect()->route('dashboard'); - } - } - - public function team() - { - $invitations = []; - if (auth()->user()->isAdminFromSession()) { - $invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get(); - } - return view('team.index', [ - 'invitations' => $invitations, - ]); - } - - public function storages() - { - $s3 = S3Storage::ownedByCurrentTeam()->get(); - return view('team.storages.all', [ - 's3' => $s3, - ]); - } - - public function storages_show() - { - $storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->firstOrFail(); - return view('team.storages.show', [ - 'storage' => $storage, - ]); - } - - public function members() - { - $invitations = []; - if (auth()->user()->isAdminFromSession()) { - $invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get(); - } - return view('team.members', [ - 'invitations' => $invitations, - ]); - } - - public function acceptInvitation() + public function accept_invitation() { try { $resetPassword = request()->query('reset-password'); @@ -169,7 +132,7 @@ public function acceptInvitation() } } - public function revokeInvitation() + public function revoke_invitation() { try { $invitation = TeamInvitation::whereUuid(request()->route('uuid'))->firstOrFail(); diff --git a/app/Http/Controllers/DatabaseController.php b/app/Http/Controllers/DatabaseController.php deleted file mode 100644 index 684e427f9..000000000 --- a/app/Http/Controllers/DatabaseController.php +++ /dev/null @@ -1,84 +0,0 @@ -load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); - if (!$project) { - return redirect()->route('dashboard'); - } - $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']); - if (!$environment) { - return redirect()->route('dashboard'); - } - $database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first(); - if (!$database) { - return redirect()->route('dashboard'); - } - return view('project.database.configuration', ['database' => $database]); - } - - public function executions() - { - $backup_uuid = request()->route('backup_uuid'); - $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); - if (!$project) { - return redirect()->route('dashboard'); - } - $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']); - if (!$environment) { - return redirect()->route('dashboard'); - } - $database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first(); - if (!$database) { - return redirect()->route('dashboard'); - } - $backup = $database->scheduledBackups->where('uuid', $backup_uuid)->first(); - if (!$backup) { - return redirect()->route('dashboard'); - } - $executions = collect($backup->executions)->sortByDesc('created_at'); - return view('project.database.backups.executions', [ - 'database' => $database, - 'backup' => $backup, - 'executions' => $executions, - 's3s' => currentTeam()->s3s, - ]); - } - - public function backups() - { - $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); - if (!$project) { - return redirect()->route('dashboard'); - } - $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']); - if (!$environment) { - return redirect()->route('dashboard'); - } - $database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first(); - if (!$database) { - return redirect()->route('dashboard'); - } - // No backups for redis - if ($database->getMorphClass() === 'App\Models\StandaloneRedis') { - return redirect()->route('project.database.configuration', [ - 'project_uuid' => $project->uuid, - 'environment_name' => $environment->name, - 'database_uuid' => $database->uuid, - ]); - } - return view('project.database.backups.all', [ - 'database' => $database, - 's3s' => currentTeam()->s3s, - ]); - } -} diff --git a/app/Jobs/ContainerStatusJob.php b/app/Jobs/ContainerStatusJob.php index 16d0efa20..c28e266dd 100644 --- a/app/Jobs/ContainerStatusJob.php +++ b/app/Jobs/ContainerStatusJob.php @@ -162,6 +162,10 @@ public function handle() // Notify user that this container should not be there. } } + if (data_get($container,'Name') === '/coolify-db') { + $foundDatabases[] = 0; + } + } $serviceLabelId = data_get($labels, 'coolify.serviceId'); if ($serviceLabelId) { @@ -212,7 +216,7 @@ public function handle() } $name = data_get($exitedService, 'name'); $fqdn = data_get($exitedService, 'fqdn'); - $containerName = $name ? "$name ($fqdn)" : $fqdn; + $containerName = $name ? "$name, available at $fqdn" : $fqdn; $projectUuid = data_get($service, 'environment.project.uuid'); $serviceUuid = data_get($service, 'uuid'); $environmentName = data_get($service, 'environment.name'); diff --git a/app/Livewire/Boarding/Index.php b/app/Livewire/Boarding/Index.php index 9c59f66ab..cc282d4c0 100644 --- a/app/Livewire/Boarding/Index.php +++ b/app/Livewire/Boarding/Index.php @@ -274,7 +274,7 @@ public function showNewResource() { $this->skipBoarding(); return redirect()->route( - 'project.resources.new', + 'project.resource.create', [ 'project_uuid' => $this->createdProject->uuid, 'environment_name' => 'production', diff --git a/app/Livewire/CommandCenter/Index.php b/app/Livewire/CommandCenter/Index.php new file mode 100644 index 000000000..fd6bb7ed6 --- /dev/null +++ b/app/Livewire/CommandCenter/Index.php @@ -0,0 +1,18 @@ +servers = Server::isReachable()->get(); + } + public function render() + { + return view('livewire.command-center.index'); + } +} diff --git a/app/Livewire/ForcePasswordReset.php b/app/Livewire/ForcePasswordReset.php index e5a9a079a..7bbec9d32 100644 --- a/app/Livewire/ForcePasswordReset.php +++ b/app/Livewire/ForcePasswordReset.php @@ -22,6 +22,10 @@ public function mount() { $this->email = auth()->user()->email; } + public function render() + { + return view('livewire.force-password-reset')->layout('layouts.simple'); + } public function submit() { try { diff --git a/app/Livewire/Profile/Form.php b/app/Livewire/Profile/Index.php similarity index 85% rename from app/Livewire/Profile/Form.php rename to app/Livewire/Profile/Index.php index 3d395bf8f..0a2a34766 100644 --- a/app/Livewire/Profile/Form.php +++ b/app/Livewire/Profile/Index.php @@ -5,21 +5,19 @@ use Livewire\Attributes\Validate; use Livewire\Component; -class Form extends Component +class Index extends Component { public int $userId; public string $email; #[Validate('required')] public string $name; - public function mount() { $this->userId = auth()->user()->id; $this->name = auth()->user()->name; $this->email = auth()->user()->email; } - public function submit() { @@ -34,4 +32,8 @@ public function submit() return handleError($e, $this); } } + public function render() + { + return view('livewire.profile.index'); + } } diff --git a/app/Livewire/Project/AddEnvironment.php b/app/Livewire/Project/AddEnvironment.php index be80c21e1..c28cafd16 100644 --- a/app/Livewire/Project/AddEnvironment.php +++ b/app/Livewire/Project/AddEnvironment.php @@ -27,7 +27,7 @@ public function submit() 'project_id' => $this->project->id, ]); - return redirect()->route('project.resources', [ + return redirect()->route('project.resource.index', [ 'project_uuid' => $this->project->uuid, 'environment_name' => $environment->name, ]); diff --git a/app/Livewire/Project/Application/Configuration.php b/app/Livewire/Project/Application/Configuration.php index 691cbb7c4..1bf9e6c3b 100644 --- a/app/Livewire/Project/Application/Configuration.php +++ b/app/Livewire/Project/Application/Configuration.php @@ -4,7 +4,6 @@ use App\Models\Application; use App\Models\Server; -use App\Models\StandaloneDocker; use Livewire\Component; class Configuration extends Component diff --git a/app/Livewire/Project/Application/Deployments.php b/app/Livewire/Project/Application/Deployment/Index.php similarity index 56% rename from app/Livewire/Project/Application/Deployments.php rename to app/Livewire/Project/Application/Deployment/Index.php index 241167a8f..9d07550f4 100644 --- a/app/Livewire/Project/Application/Deployments.php +++ b/app/Livewire/Project/Application/Deployment/Index.php @@ -1,15 +1,15 @@ load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); + if (!$project) { + return redirect()->route('dashboard'); + } + $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']); + if (!$environment) { + return redirect()->route('dashboard'); + } + $application = $environment->applications->where('uuid', request()->route('application_uuid'))->first(); + if (!$application) { + return redirect()->route('dashboard'); + } + ['deployments' => $deployments, 'count' => $count] = $application->deployments(0, 40); + $this->application = $application; + $this->deployments = $deployments; + $this->deployments_count = $count; $this->current_url = url()->current(); $this->show_pull_request_only(); $this->show_more(); } - private function show_pull_request_only() { + private function show_pull_request_only() + { if ($this->pull_request_id) { $this->deployments = $this->deployments->where('pull_request_id', $this->pull_request_id); } @@ -57,4 +74,8 @@ public function load_deployments(int|null $take = null) $this->show_pull_request_only(); $this->show_more(); } + public function render() + { + return view('livewire.project.application.deployment.index'); + } } diff --git a/app/Http/Controllers/ApplicationController.php b/app/Livewire/Project/Application/Deployment/Show.php similarity index 52% rename from app/Http/Controllers/ApplicationController.php rename to app/Livewire/Project/Application/Deployment/Show.php index 12411d3fd..b83c3f3af 100644 --- a/app/Http/Controllers/ApplicationController.php +++ b/app/Livewire/Project/Application/Deployment/Show.php @@ -1,35 +1,20 @@ load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); - if (!$project) { - return redirect()->route('dashboard'); - } - $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']); - if (!$environment) { - return redirect()->route('dashboard'); - } - $application = $environment->applications->where('uuid', request()->route('application_uuid'))->first(); - if (!$application) { - return redirect()->route('dashboard'); - } - ['deployments' => $deployments, 'count' => $count] = $application->deployments(0, 40); - return view('project.application.deployments', ['application' => $application, 'deployments' => $deployments, 'deployments_count' => $count]); - } - - public function deployment() - { + public function mount() { $deploymentUuid = request()->route('deployment_uuid'); $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); @@ -46,7 +31,7 @@ public function deployment() } // $activity = Activity::where('properties->type_uuid', '=', $deploymentUuid)->first(); // if (!$activity) { - // return redirect()->route('project.application.deployments', [ + // return redirect()->route('project.application.deployment.index', [ // 'project_uuid' => $project->uuid, // 'environment_name' => $environment->name, // 'application_uuid' => $application->uuid, @@ -54,17 +39,32 @@ public function deployment() // } $application_deployment_queue = ApplicationDeploymentQueue::where('deployment_uuid', $deploymentUuid)->first(); if (!$application_deployment_queue) { - return redirect()->route('project.application.deployments', [ + return redirect()->route('project.application.deployment.index', [ 'project_uuid' => $project->uuid, 'environment_name' => $environment->name, 'application_uuid' => $application->uuid, ]); } - return view('project.application.deployment', [ - 'application' => $application, - // 'activity' => $activity, - 'application_deployment_queue' => $application_deployment_queue, - 'deployment_uuid' => $deploymentUuid, - ]); + $this->application = $application; + $this->application_deployment_queue = $application_deployment_queue; + $this->deployment_uuid = $deploymentUuid; + } + + public function refreshQueue() + { + $this->application_deployment_queue->refresh(); + } + + public function polling() + { + $this->dispatch('deploymentFinished'); + $this->application_deployment_queue->refresh(); + if (data_get($this->application_deployment_queue, 'status') == 'finished' || data_get($this->application_deployment_queue, 'status') == 'failed') { + $this->isKeepAliveOn = false; + } + } + public function render() + { + return view('livewire.project.application.deployment.show'); } } diff --git a/app/Livewire/Project/Application/DeploymentLogs.php b/app/Livewire/Project/Application/DeploymentLogs.php deleted file mode 100644 index d2d07035d..000000000 --- a/app/Livewire/Project/Application/DeploymentLogs.php +++ /dev/null @@ -1,27 +0,0 @@ -application_deployment_queue->refresh(); - } - - public function polling() - { - $this->dispatch('deploymentFinished'); - $this->application_deployment_queue->refresh(); - if (data_get($this->application_deployment_queue, 'status') == 'finished' || data_get($this->application_deployment_queue, 'status') == 'failed') { - $this->isKeepAliveOn = false; - } - } -} diff --git a/app/Livewire/Project/Application/Heading.php b/app/Livewire/Project/Application/Heading.php index f6bf4852b..170f1db6e 100644 --- a/app/Livewire/Project/Application/Heading.php +++ b/app/Livewire/Project/Application/Heading.php @@ -60,7 +60,7 @@ public function deployNew() force_rebuild: false, is_new_deployment: true, ); - return redirect()->route('project.application.deployment', [ + return redirect()->route('project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $this->deploymentUuid, @@ -83,7 +83,7 @@ public function deploy(bool $force_rebuild = false) deployment_uuid: $this->deploymentUuid, force_rebuild: $force_rebuild, ); - return redirect()->route('project.application.deployment', [ + return redirect()->route('project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $this->deploymentUuid, @@ -113,7 +113,7 @@ public function restartNew() restart_only: true, is_new_deployment: true, ); - return redirect()->route('project.application.deployment', [ + return redirect()->route('project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $this->deploymentUuid, @@ -128,7 +128,7 @@ public function restart() deployment_uuid: $this->deploymentUuid, restart_only: true, ); - return redirect()->route('project.application.deployment', [ + return redirect()->route('project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $this->deploymentUuid, diff --git a/app/Livewire/Project/Application/Previews.php b/app/Livewire/Project/Application/Previews.php index 91a28c994..dffb9461c 100644 --- a/app/Livewire/Project/Application/Previews.php +++ b/app/Livewire/Project/Application/Previews.php @@ -52,7 +52,7 @@ public function deploy(int $pull_request_id, string|null $pull_request_html_url force_rebuild: true, pull_request_id: $pull_request_id, ); - return redirect()->route('project.application.deployment', [ + return redirect()->route('project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $this->deployment_uuid, diff --git a/app/Livewire/Project/Application/Rollback.php b/app/Livewire/Project/Application/Rollback.php index 64d83a5be..a26d5cd47 100644 --- a/app/Livewire/Project/Application/Rollback.php +++ b/app/Livewire/Project/Application/Rollback.php @@ -29,7 +29,7 @@ public function rollbackImage($commit) commit: $commit, force_rebuild: false, ); - return redirect()->route('project.application.deployment', [ + return redirect()->route('project.application.deployment.show', [ 'project_uuid' => $this->parameters['project_uuid'], 'application_uuid' => $this->parameters['application_uuid'], 'deployment_uuid' => $deployment_uuid, diff --git a/app/Livewire/Project/CloneProject.php b/app/Livewire/Project/CloneMe.php similarity index 97% rename from app/Livewire/Project/CloneProject.php rename to app/Livewire/Project/CloneMe.php index 2dea157a2..993c9516c 100644 --- a/app/Livewire/Project/CloneProject.php +++ b/app/Livewire/Project/CloneMe.php @@ -8,7 +8,7 @@ use Livewire\Component; use Visus\Cuid2\Cuid2; -class CloneProject extends Component +class CloneMe extends Component { public string $project_uuid; public string $environment_name; @@ -41,7 +41,7 @@ public function mount($project_uuid) public function render() { - return view('livewire.project.clone-project'); + return view('livewire.project.clone-me'); } public function selectServer($server_id, $destination_id) @@ -152,7 +152,7 @@ public function clone() } $newService->parse(); } - return redirect()->route('project.resources', [ + return redirect()->route('project.resource.index', [ 'project_uuid' => $newProject->uuid, 'environment_name' => $newEnvironment->name, ]); diff --git a/app/Livewire/Project/Database/Backup/Execution.php b/app/Livewire/Project/Database/Backup/Execution.php new file mode 100644 index 000000000..07f7db03c --- /dev/null +++ b/app/Livewire/Project/Database/Backup/Execution.php @@ -0,0 +1,41 @@ +route('backup_uuid'); + $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); + if (!$project) { + return redirect()->route('dashboard'); + } + $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']); + if (!$environment) { + return redirect()->route('dashboard'); + } + $database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first(); + if (!$database) { + return redirect()->route('dashboard'); + } + $backup = $database->scheduledBackups->where('uuid', $backup_uuid)->first(); + if (!$backup) { + return redirect()->route('dashboard'); + } + $executions = collect($backup->executions)->sortByDesc('created_at'); + $this->database = $database; + $this->backup = $backup; + $this->executions = $executions; + $this->s3s = currentTeam()->s3s; + } + public function render() + { + return view('livewire.project.database.backup.execution'); + } +} diff --git a/app/Livewire/Project/Database/Backup/Index.php b/app/Livewire/Project/Database/Backup/Index.php new file mode 100644 index 000000000..6211a0e47 --- /dev/null +++ b/app/Livewire/Project/Database/Backup/Index.php @@ -0,0 +1,39 @@ +load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); + if (!$project) { + return redirect()->route('dashboard'); + } + $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']); + if (!$environment) { + return redirect()->route('dashboard'); + } + $database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first(); + if (!$database) { + return redirect()->route('dashboard'); + } + // No backups for redis + if ($database->getMorphClass() === 'App\Models\StandaloneRedis') { + return redirect()->route('project.database.configuration', [ + 'project_uuid' => $project->uuid, + 'environment_name' => $environment->name, + 'database_uuid' => $database->uuid, + ]); + } + $this->database = $database; + $this->s3s = currentTeam()->s3s; + } + public function render() + { + return view('livewire.project.database.backup.index'); + } +} diff --git a/app/Livewire/Project/Database/BackupEdit.php b/app/Livewire/Project/Database/BackupEdit.php index e8e763c73..86aec0f6a 100644 --- a/app/Livewire/Project/Database/BackupEdit.php +++ b/app/Livewire/Project/Database/BackupEdit.php @@ -52,7 +52,7 @@ public function delete() $url = $url->getPath() . "#{$url->getFragment()}"; return redirect($url); } else { - return redirect()->route('project.database.backups.all', $this->parameters); + return redirect()->route('project.database.backup.index', $this->parameters); } } diff --git a/app/Livewire/Project/Database/Configuration.php b/app/Livewire/Project/Database/Configuration.php new file mode 100644 index 000000000..c988477de --- /dev/null +++ b/app/Livewire/Project/Database/Configuration.php @@ -0,0 +1,29 @@ +load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); + if (!$project) { + return redirect()->route('dashboard'); + } + $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first()->load(['applications']); + if (!$environment) { + return redirect()->route('dashboard'); + } + $database = $environment->databases()->where('uuid', request()->route('database_uuid'))->first(); + if (!$database) { + return redirect()->route('dashboard'); + } + $this->database = $database; + } + public function render() + { + return view('livewire.project.database.configuration'); + } +} diff --git a/app/Livewire/Project/DeleteProject.php b/app/Livewire/Project/DeleteProject.php index 23ca8eb79..7ac4aa281 100644 --- a/app/Livewire/Project/DeleteProject.php +++ b/app/Livewire/Project/DeleteProject.php @@ -25,6 +25,6 @@ public function delete() return $this->dispatch('error', 'Project has resources defined, please delete them first.'); } $project->delete(); - return redirect()->route('projects'); + return redirect()->route('project.index'); } } diff --git a/app/Livewire/Project/Edit.php b/app/Livewire/Project/Edit.php index d08aa3e59..e674e3dd9 100644 --- a/app/Livewire/Project/Edit.php +++ b/app/Livewire/Project/Edit.php @@ -12,6 +12,15 @@ class Edit extends Component 'project.name' => 'required|min:3|max:255', 'project.description' => 'nullable|string|max:255', ]; + public function mount() { + $projectUuid = request()->route('project_uuid'); + $teamId = currentTeam()->id; + $project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first(); + if (!$project) { + return redirect()->route('dashboard'); + } + $this->project = $project; + } public function submit() { diff --git a/app/Livewire/Project/Index.php b/app/Livewire/Project/Index.php new file mode 100644 index 000000000..1e6f79855 --- /dev/null +++ b/app/Livewire/Project/Index.php @@ -0,0 +1,21 @@ +projects = Project::ownedByCurrentTeam()->get(); + $this->servers = Server::ownedByCurrentTeam()->count(); + } + public function render() + { + return view('livewire.project.index'); + } +} diff --git a/app/Livewire/Project/New/Select.php b/app/Livewire/Project/New/Select.php index 47834a7fc..3133efc97 100644 --- a/app/Livewire/Project/New/Select.php +++ b/app/Livewire/Project/New/Select.php @@ -55,7 +55,7 @@ public function render() public function updatedSelectedEnvironment() { - return redirect()->route('project.resources.new', [ + return redirect()->route('project.resource.create', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_name' => $this->selectedEnvironment, ]); @@ -157,7 +157,7 @@ public function setServer(Server $server) public function setDestination(string $destination_uuid) { $this->destination_uuid = $destination_uuid; - return redirect()->route('project.resources.new', [ + return redirect()->route('project.resource.create', [ 'project_uuid' => $this->parameters['project_uuid'], 'environment_name' => $this->parameters['environment_name'], 'type' => $this->type, diff --git a/app/Http/Controllers/ProjectController.php b/app/Livewire/Project/Resource/Create.php similarity index 63% rename from app/Http/Controllers/ProjectController.php rename to app/Livewire/Project/Resource/Create.php index 1e7d6b9cd..db5dc03f4 100644 --- a/app/Http/Controllers/ProjectController.php +++ b/app/Livewire/Project/Resource/Create.php @@ -1,52 +1,18 @@ Project::ownedByCurrentTeam()->get(), - 'servers' => Server::ownedByCurrentTeam()->count(), - ]); - } - - public function edit() - { - $projectUuid = request()->route('project_uuid'); - $teamId = currentTeam()->id; - $project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first(); - if (!$project) { - return redirect()->route('dashboard'); - } - return view('project.edit', ['project' => $project]); - } - - public function show() - { - $projectUuid = request()->route('project_uuid'); - $teamId = currentTeam()->id; - - $project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first(); - if (!$project) { - return redirect()->route('dashboard'); - } - $project->load(['environments']); - return view('project.show', ['project' => $project]); - } - - public function new() - { + public $type; + public function mount() { $services = getServiceTemplates(); - $type = Str::of(request()->query('type')); + $type = str(request()->query('type')); $destination_uuid = request()->query('destination'); $server_id = request()->query('server_id'); @@ -81,14 +47,14 @@ public function new() $oneClickService = data_get($services, "$oneClickServiceName.compose"); $oneClickDotEnvs = data_get($services, "$oneClickServiceName.envs", null); if ($oneClickDotEnvs) { - $oneClickDotEnvs = Str::of(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) { + $oneClickDotEnvs = str(base64_decode($oneClickDotEnvs))->split('/\r\n|\r|\n/')->filter(function ($value) { return !empty($value); }); } if ($oneClickService) { $destination = StandaloneDocker::whereUuid($destination_uuid)->first(); $service = Service::create([ - 'name' => "$oneClickServiceName-" . Str::random(10), + 'name' => "$oneClickServiceName-" . str()->random(10), 'docker_compose_raw' => base64_decode($oneClickService), 'environment_id' => $environment->id, 'server_id' => (int) $server_id, @@ -99,8 +65,8 @@ public function new() $service->save(); if ($oneClickDotEnvs?->count() > 0) { $oneClickDotEnvs->each(function ($value) use ($service) { - $key = Str::before($value, '='); - $value = Str::of(Str::after($value, '=')); + $key = str()->before($value, '='); + $value = str(str()->after($value, '=')); $generatedValue = $value; if ($value->contains('SERVICE_')) { $command = $value->after('SERVICE_')->beforeLast('_'); @@ -123,24 +89,10 @@ public function new() ]); } } - return view('project.new', [ - 'type' => $type->value() - ]); + $this->type = $type->value(); } - - public function resources() + public function render() { - $project = currentTeam()->load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); - if (!$project) { - return redirect()->route('dashboard'); - } - $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first(); - if (!$environment) { - return redirect()->route('dashboard'); - } - return view('project.resources', [ - 'project' => $project, - 'environment' => $environment - ]); + return view('livewire.project.resource.create'); } } diff --git a/app/Livewire/Project/Resource/Index.php b/app/Livewire/Project/Resource/Index.php new file mode 100644 index 000000000..2a7570c9d --- /dev/null +++ b/app/Livewire/Project/Resource/Index.php @@ -0,0 +1,29 @@ +load(['projects'])->projects->where('uuid', request()->route('project_uuid'))->first(); + if (!$project) { + return redirect()->route('dashboard'); + } + $environment = $project->load(['environments'])->environments->where('name', request()->route('environment_name'))->first(); + if (!$environment) { + return redirect()->route('dashboard'); + } + $this->project = $project; + $this->environment = $environment; + } + public function render() + { + return view('livewire.project.resource.index'); + } +} diff --git a/app/Livewire/Project/Service/Configuration.php b/app/Livewire/Project/Service/Configuration.php new file mode 100644 index 000000000..5954b3b36 --- /dev/null +++ b/app/Livewire/Project/Service/Configuration.php @@ -0,0 +1,54 @@ +user()->id; + return [ + "echo-private:user.{$userId},ServiceStatusChanged" => 'checkStatus', + "refreshStacks", + "checkStatus", + ]; + } + public function render() + { + return view('livewire.project.service.configuration'); + } + public function mount() + { + $this->parameters = get_route_parameters(); + $this->query = request()->query(); + $this->service = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail(); + $this->applications = $this->service->applications->sort(); + $this->databases = $this->service->databases->sort(); + } + public function checkStatus() + { + dispatch_sync(new ContainerStatusJob($this->service->server)); + $this->refreshStacks(); + $this->dispatch('serviceStatusChanged'); + } + public function refreshStacks() + { + $this->applications = $this->service->applications->sort(); + $this->applications->each(function ($application) { + $application->refresh(); + }); + $this->databases = $this->service->databases->sort(); + $this->databases->each(function ($database) { + $database->refresh(); + }); + } +} diff --git a/app/Livewire/Project/Service/Index.php b/app/Livewire/Project/Service/Index.php index e55dc610c..21009cb44 100644 --- a/app/Livewire/Project/Service/Index.php +++ b/app/Livewire/Project/Service/Index.php @@ -2,53 +2,51 @@ namespace App\Livewire\Project\Service; -use App\Jobs\ContainerStatusJob; use App\Models\Service; +use App\Models\ServiceApplication; +use App\Models\ServiceDatabase; +use Illuminate\Support\Collection; use Livewire\Component; class Index extends Component { public Service $service; - public $applications; - public $databases; + public ?ServiceApplication $serviceApplication = null; + public ?ServiceDatabase $serviceDatabase = null; public array $parameters; public array $query; - public function getListeners() + public Collection $services; + public $s3s; + + protected $listeners = ['generateDockerCompose']; + + public function mount() { - $userId = auth()->user()->id; - return [ - "echo-private:user.{$userId},ServiceStatusChanged" => 'checkStatus', - "refreshStacks", - "checkStatus", - ]; + try { + $this->services = collect([]); + $this->parameters = get_route_parameters(); + $this->query = request()->query(); + $this->service = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail(); + $service = $this->service->applications()->whereName($this->parameters['service_name'])->first(); + if ($service) { + $this->serviceApplication = $service; + $this->serviceApplication->getFilesFromServer(); + } else { + $this->serviceDatabase = $this->service->databases()->whereName($this->parameters['service_name'])->first(); + $this->serviceDatabase->getFilesFromServer(); + } + $this->s3s = currentTeam()->s3s; + } catch(\Throwable $e) { + return handleError($e, $this); + } + + } + public function generateDockerCompose() + { + $this->service->parse(); } public function render() { return view('livewire.project.service.index'); } - public function mount() - { - $this->parameters = get_route_parameters(); - $this->query = request()->query(); - $this->service = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail(); - $this->applications = $this->service->applications->sort(); - $this->databases = $this->service->databases->sort(); - } - public function checkStatus() - { - dispatch_sync(new ContainerStatusJob($this->service->server)); - $this->refreshStacks(); - $this->dispatch('serviceStatusChanged'); - } - public function refreshStacks() - { - $this->applications = $this->service->applications->sort(); - $this->applications->each(function ($application) { - $application->refresh(); - }); - $this->databases = $this->service->databases->sort(); - $this->databases->each(function ($database) { - $database->refresh(); - }); - } } diff --git a/app/Livewire/Project/Service/Show.php b/app/Livewire/Project/Service/Show.php deleted file mode 100644 index 272e0a399..000000000 --- a/app/Livewire/Project/Service/Show.php +++ /dev/null @@ -1,52 +0,0 @@ -services = collect([]); - $this->parameters = get_route_parameters(); - $this->query = request()->query(); - $this->service = Service::whereUuid($this->parameters['service_uuid'])->firstOrFail(); - $service = $this->service->applications()->whereName($this->parameters['service_name'])->first(); - if ($service) { - $this->serviceApplication = $service; - $this->serviceApplication->getFilesFromServer(); - } else { - $this->serviceDatabase = $this->service->databases()->whereName($this->parameters['service_name'])->first(); - $this->serviceDatabase->getFilesFromServer(); - } - $this->s3s = currentTeam()->s3s; - } catch(\Throwable $e) { - return handleError($e, $this); - } - - } - public function generateDockerCompose() - { - $this->service->parse(); - } - public function render() - { - return view('livewire.project.service.show'); - } -} diff --git a/app/Livewire/Project/Shared/Danger.php b/app/Livewire/Project/Shared/Danger.php index 44a9d5cf3..37664c870 100644 --- a/app/Livewire/Project/Shared/Danger.php +++ b/app/Livewire/Project/Shared/Danger.php @@ -25,7 +25,7 @@ public function delete() { try { DeleteResourceJob::dispatchSync($this->resource); - return redirect()->route('project.resources', [ + return redirect()->route('project.resource.index', [ 'project_uuid' => $this->projectUuid, 'environment_name' => $this->environmentName ]); diff --git a/app/Livewire/Project/Shared/ExecuteContainerCommand.php b/app/Livewire/Project/Shared/ExecuteContainerCommand.php index a3a63c154..f06f7784d 100644 --- a/app/Livewire/Project/Shared/ExecuteContainerCommand.php +++ b/app/Livewire/Project/Shared/ExecuteContainerCommand.php @@ -10,7 +10,6 @@ use App\Models\StandaloneMysql; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; -use Illuminate\Support\Sleep; use Livewire\Component; class ExecuteContainerCommand extends Component diff --git a/app/Livewire/Project/Show.php b/app/Livewire/Project/Show.php new file mode 100644 index 000000000..0824ab32e --- /dev/null +++ b/app/Livewire/Project/Show.php @@ -0,0 +1,26 @@ +route('project_uuid'); + $teamId = currentTeam()->id; + + $project = Project::where('team_id', $teamId)->where('uuid', $projectUuid)->first(); + if (!$project) { + return redirect()->route('dashboard'); + } + $project->load(['environments']); + $this->project = $project; + } + public function render() + { + return view('livewire.project.show'); + } +} diff --git a/app/Livewire/PrivateKey/Create.php b/app/Livewire/Security/PrivateKey/Create.php similarity index 98% rename from app/Livewire/PrivateKey/Create.php rename to app/Livewire/Security/PrivateKey/Create.php index a82b6fb48..62d763601 100644 --- a/app/Livewire/PrivateKey/Create.php +++ b/app/Livewire/Security/PrivateKey/Create.php @@ -1,6 +1,6 @@ private_key = PrivateKey::ownedByCurrentTeam(['name', 'description', 'private_key', 'is_git_related'])->whereUuid(request()->private_key_uuid)->firstOrFail(); $this->public_key = $this->private_key->publicKey(); }catch(\Throwable $e) { return handleError($e, $this); diff --git a/app/Livewire/Server/Delete.php b/app/Livewire/Server/Delete.php index 73edf5ffe..3333283eb 100644 --- a/app/Livewire/Server/Delete.php +++ b/app/Livewire/Server/Delete.php @@ -19,7 +19,7 @@ public function delete() return; } $this->server->delete(); - return redirect()->route('server.all'); + return redirect()->route('server.index'); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Server/Destination/Show.php b/app/Livewire/Server/Destination/Show.php index 7fa2a2823..4e0f54296 100644 --- a/app/Livewire/Server/Destination/Show.php +++ b/app/Livewire/Server/Destination/Show.php @@ -15,7 +15,7 @@ public function mount() try { $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); if (is_null($this->server)) { - return redirect()->route('server.all'); + return redirect()->route('server.index'); } } catch (\Throwable $e) { return handleError($e, $this); diff --git a/app/Livewire/Server/All.php b/app/Livewire/Server/Index.php similarity index 80% rename from app/Livewire/Server/All.php rename to app/Livewire/Server/Index.php index fad5f3fba..45bb1c3e1 100644 --- a/app/Livewire/Server/All.php +++ b/app/Livewire/Server/Index.php @@ -6,7 +6,7 @@ use Illuminate\Database\Eloquent\Collection; use Livewire\Component; -class All extends Component +class Index extends Component { public ?Collection $servers = null; @@ -15,6 +15,6 @@ public function mount () { } public function render() { - return view('livewire.server.all'); + return view('livewire.server.index'); } } diff --git a/app/Livewire/Server/LogDrains.php b/app/Livewire/Server/LogDrains.php index 902ec4b75..b922cc0c9 100644 --- a/app/Livewire/Server/LogDrains.php +++ b/app/Livewire/Server/LogDrains.php @@ -43,7 +43,7 @@ public function mount() try { $server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); if (is_null($server)) { - return redirect()->route('server.all'); + return redirect()->route('server.index'); } $this->server = $server; } catch (\Throwable $e) { diff --git a/app/Livewire/Server/PrivateKey/Show.php b/app/Livewire/Server/PrivateKey/Show.php index 9fa0acb75..71dea7c9d 100644 --- a/app/Livewire/Server/PrivateKey/Show.php +++ b/app/Livewire/Server/PrivateKey/Show.php @@ -17,7 +17,7 @@ public function mount() try { $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); if (is_null($this->server)) { - return redirect()->route('server.all'); + return redirect()->route('server.index'); } $this->privateKeys = PrivateKey::ownedByCurrentTeam()->get()->where('is_git_related', false); } catch (\Throwable $e) { diff --git a/app/Livewire/Server/Proxy/Logs.php b/app/Livewire/Server/Proxy/Logs.php index ed12f8c49..7949b0086 100644 --- a/app/Livewire/Server/Proxy/Logs.php +++ b/app/Livewire/Server/Proxy/Logs.php @@ -15,7 +15,7 @@ public function mount() try { $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); if (is_null($this->server)) { - return redirect()->route('server.all'); + return redirect()->route('server.index'); } } catch (\Throwable $e) { return handleError($e, $this); diff --git a/app/Livewire/Server/Proxy/Show.php b/app/Livewire/Server/Proxy/Show.php index b1175d3b7..7e21e3344 100644 --- a/app/Livewire/Server/Proxy/Show.php +++ b/app/Livewire/Server/Proxy/Show.php @@ -20,7 +20,7 @@ public function mount() try { $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); if (is_null($this->server)) { - return redirect()->route('server.all'); + return redirect()->route('server.index'); } } catch (\Throwable $e) { return handleError($e, $this); diff --git a/app/Livewire/Server/Show.php b/app/Livewire/Server/Show.php index 065335835..13ebc97d4 100644 --- a/app/Livewire/Server/Show.php +++ b/app/Livewire/Server/Show.php @@ -17,7 +17,7 @@ public function mount() try { $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); if (is_null($this->server)) { - return redirect()->route('server.all'); + return redirect()->route('server.index'); } } catch (\Throwable $e) { diff --git a/app/Livewire/Settings/Index.php b/app/Livewire/Settings/Index.php new file mode 100644 index 000000000..44c653b74 --- /dev/null +++ b/app/Livewire/Settings/Index.php @@ -0,0 +1,38 @@ +first(); + if ($database) { + if ($database->status !== 'running') { + $database->status = 'running'; + $database->save(); + } + $s3s = S3Storage::whereTeamId(0)->get(); + } + $this->settings = $settings; + $this->database = $database; + $this->s3s = $s3s ?? []; + } else { + return redirect()->route('dashboard'); + } + } + public function render() + { + return view('livewire.settings.index'); + } +} diff --git a/app/Livewire/CheckLicense.php b/app/Livewire/Settings/License.php similarity index 79% rename from app/Livewire/CheckLicense.php rename to app/Livewire/Settings/License.php index 8d4351fce..64ad0a6f7 100644 --- a/app/Livewire/CheckLicense.php +++ b/app/Livewire/Settings/License.php @@ -1,15 +1,16 @@ 'nullable', 'settings.is_resale_license_active' => 'nullable', @@ -20,12 +21,17 @@ class CheckLicense extends Component 'settings.is_resale_license_active' => 'Is License Active', ]; - public function mount() - { + public function mount () { + if (!isCloud()) { + abort(404); + } $this->instance_id = config('app.id'); $this->settings = InstanceSettings::get(); } - + public function render() + { + return view('livewire.settings.license')->layout('layouts.subscription'); + } public function submit() { $this->validate(); diff --git a/app/Livewire/Subscription/Show.php b/app/Livewire/Subscription/Index.php similarity index 86% rename from app/Livewire/Subscription/Show.php rename to app/Livewire/Subscription/Index.php index 6c92f7555..afc3729c6 100644 --- a/app/Livewire/Subscription/Show.php +++ b/app/Livewire/Subscription/Index.php @@ -6,7 +6,7 @@ use App\Providers\RouteServiceProvider; use Livewire\Component; -class Show extends Component +class Index extends Component { public InstanceSettings $settings; public bool $alreadySubscribed = false; @@ -26,6 +26,6 @@ public function stripeCustomerPortal() { } public function render() { - return view('livewire.subscription.show')->layout('layouts.subscription'); + return view('livewire.subscription.index')->layout('layouts.subscription'); } } diff --git a/app/Livewire/Team/Delete.php b/app/Livewire/Team/Delete.php deleted file mode 100644 index 097419c4c..000000000 --- a/app/Livewire/Team/Delete.php +++ /dev/null @@ -1,29 +0,0 @@ -delete(); - - $currentTeam->members->each(function ($user) use ($currentTeam) { - if ($user->id === auth()->user()->id) { - return; - } - $user->teams()->detach($currentTeam); - $session = DB::table('sessions')->where('user_id', $user->id)->first(); - if ($session) { - DB::table('sessions')->where('id', $session->id)->delete(); - } - }); - - refreshSession(); - return redirect()->route('team.index'); - } -} diff --git a/app/Livewire/Team/Form.php b/app/Livewire/Team/Form.php deleted file mode 100644 index 3deaf0b92..000000000 --- a/app/Livewire/Team/Form.php +++ /dev/null @@ -1,35 +0,0 @@ - 'required|min:3|max:255', - 'team.description' => 'nullable|min:3|max:255', - ]; - protected $validationAttributes = [ - 'team.name' => 'name', - 'team.description' => 'description', - ]; - - public function mount() - { - $this->team = currentTeam(); - } - - public function submit() - { - $this->validate(); - try { - $this->team->save(); - refreshSession(); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } -} diff --git a/app/Livewire/Team/Index.php b/app/Livewire/Team/Index.php new file mode 100644 index 000000000..b7482e671 --- /dev/null +++ b/app/Livewire/Team/Index.php @@ -0,0 +1,65 @@ + 'required|min:3|max:255', + 'team.description' => 'nullable|min:3|max:255', + ]; + protected $validationAttributes = [ + 'team.name' => 'name', + 'team.description' => 'description', + ]; + public function mount() { + $this->team = currentTeam(); + + if (auth()->user()->isAdminFromSession()) { + $this->invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get(); + } + } + public function render() + { + return view('livewire.team.index'); + } + + public function submit() + { + $this->validate(); + try { + $this->team->save(); + refreshSession(); + $this->dispatch('success', 'Team updated successfully.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function delete() + { + $currentTeam = currentTeam(); + $currentTeam->delete(); + + $currentTeam->members->each(function ($user) use ($currentTeam) { + if ($user->id === auth()->user()->id) { + return; + } + $user->teams()->detach($currentTeam); + $session = DB::table('sessions')->where('user_id', $user->id)->first(); + if ($session) { + DB::table('sessions')->where('id', $session->id)->delete(); + } + }); + + refreshSession(); + return redirect()->route('team.index'); + } +} diff --git a/app/Livewire/Team/Member/Index.php b/app/Livewire/Team/Member/Index.php new file mode 100644 index 000000000..bca24c26c --- /dev/null +++ b/app/Livewire/Team/Member/Index.php @@ -0,0 +1,20 @@ +user()->isAdminFromSession()) { + $this->invitations = TeamInvitation::whereTeamId(currentTeam()->id)->get(); + } + } + public function render() + { + return view('livewire.team.member.index'); + } +} diff --git a/app/Livewire/Team/Notification/Index.php b/app/Livewire/Team/Notification/Index.php new file mode 100644 index 000000000..86754d619 --- /dev/null +++ b/app/Livewire/Team/Notification/Index.php @@ -0,0 +1,13 @@ +storage->team_id = currentTeam()->id; $this->storage->testConnection(); $this->storage->save(); - return redirect()->route('team.storages.show', $this->storage->uuid); + return redirect()->route('team.storage.show', $this->storage->uuid); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Team/Storage/Form.php b/app/Livewire/Team/Storage/Form.php index 23b0fe34c..8a26a3471 100644 --- a/app/Livewire/Team/Storage/Form.php +++ b/app/Livewire/Team/Storage/Form.php @@ -43,7 +43,7 @@ public function delete() { try { $this->storage->delete(); - return redirect()->route('team.storages.all'); + return redirect()->route('team.storage.index'); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Team/Storage/Index.php b/app/Livewire/Team/Storage/Index.php new file mode 100644 index 000000000..c15834564 --- /dev/null +++ b/app/Livewire/Team/Storage/Index.php @@ -0,0 +1,18 @@ +s3 = S3Storage::ownedByCurrentTeam()->get(); + } + public function render() + { + return view('livewire.team.storage.index'); + } +} diff --git a/app/Livewire/Team/Storage/Show.php b/app/Livewire/Team/Storage/Show.php new file mode 100644 index 000000000..6fbb6034f --- /dev/null +++ b/app/Livewire/Team/Storage/Show.php @@ -0,0 +1,22 @@ +storage = S3Storage::ownedByCurrentTeam()->whereUuid(request()->storage_uuid)->first(); + if (!$this->storage) { + abort(404); + } + } + public function render() + { + return view('livewire.team.storage.show'); + } +} diff --git a/app/Models/S3Storage.php b/app/Models/S3Storage.php index ec18477eb..9d60ce491 100644 --- a/app/Models/S3Storage.php +++ b/app/Models/S3Storage.php @@ -48,7 +48,7 @@ public function testConnection(bool $shouldSave = false) if ($this->unusable_email_sent === false && is_transactional_emails_active()) { $mail = new MailMessage(); $mail->subject('Coolify: S3 Storage Connection Error'); - $mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('team.storages.show', ['storage_uuid' => $this->uuid])]); + $mail->view('emails.s3-connection-error', ['name' => $this->name, 'reason' => $e->getMessage(), 'url' => route('team.storage.show', ['storage_uuid' => $this->uuid])]); $users = collect([]); $members = $this->team->members()->get(); foreach ($members as $user) { diff --git a/app/Notifications/Container/ContainerRestarted.php b/app/Notifications/Container/ContainerRestarted.php index 723cad8f6..21dc799f8 100644 --- a/app/Notifications/Container/ContainerRestarted.php +++ b/app/Notifications/Container/ContainerRestarted.php @@ -27,7 +27,7 @@ public function via(object $notifiable): array public function toMail(): MailMessage { $mail = new MailMessage(); - $mail->subject("Coolify: A service ({$this->name}) has been restarted automatically on {$this->server->name}"); + $mail->subject("Coolify: A resource ({$this->name}) has been restarted automatically on {$this->server->name}"); $mail->view('emails.container-restarted', [ 'containerName' => $this->name, 'serverName' => $this->server->name, @@ -38,12 +38,12 @@ public function toMail(): MailMessage public function toDiscord(): string { - $message = "Coolify: A service ({$this->name}) has been restarted automatically on {$this->server->name}"; + $message = "Coolify: A resource ({$this->name}) has been restarted automatically on {$this->server->name}"; return $message; } public function toTelegram(): array { - $message = "Coolify: A service ({$this->name}) has been restarted automatically on {$this->server->name}"; + $message = "Coolify: A resource ({$this->name}) has been restarted automatically on {$this->server->name}"; $payload = [ "message" => $message, ]; diff --git a/app/Notifications/Container/ContainerStopped.php b/app/Notifications/Container/ContainerStopped.php index ea474a3e9..ac218c5fe 100644 --- a/app/Notifications/Container/ContainerStopped.php +++ b/app/Notifications/Container/ContainerStopped.php @@ -26,7 +26,7 @@ public function via(object $notifiable): array public function toMail(): MailMessage { $mail = new MailMessage(); - $mail->subject("Coolify: A service ({$this->name}) has been stopped on {$this->server->name}"); + $mail->subject("Coolify: A resource has been stopped unexpectedly on {$this->server->name}"); $mail->view('emails.container-stopped', [ 'containerName' => $this->name, 'serverName' => $this->server->name, @@ -37,12 +37,12 @@ public function toMail(): MailMessage public function toDiscord(): string { - $message = "Coolify: A service ({$this->name}) has been stopped on {$this->server->name}"; + $message = "Coolify: A resource has been stopped unexpectedly on {$this->server->name}"; return $message; } public function toTelegram(): array { - $message = "Coolify: A service ($this->name} has been stopped on {$this->server->name}"; + $message = "Coolify: A resource has been stopped unexpectedly on {$this->server->name}"; $payload = [ "message" => $message, ]; diff --git a/app/Providers/FortifyServiceProvider.php b/app/Providers/FortifyServiceProvider.php index ccd90d14b..630da761d 100644 --- a/app/Providers/FortifyServiceProvider.php +++ b/app/Providers/FortifyServiceProvider.php @@ -31,7 +31,7 @@ public function toResponse($request) { // First user (root) will be redirected to /settings instead of / on registration. if ($request->user()->currentTeam->id === 0) { - return redirect()->route('settings.configuration'); + return redirect()->route('settings.index'); } return redirect(RouteServiceProvider::HOME); } diff --git a/resources/views/auth/force-password-reset.blade.php b/resources/views/auth/force-password-reset.blade.php deleted file mode 100644 index df1f415f6..000000000 --- a/resources/views/auth/force-password-reset.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/resources/views/components/applications/navbar.blade.php b/resources/views/components/applications/navbar.blade.php index fd01ae474..db69feb6b 100644 --- a/resources/views/components/applications/navbar.blade.php +++ b/resources/views/components/applications/navbar.blade.php @@ -13,8 +13,8 @@ href="{{ route('project.application.logs', $parameters) }}"> - + diff --git a/resources/views/components/databases/navbar.blade.php b/resources/views/components/databases/navbar.blade.php index 8774fa1df..9f3dfad3b 100644 --- a/resources/views/components/databases/navbar.blade.php +++ b/resources/views/components/databases/navbar.blade.php @@ -16,8 +16,8 @@ $database->getMorphClass() === 'App\Models\StandaloneMongodb' || $database->getMorphClass() === 'App\Models\StandaloneMysql' || $database->getMorphClass() === 'App\Models\StandaloneMariadb') - + @endif diff --git a/resources/views/components/resources/breadcrumbs.blade.php b/resources/views/components/resources/breadcrumbs.blade.php index b7e24eb61..5b529e7a2 100644 --- a/resources/views/components/resources/breadcrumbs.blade.php +++ b/resources/views/components/resources/breadcrumbs.blade.php @@ -14,7 +14,7 @@ clip-rule="evenodd"> {{ $this->parameters['environment_name'] }} + href="{{ route('project.resource.index', ['environment_name' => $this->parameters['environment_name'], 'project_uuid' => $this->parameters['project_uuid']]) }}">{{ $this->parameters['environment_name'] }}
  • diff --git a/resources/views/components/settings/navbar.blade.php b/resources/views/components/settings/navbar.blade.php index a4839cab3..93625efd9 100644 --- a/resources/views/components/settings/navbar.blade.php +++ b/resources/views/components/settings/navbar.blade.php @@ -2,8 +2,8 @@

    Settings

    Instance wide settings for Coolify.
  • diff --git a/resources/views/projects.blade.php b/resources/views/livewire/project/index.blade.php similarity index 99% rename from resources/views/projects.blade.php rename to resources/views/livewire/project/index.blade.php index 387750b6b..4e3f28c9f 100644 --- a/resources/views/projects.blade.php +++ b/resources/views/livewire/project/index.blade.php @@ -1,4 +1,4 @@ - +

    Projects

    @if ($servers > 0) @@ -51,4 +51,4 @@ function goto(uuid) { }
    - +
    diff --git a/resources/views/livewire/project/resource/create.blade.php b/resources/views/livewire/project/resource/create.blade.php new file mode 100644 index 000000000..efbdd3753 --- /dev/null +++ b/resources/views/livewire/project/resource/create.blade.php @@ -0,0 +1,17 @@ +
    + @if ($type === 'public') + + @elseif ($type === 'private-gh-app') + + @elseif ($type === 'private-deploy-key') + + @elseif ($type === 'dockerfile') + + @elseif ($type === 'docker-compose-empty') + + @elseif ($type === 'docker-image') + + @else + + @endif +
    diff --git a/resources/views/livewire/project/resource/index.blade.php b/resources/views/livewire/project/resource/index.blade.php new file mode 100644 index 000000000..a1ff05693 --- /dev/null +++ b/resources/views/livewire/project/resource/index.blade.php @@ -0,0 +1,97 @@ +
    +
    +
    +

    Resources

    + @if ($environment->isEmpty()) + + Clone + + + @else + + + New + + Clone + + @endif +
    + +
    + @if ($environment->isEmpty()) + + Add New Resource + @endif + +
    diff --git a/resources/views/livewire/project/service/configuration.blade.php b/resources/views/livewire/project/service/configuration.blade.php new file mode 100644 index 000000000..c02a2ea05 --- /dev/null +++ b/resources/views/livewire/project/service/configuration.blade.php @@ -0,0 +1,169 @@ +
    + +
    + +
    +
    + +
    + @foreach ($applications as $application) +
    Str::of( + $application->status)->contains(['exited']), + 'border-l border-dashed border-success' => Str::of( + $application->status)->contains(['running']), + 'border-l border-dashed border-warning' => Str::of( + $application->status)->contains(['starting']), + 'flex gap-2 box-without-bg bg-coolgray-100 hover:text-neutral-300 group', + ])> +
    +
    +
    + @if ($application->human_name) + {{ Str::headline($application->human_name) }} + @else + {{ Str::headline($application->name) }} + @endif + ({{ $application->image }}) +
    + @if ($application->configuration_required) + (configuration required) + @endif + @if ($application->description) + {{ Str::limit($application->description, 60) }} + @endif + @if ($application->fqdn) + {{ Str::limit($application->fqdn, 60) }} + @endif +
    {{ $application->status }}
    +
    + +
    +
    + @endforeach + @foreach ($databases as $database) +
    Str::of( + $database->status)->contains(['exited']), + 'border-l border-dashed border-success' => Str::of( + $database->status)->contains(['running']), + 'border-l border-dashed border-warning' => Str::of( + $database->status)->contains(['restarting']), + 'flex gap-2 box-without-bg bg-coolgray-100 hover:text-neutral-300 group', + ])> + + +
    +
    +
    + @if ($database->human_name) + {{ Str::headline($database->human_name) }} + @else + {{ Str::headline($database->name) }} + @endif + ({{ $database->image }}) +
    + @if ($database->configuration_required) + (configuration required) + @endif + @if ($database->description) + {{ Str::limit($database->description, 60) }} + @endif +
    {{ $database->status }}
    +
    + +
    +
    + @endforeach +
    +
    +
    +
    +

    Storages

    +
    +
    Persistent storage to preserve data between deployments.
    + Please modify storage layout in your Docker Compose file. + @foreach ($applications as $application) + + @endforeach + @foreach ($databases as $database) + + @endforeach +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    + +
    +
    +
    +
    diff --git a/resources/views/livewire/project/service/index.blade.php b/resources/views/livewire/project/service/index.blade.php index 5f4363b31..15e9b9d21 100644 --- a/resources/views/livewire/project/service/index.blade.php +++ b/resources/views/livewire/project/service/index.blade.php @@ -1,169 +1,62 @@ -
    +
    -
    - Documentation - Service Stack - Execute Command - Logs +
    + + + + General Storages - Webhooks - - Environment - Variables - Danger Zone + @click.prevent="activeTab = 'storages'; window.location.hash = 'storages'; if(window.location.search) window.location.search = ''" + href="#">Storages + @if ( + $serviceDatabase?->databaseType() === 'standalone-mysql' || + $serviceDatabase?->databaseType() === 'standalone-postgresql' || + $serviceDatabase?->databaseType() === 'standalone-mariadb') + Backups + @endif
    -
    - -
    - @foreach ($applications as $application) -
    Str::of( - $application->status)->contains(['exited']), - 'border-l border-dashed border-success' => Str::of( - $application->status)->contains(['running']), - 'border-l border-dashed border-warning' => Str::of( - $application->status)->contains(['starting']), - 'flex gap-2 box-without-bg bg-coolgray-100 hover:text-neutral-300 group', - ])> -
    -
    -
    - @if ($application->human_name) - {{ Str::headline($application->human_name) }} - @else - {{ Str::headline($application->name) }} - @endif - ({{ $application->image }}) -
    - @if ($application->configuration_required) - (configuration required) - @endif - @if ($application->description) - {{ Str::limit($application->description, 60) }} - @endif - @if ($application->fqdn) - {{ Str::limit($application->fqdn, 60) }} - @endif -
    {{ $application->status }}
    -
    - -
    -
    - @endforeach - @foreach ($databases as $database) -
    Str::of( - $database->status)->contains(['exited']), - 'border-l border-dashed border-success' => Str::of( - $database->status)->contains(['running']), - 'border-l border-dashed border-warning' => Str::of( - $database->status)->contains(['restarting']), - 'flex gap-2 box-without-bg bg-coolgray-100 hover:text-neutral-300 group', - ])> - - -
    -
    -
    - @if ($database->human_name) - {{ Str::headline($database->human_name) }} - @else - {{ Str::headline($database->name) }} - @endif - ({{ $database->image }}) -
    - @if ($database->configuration_required) - (configuration required) - @endif - @if ($database->description) - {{ Str::limit($database->description, 60) }} - @endif -
    {{ $database->status }}
    -
    - -
    -
    - @endforeach + @isset($serviceApplication) +
    +
    -
    -
    -
    -

    Storages

    +
    +
    +

    Storages

    +
    +
    Persistent storage to preserve data between deployments.
    + Please modify storage layout in your Docker Compose file. +
    -
    Persistent storage to preserve data between deployments.
    - Please modify storage layout in your Docker Compose file. - @foreach ($applications as $application) - - @endforeach - @foreach ($databases as $database) - - @endforeach -
    -
    - -
    -
    - -
    -
    - -
    -
    -
    - + @endisset + @isset($serviceDatabase) +
    +
    -
    -
    - -
    +
    +
    +

    Storages

    +
    +
    Persistent storage to preserve data between deployments.
    + Please modify storage layout in your Docker Compose file. + +
    +
    +
    +

    Scheduled Backups

    + + Add +
    + + +
    + @endisset
    diff --git a/resources/views/livewire/project/service/show.blade.php b/resources/views/livewire/project/service/show.blade.php deleted file mode 100644 index 15e9b9d21..000000000 --- a/resources/views/livewire/project/service/show.blade.php +++ /dev/null @@ -1,62 +0,0 @@ -
    - -
    -
    - - - - General - Storages - - @if ( - $serviceDatabase?->databaseType() === 'standalone-mysql' || - $serviceDatabase?->databaseType() === 'standalone-postgresql' || - $serviceDatabase?->databaseType() === 'standalone-mariadb') - Backups - @endif -
    -
    - @isset($serviceApplication) -
    - -
    -
    -
    -

    Storages

    -
    -
    Persistent storage to preserve data between deployments.
    - Please modify storage layout in your Docker Compose file. - -
    - @endisset - @isset($serviceDatabase) -
    - -
    -
    -
    -

    Storages

    -
    -
    Persistent storage to preserve data between deployments.
    - Please modify storage layout in your Docker Compose file. - -
    -
    -
    -

    Scheduled Backups

    - + Add -
    - - -
    - @endisset -
    -
    -
    diff --git a/resources/views/project/show.blade.php b/resources/views/livewire/project/show.blade.php similarity index 95% rename from resources/views/project/show.blade.php rename to resources/views/livewire/project/show.blade.php index 98da15b32..319da2b71 100644 --- a/resources/views/project/show.blade.php +++ b/resources/views/livewire/project/show.blade.php @@ -1,4 +1,4 @@ - +
    diff --git a/resources/views/livewire/private-key/create.blade.php b/resources/views/livewire/security/private-key/create.blade.php similarity index 86% rename from resources/views/livewire/private-key/create.blade.php rename to resources/views/livewire/security/private-key/create.blade.php index 17d054945..10ef5185d 100644 --- a/resources/views/livewire/private-key/create.blade.php +++ b/resources/views/livewire/security/private-key/create.blade.php @@ -1,4 +1,6 @@
    +

    Create a new Private Key

    +
    Private Keys are used to connect to your servers without passwords.
    Generate new SSH key for me
    diff --git a/resources/views/livewire/security/private-key/show.blade.php b/resources/views/livewire/security/private-key/show.blade.php new file mode 100644 index 000000000..43bcd95f6 --- /dev/null +++ b/resources/views/livewire/security/private-key/show.blade.php @@ -0,0 +1,54 @@ +
    + +
    + + +

    This private key will be deleted. It is not reversible.
    Please think again.

    +
    +
    + +
    +

    Private Key

    + + Save + + @if ($private_key->id > 0) + + Delete + + @endif +
    + + +
    +
    +
    Public Key
    +
    + +
    +
    Private Key *
    +
    + Edit +
    +
    + Hide +
    +
    + @if ($private_key->is_git_related) +
    + +
    + @endif +
    + +
    +
    + +
    +
    + +
    +
    diff --git a/resources/views/livewire/server/all.blade.php b/resources/views/livewire/server/index.blade.php similarity index 100% rename from resources/views/livewire/server/all.blade.php rename to resources/views/livewire/server/index.blade.php diff --git a/resources/views/livewire/server/show-private-key.blade.php b/resources/views/livewire/server/show-private-key.blade.php index a9bcde0bc..c10e440b8 100644 --- a/resources/views/livewire/server/show-private-key.blade.php +++ b/resources/views/livewire/server/show-private-key.blade.php @@ -1,7 +1,7 @@

    Private Key

    -
    + Add a new Private Key diff --git a/resources/views/livewire/settings/index.blade.php b/resources/views/livewire/settings/index.blade.php new file mode 100644 index 000000000..7491d8d1c --- /dev/null +++ b/resources/views/livewire/settings/index.blade.php @@ -0,0 +1,25 @@ +
    + +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    diff --git a/resources/views/livewire/settings/license.blade.php b/resources/views/livewire/settings/license.blade.php new file mode 100644 index 000000000..31dc0fb94 --- /dev/null +++ b/resources/views/livewire/settings/license.blade.php @@ -0,0 +1,28 @@ +
    + +

    Resale License

    +
    +
    + @if ($settings->is_resale_license_active) +
    License is active
    + @else +
    License is not active
    + @endif +
    +
    + + +
    +
    + + Check License + +
    + @if (session()->has('error')) +
    + {!! session('error') !!} +
    + @endif +
    +
    diff --git a/resources/views/livewire/subscription/show.blade.php b/resources/views/livewire/subscription/index.blade.php similarity index 100% rename from resources/views/livewire/subscription/show.blade.php rename to resources/views/livewire/subscription/index.blade.php diff --git a/resources/views/livewire/team/create.blade.php b/resources/views/livewire/team/create.blade.php index e90ae3040..d6afcbbab 100644 --- a/resources/views/livewire/team/create.blade.php +++ b/resources/views/livewire/team/create.blade.php @@ -1,7 +1,11 @@ -
    - - - - Save Team - - +
    +

    New Team

    +
    Add a new team
    +
    + + + + Save Team + + +
    diff --git a/resources/views/livewire/team/delete.blade.php b/resources/views/livewire/team/delete.blade.php deleted file mode 100644 index 4e4bd5977..000000000 --- a/resources/views/livewire/team/delete.blade.php +++ /dev/null @@ -1,60 +0,0 @@ -
    - - -

    This team be deleted. It is not reversible.
    Please think again.

    -
    -
    -

    Danger Zone

    -
    Woah. I hope you know what are you doing.
    -

    Delete Team

    - @if (session('currentTeam.id') === 0) -
    This is the default team. You can't delete it.
    - @elseif(auth()->user()->teams()->get()->count() === 1) -
    You can't delete your last team.
    - @elseif(currentTeam()->subscription && currentTeam()->subscription?->lemon_status !== 'cancelled') -
    Please cancel your subscription before delete this team (Manage My Subscription).
    - @else - @if (currentTeam()->isEmpty()) -
    This will delete your team. Beware! There is no coming back!
    - - Delete - - @else -
    -
    You need to delete the following resources to be able to delete the team:
    - @if (currentTeam()->projects()->count() > 0) -

    Projects:

    -
      - @foreach (currentTeam()->projects as $resource) -
    • {{ $resource->name }}
    • - @endforeach -
    - @endif - @if (currentTeam()->servers()->count() > 0) -

    Servers:

    -
      - @foreach (currentTeam()->servers as $resource) -
    • {{ $resource->name }}
    • - @endforeach -
    - @endif - @if (currentTeam()->privateKeys()->count() > 0) -

    Private Keys:

    -
      - @foreach (currentTeam()->privateKeys as $resource) -
    • {{ $resource->name }}
    • - @endforeach -
    - @endif - @if (currentTeam()->sources()->count() > 0) -

    Sources:

    -
      - @foreach (currentTeam()->sources() as $resource) -
    • {{ $resource->name }}
    • - @endforeach -
    - @endif - @endif - @endif - -
    diff --git a/resources/views/livewire/team/form.blade.php b/resources/views/livewire/team/form.blade.php deleted file mode 100644 index c484cb358..000000000 --- a/resources/views/livewire/team/form.blade.php +++ /dev/null @@ -1,12 +0,0 @@ -
    -
    -

    General

    - - Save - -
    -
    - - -
    -
    diff --git a/resources/views/livewire/team/index.blade.php b/resources/views/livewire/team/index.blade.php new file mode 100644 index 000000000..20e164193 --- /dev/null +++ b/resources/views/livewire/team/index.blade.php @@ -0,0 +1,89 @@ +
    + + +
    +
    +

    General

    + + Save + +
    +
    + + +
    +
    + + @if (isCloud()) +
    +

    Subscription

    + @if (data_get(currentTeam(), 'subscription')) + + @else + Subscribe Now + + @endif + +
    + @endif +
    + + +

    This team be deleted. It is not reversible.
    Please think again.

    +
    +
    +

    Danger Zone

    +
    Woah. I hope you know what are you doing.
    +

    Delete Team

    + @if (session('currentTeam.id') === 0) +
    This is the default team. You can't delete it.
    + @elseif(auth()->user()->teams()->get()->count() === 1) +
    You can't delete your last team.
    + @elseif(currentTeam()->subscription && currentTeam()->subscription?->lemon_status !== 'cancelled') +
    Please cancel your subscription before delete this team (Manage My Subscription).
    + @else + @if (currentTeam()->isEmpty()) +
    This will delete your team. Beware! There is no coming back!
    + + Delete + + @else +
    +
    You need to delete the following resources to be able to delete the team:
    + @if (currentTeam()->projects()->count() > 0) +

    Projects:

    +
      + @foreach (currentTeam()->projects as $resource) +
    • {{ $resource->name }}
    • + @endforeach +
    + @endif + @if (currentTeam()->servers()->count() > 0) +

    Servers:

    +
      + @foreach (currentTeam()->servers as $resource) +
    • {{ $resource->name }}
    • + @endforeach +
    + @endif + @if (currentTeam()->privateKeys()->count() > 0) +

    Private Keys:

    +
      + @foreach (currentTeam()->privateKeys as $resource) +
    • {{ $resource->name }}
    • + @endforeach +
    + @endif + @if (currentTeam()->sources()->count() > 0) +

    Sources:

    +
      + @foreach (currentTeam()->sources() as $resource) +
    • {{ $resource->name }}
    • + @endforeach +
    + @endif + @endif + @endif +
    +
    diff --git a/resources/views/team/members.blade.php b/resources/views/livewire/team/member/index.blade.php similarity index 98% rename from resources/views/team/members.blade.php rename to resources/views/livewire/team/member/index.blade.php index 60839bcc8..72d7864c6 100644 --- a/resources/views/team/members.blade.php +++ b/resources/views/livewire/team/member/index.blade.php @@ -1,4 +1,4 @@ - +

    Members

    @@ -41,4 +41,4 @@ class="underline text-warning">Transactional
    @endif - +
    diff --git a/resources/views/team/notifications.blade.php b/resources/views/livewire/team/notification/index.blade.php similarity index 98% rename from resources/views/team/notifications.blade.php rename to resources/views/livewire/team/notification/index.blade.php index a86db9ad2..26270b480 100644 --- a/resources/views/team/notifications.blade.php +++ b/resources/views/livewire/team/notification/index.blade.php @@ -1,4 +1,4 @@ - +

    Notifications

    @@ -21,4 +21,4 @@
    -
    +
    diff --git a/resources/views/team/storages/all.blade.php b/resources/views/livewire/team/storage/index.blade.php similarity index 98% rename from resources/views/team/storages/all.blade.php rename to resources/views/livewire/team/storage/index.blade.php index 0ac2051b3..c64ff050f 100644 --- a/resources/views/team/storages/all.blade.php +++ b/resources/views/livewire/team/storage/index.blade.php @@ -1,4 +1,4 @@ - +
    @@ -30,4 +30,4 @@ function goto(uuid) { window.location.href = '/team/storages/' + uuid; } - +
    diff --git a/resources/views/team/storages/show.blade.php b/resources/views/livewire/team/storage/show.blade.php similarity index 85% rename from resources/views/team/storages/show.blade.php rename to resources/views/livewire/team/storage/show.blade.php index 88f8780d6..83fa95a08 100644 --- a/resources/views/team/storages/show.blade.php +++ b/resources/views/livewire/team/storage/show.blade.php @@ -1,6 +1,6 @@ - +
    - +
    diff --git a/resources/views/livewire/team/storages/create.blade.php b/resources/views/livewire/team/storages/create.blade.php new file mode 100644 index 000000000..379e555e9 --- /dev/null +++ b/resources/views/livewire/team/storages/create.blade.php @@ -0,0 +1,3 @@ +
    + {{-- If you look to others for fulfillment, you will never truly be fulfilled. --}} +
    diff --git a/resources/views/project/edit.blade.php b/resources/views/project/edit.blade.php deleted file mode 100644 index 14746275f..000000000 --- a/resources/views/project/edit.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/resources/views/project/resources.blade.php b/resources/views/project/resources.blade.php index 8e97bf324..2b5e6fcd1 100644 --- a/resources/views/project/resources.blade.php +++ b/resources/views/project/resources.blade.php @@ -4,16 +4,16 @@

    Resources

    @if ($environment->isEmpty()) + href="{{ route('project.clone-me', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => request()->route('environment_name')]) }}"> Clone @else - + New + href="{{ route('project.clone-me', ['project_uuid' => data_get($project, 'uuid'), 'environment_name' => request()->route('environment_name')]) }}"> Clone @endif @@ -34,14 +34,14 @@ class="font-normal text-white normal-case border-none rounded hover:no-underline clip-rule="evenodd"> {{ request()->route('environment_name') }} + href="{{ route('project.resource.index', ['environment_name' => request()->route('environment_name'), 'project_uuid' => request()->route('project_uuid')]) }}">{{ request()->route('environment_name') }}
  • @if ($environment->isEmpty()) - + Add New Resource @endif
    diff --git a/resources/views/security/private-key/index.blade.php b/resources/views/security/private-key/index.blade.php index 6e7190c34..64687d149 100644 --- a/resources/views/security/private-key/index.blade.php +++ b/resources/views/security/private-key/index.blade.php @@ -2,11 +2,11 @@

    Private Keys

    - + Add + + Add
    @forelse ($privateKeys as $key) -
    {{ $key->name }}
    diff --git a/resources/views/security/private-key/new.blade.php b/resources/views/security/private-key/new.blade.php deleted file mode 100644 index b5e59eea2..000000000 --- a/resources/views/security/private-key/new.blade.php +++ /dev/null @@ -1,5 +0,0 @@ - -

    Create a new Private Key

    -
    Private Keys are used to connect to your servers without passwords.
    - -
    diff --git a/resources/views/security/private-key/show.blade.php b/resources/views/security/private-key/show.blade.php deleted file mode 100644 index 82cf634f0..000000000 --- a/resources/views/security/private-key/show.blade.php +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/resources/views/team/create.blade.php b/resources/views/team/create.blade.php deleted file mode 100644 index a64050849..000000000 --- a/resources/views/team/create.blade.php +++ /dev/null @@ -1,5 +0,0 @@ - -

    New Team

    -
    Add a new team
    - -
    diff --git a/resources/views/team/index.blade.php b/resources/views/team/index.blade.php deleted file mode 100644 index fa732010e..000000000 --- a/resources/views/team/index.blade.php +++ /dev/null @@ -1,18 +0,0 @@ - - - - @if (isCloud()) -
    - @endif - - diff --git a/resources/views/team/storages/create.blade.php b/resources/views/team/storages/create.blade.php deleted file mode 100644 index 711c521e3..000000000 --- a/resources/views/team/storages/create.blade.php +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/routes/web.php b/routes/web.php index ffd907344..b25ee3819 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,102 +1,86 @@ name('dev.compose'); } -Route::get('/api/v1/test/realtime', function () { - if (auth()->user()?->currentTeam()->id !== 0) { - return redirect(RouteServiceProvider::HOME); - } - TestEvent::dispatch('asd'); - return 'Look at your other tab.'; -})->middleware('auth'); - - -Route::post('/forgot-password', function (Request $request) { - if (is_transactional_emails_active()) { - $arrayOfRequest = $request->only(Fortify::email()); - $request->merge([ - 'email' => Str::lower($arrayOfRequest['email']), - ]); - $type = set_transanctional_email_settings(); - if (!$type) { - return response()->json(['message' => 'Transactional emails are not active'], 400); - } - $request->validate([Fortify::email() => 'required|email']); - $status = Password::broker(config('fortify.passwords'))->sendResetLink( - $request->only(Fortify::email()) - ); - if ($status == Password::RESET_LINK_SENT) { - return app(SuccessfulPasswordResetLinkRequestResponse::class, ['status' => $status]); - } - if ($status == Password::RESET_THROTTLED) { - return response('Already requested a password reset in the past minutes.', 400); - } - return app(FailedPasswordResetLinkRequestResponse::class, ['status' => $status]); - } - return response()->json(['message' => 'Transactional emails are not active'], 400); -})->name('password.forgot'); - - +Route::post('/forgot-password', [Controller::class, 'forgot_password'])->name('password.forgot'); +Route::get('/api/v1/test/realtime', [Controller::class, 'realtime_test'])->middleware('auth'); Route::get('/waitlist', WaitlistIndex::class)->name('waitlist.index'); - -Route::get('/verify', function () { - return view('auth.verify-email'); -})->middleware('auth')->name('verify.email'); - -Route::get('/email/verify/{id}/{hash}', function (EmailVerificationRequest $request) { - $request->fulfill(); - send_internal_notification("User {$request->user()->name} verified their email address."); - return redirect(RouteServiceProvider::HOME); -})->middleware(['auth'])->name('verify.verify'); - +Route::get('/verify', [Controller::class, 'verify'])->middleware('auth')->name('verify.email'); +Route::get('/email/verify/{id}/{hash}', [Controller::class, 'email_verify'])->middleware(['auth'])->name('verify.verify'); Route::middleware(['throttle:login'])->group(function () { Route::get('/auth/link', [Controller::class, 'link'])->name('auth.link'); }); + Route::prefix('magic')->middleware(['auth'])->group(function () { Route::get('/servers', [MagicController::class, 'servers']); Route::get('/destinations', [MagicController::class, 'destinations']); @@ -107,88 +91,90 @@ }); Route::middleware(['auth', 'verified'])->group(function () { - Route::get('/projects', [ProjectController::class, 'all'])->name('projects'); - Route::get('/project/{project_uuid}', [ProjectController::class, 'show'])->name('project.show'); - Route::get('/project/{project_uuid}/edit', [ProjectController::class, 'edit'])->name('project.edit'); - Route::get('/project/{project_uuid}/{environment_name}/clone', CloneProject::class)->name('project.clone'); + Route::middleware(['throttle:force-password-reset'])->group(function () { + Route::get('/force-password-reset', ForcePasswordReset::class)->name('auth.force-password-reset'); + }); - Route::get('/project/{project_uuid}/{environment_name}/new', [ProjectController::class, 'new'])->name('project.resources.new'); - Route::get('/project/{project_uuid}/{environment_name}', [ProjectController::class, 'resources'])->name('project.resources'); - Route::get('/project/{project_uuid}/{environment_name}/edit', EnvironmentEdit::class)->name('project.environment.edit'); - - // Applications - Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}', ApplicationConfiguration::class)->name('project.application.configuration'); - - Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}/deployment', [ApplicationController::class, 'deployments'])->name('project.application.deployments'); - Route::get( - '/project/{project_uuid}/{environment_name}/application/{application_uuid}/deployment/{deployment_uuid}', - [ApplicationController::class, 'deployment'] - )->name('project.application.deployment'); - - Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}/logs', Logs::class)->name('project.application.logs'); - Route::get('/project/{project_uuid}/{environment_name}/application/{application_uuid}/command', ExecuteContainerCommand::class)->name('project.application.command'); - - // Databases - Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}', [DatabaseController::class, 'configuration'])->name('project.database.configuration'); - Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}/backups', [DatabaseController::class, 'backups'])->name('project.database.backups.all'); - Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}/backups/{backup_uuid}', [DatabaseController::class, 'executions'])->name('project.database.backups.executions'); - Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}/logs', Logs::class)->name('project.database.logs'); - Route::get('/project/{project_uuid}/{environment_name}/database/{database_uuid}/command', ExecuteContainerCommand::class)->name('project.database.command'); - - - // Services - Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}', ServiceIndex::class)->name('project.service.configuration'); - Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}/{service_name}', ServiceShow::class)->name('project.service.show'); - Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}/command', ExecuteContainerCommand::class)->name('project.service.command'); -}); - -Route::middleware(['auth'])->group(function () { - Route::get('/servers', All::class)->name('server.all'); - Route::get('/server/new', Create::class)->name('server.create'); - Route::get('/server/{server_uuid}', Show::class)->name('server.show'); - Route::get('/server/{server_uuid}/proxy', ProxyShow::class)->name('server.proxy'); - Route::get('/server/{server_uuid}/proxy/logs', ProxyLogs::class)->name('server.proxy.logs'); - Route::get('/server/{server_uuid}/private-key', PrivateKeyShow::class)->name('server.private-key'); - Route::get('/server/{server_uuid}/destinations', DestinationShow::class)->name('server.destinations'); - Route::get('/server/{server_uuid}/log-drains', LogDrains::class)->name('server.log-drains'); -}); - - -Route::middleware(['auth', 'verified'])->group(function () { Route::get('/', Dashboard::class)->name('dashboard'); Route::get('/boarding', BoardingIndex::class)->name('boarding'); - Route::middleware(['throttle:force-password-reset'])->group(function () { - Route::get('/force-password-reset', [Controller::class, 'force_passoword_reset'])->name('auth.force-password-reset'); - }); - Route::get('/subscription', SubscriptionShow::class)->name('subscription.index'); - Route::get('/settings', [Controller::class, 'settings'])->name('settings.configuration'); - Route::get('/settings/license', [Controller::class, 'license'])->name('settings.license'); - Route::get('/profile', fn () => view('profile', ['request' => request()]))->name('profile'); - Route::get('/team', [Controller::class, 'team'])->name('team.index'); - Route::get('/team/new', fn () => view('team.create'))->name('team.create'); - Route::get('/team/notifications', fn () => view('team.notifications'))->name('team.notifications'); - Route::get('/team/storages', [Controller::class, 'storages'])->name('team.storages.all'); - Route::get('/team/storages/new', fn () => view('team.storages.create'))->name('team.storages.new'); - Route::get('/team/storages/{storage_uuid}', [Controller::class, 'storages_show'])->name('team.storages.show'); - Route::get('/team/members', [Controller::class, 'members'])->name('team.members'); - Route::get('/command-center', fn () => view('command-center', ['servers' => Server::isReachable()->get()]))->name('command-center'); - Route::get('/invitations/{uuid}', [Controller::class, 'acceptInvitation'])->name('team.invitation.accept'); - Route::get('/invitations/{uuid}/revoke', [Controller::class, 'revokeInvitation'])->name('team.invitation.revoke'); -}); -Route::middleware(['auth'])->group(function () { - Route::get('/security', fn () => view('security.index'))->name('security.index'); + Route::get('/subscription', SubscriptionIndex::class)->name('subscription.index'); + + Route::get('/settings', SettingsIndex::class)->name('settings.index'); + Route::get('/settings/license', SettingsLicense::class)->name('settings.license'); + + Route::get('/profile', ProfileIndex::class)->name('profile'); + + Route::prefix('team')->group(function () { + Route::get('/', TeamIndex::class)->name('team.index'); + Route::get('/new', TeamCreate::class)->name('team.create'); + Route::get('/members', TeamMemberIndex::class)->name('team.member.index'); + Route::get('/notifications', TeamNotificationIndex::class)->name('team.notification.index'); + Route::get('/storages', TeamStorageIndex::class)->name('team.storage.index'); + Route::get('/storages/new', TeamStorageCreate::class)->name('team.storage.create'); + Route::get('/storages/{storage_uuid}', TeamStorageShow::class)->name('team.storage.show'); + }); + + Route::get('/command-center', CommandCenterIndex::class)->name('command-center'); + + Route::prefix('invitations')->group(function () { + Route::get('/{uuid}', [Controller::class, 'accept_invitation'])->name('team.invitation.accept'); + Route::get('/{uuid}/revoke', [Controller::class, 'revoke_invitation'])->name('team.invitation.revoke'); + }); + + Route::get('/projects', ProjectIndex::class)->name('project.index'); + Route::prefix('project/{project_uuid}')->group(function () { + Route::get('/', ProjectShow::class)->name('project.show'); + Route::get('/edit', ProjectEdit::class)->name('project.edit'); + }); + Route::prefix('project/{project_uuid}/{environment_name}')->group(function () { + Route::get('/', ResourceIndex::class)->name('project.resource.index'); + Route::get('/clone', ProjectCloneMe::class)->name('project.clone-me'); + Route::get('/new', ResourceCreate::class)->name('project.resource.create'); + Route::get('/edit', EnvironmentEdit::class)->name('project.environment.edit'); + }); + Route::prefix('project/{project_uuid}/{environment_name}/application/{application_uuid}')->group(function () { + Route::get('/', ApplicationConfiguration::class)->name('project.application.configuration'); + Route::get('/deployment', DeploymentIndex::class)->name('project.application.deployment.index'); + Route::get('/deployment/{deployment_uuid}', DeploymentShow::class)->name('project.application.deployment.show'); + Route::get('/logs', Logs::class)->name('project.application.logs'); + Route::get('/command', ExecuteContainerCommand::class)->name('project.application.command'); + }); + Route::prefix('project/{project_uuid}/{environment_name}/database/{database_uuid}')->group(function () { + Route::get('/', DatabaseConfiguration::class)->name('project.database.configuration'); + Route::get('/logs', Logs::class)->name('project.database.logs'); + Route::get('/command', ExecuteContainerCommand::class)->name('project.database.command'); + Route::get('/backups', DatabaseBackupIndex::class)->name('project.database.backup.index'); + Route::get('/backups/{backup_uuid}', DatabaseBackupExecution::class)->name('project.database.backup.execution'); + }); + Route::prefix('project/{project_uuid}/{environment_name}/service/{service_uuid}')->group(function () { + Route::get('/', ServiceConfiguration::class)->name('project.service.configuration'); + Route::get('/{service_name}', ServiceIndex::class)->name('project.service.index'); + Route::get('/command', ExecuteContainerCommand::class)->name('project.service.command'); + }); + + Route::get('/servers', ServerIndex::class)->name('server.index'); + Route::get('/server/new', ServerCreate::class)->name('server.create'); + + Route::prefix('server/{server_uuid}')->group(function () { + Route::get('/', ServerShow::class)->name('server.show'); + Route::get('/proxy', ProxyShow::class)->name('server.proxy'); + Route::get('/proxy/logs', ProxyLogs::class)->name('server.proxy.logs'); + Route::get('/private-key', PrivateKeyShow::class)->name('server.private-key'); + Route::get('/destinations', DestinationShow::class)->name('server.destinations'); + Route::get('/log-drains', LogDrains::class)->name('server.log-drains'); + }); + + // Route::get('/security', fn () => view('security.index'))->name('security.index'); Route::get('/security/private-key', fn () => view('security.private-key.index', [ 'privateKeys' => PrivateKey::ownedByCurrentTeam(['name', 'uuid', 'is_git_related'])->get() ]))->name('security.private-key.index'); - Route::get('/security/private-key/new', fn () => view('security.private-key.new'))->name('security.private-key.new'); - Route::get('/security/private-key/{private_key_uuid}', fn () => view('security.private-key.show', [ - 'private_key' => PrivateKey::ownedByCurrentTeam(['name', 'description', 'private_key', 'is_git_related'])->whereUuid(request()->private_key_uuid)->firstOrFail() - ]))->name('security.private-key.show'); + Route::get('/security/private-key/new', SecurityPrivateKeyCreate::class)->name('security.private-key.create'); + Route::get('/security/private-key/{private_key_uuid}', SecurityPrivateKeyShow::class)->name('security.private-key.show'); + Route::get('/security/api-tokens', ApiTokens::class)->name('security.api-tokens'); }); - Route::middleware(['auth'])->group(function () { Route::get('/source/new', fn () => view('source.new'))->name('source.new'); Route::get('/sources', function () { From b6745c691b767d63791cb4af643449243f043558 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 8 Jan 2024 16:33:34 +0100 Subject: [PATCH 04/15] fix: queue retry fix: nixpacks builds --- app/Jobs/ApplicationDeploymentJob.php | 112 ++++++++++++++++---------- config/queue.php | 2 +- 2 files changed, 72 insertions(+), 42 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 5ce4040e7..1fe0d54a3 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -30,6 +30,7 @@ use Symfony\Component\Yaml\Yaml; use Throwable; use Visus\Cuid2\Cuid2; +use Yosymfony\Toml\Toml; class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted { @@ -73,6 +74,8 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted private $env_args; private $docker_compose; private $docker_compose_base64; + private ?string $nixpacks_plan = null; + private ?string $nixpacks_type = null; private string $dockerfile_location = '/Dockerfile'; private string $docker_compose_location = '/docker-compose.yml'; private ?string $docker_compose_custom_start_command = null; @@ -170,7 +173,7 @@ public function handle(): void if ($containerName === 'coolify-proxy') { continue; } - if (preg_match('/-(\d{12})/',$containerName)) { + if (preg_match('/-(\d{12})/', $containerName)) { continue; } $containerIp = data_get($container, 'IPv4Address'); @@ -579,7 +582,7 @@ private function deploy_nixpacks_buildpack() $this->generate_nixpacks_confs(); $this->generate_compose_file(); $this->generate_build_env_variables(); - $this->add_build_env_variables_to_dockerfile(); + // $this->add_build_env_variables_to_dockerfile(); $this->build_image(); $this->rolling_update(); } @@ -866,24 +869,33 @@ private function cleanup_git() private function generate_nixpacks_confs() { $nixpacks_command = $this->nixpacks_build_cmd(); + ray($nixpacks_command); $this->execute_remote_command( [ "echo -n 'Generating nixpacks configuration with: $nixpacks_command'", ], - [executeInDocker($this->deployment_uuid, $nixpacks_command)], - [executeInDocker($this->deployment_uuid, "cp {$this->workdir}/.nixpacks/Dockerfile {$this->workdir}/Dockerfile")], - [executeInDocker($this->deployment_uuid, "rm -f {$this->workdir}/.nixpacks/Dockerfile")] + [executeInDocker($this->deployment_uuid, $nixpacks_command), "save" => "nixpacks_plan", "hidden" => true], + [executeInDocker($this->deployment_uuid, "nixpacks detect {$this->workdir}"), "save" => "nixpacks_type", "hidden" => true], ); + if ($this->saved_outputs->get('nixpacks_type')) { + $this->nixpacks_type = $this->saved_outputs->get('nixpacks_type'); + } + if ($this->saved_outputs->get('nixpacks_plan')) { + $this->nixpacks_plan = $this->saved_outputs->get('nixpacks_plan'); + if ($this->nixpacks_plan) { + $parsed = Toml::Parse($this->nixpacks_plan); + // Do any modifications here + $cmds = collect(data_get($parsed, 'phases.setup.cmds', [])); + data_set($parsed, 'phases.setup.cmds', $cmds); + $this->nixpacks_plan = json_encode($parsed); + } + } } private function nixpacks_build_cmd() { $this->generate_env_variables(); - // $cacheKey = $this->application->uuid; - // if ($this->pull_request_id !== 0) { - // $cacheKey = "{$this->application->uuid}-pr-{$this->pull_request_id}"; - // } - $nixpacks_command = "nixpacks build {$this->env_args} --no-error-without-start"; + $nixpacks_command = "nixpacks plan -f toml {$this->env_args}"; if ($this->application->build_command) { $nixpacks_command .= " --build-cmd \"{$this->application->build_command}\""; } @@ -893,7 +905,7 @@ private function nixpacks_build_cmd() if ($this->application->install_command) { $nixpacks_command .= " --install-cmd \"{$this->application->install_command}\""; } - $nixpacks_command .= " -o {$this->workdir} {$this->workdir}"; + $nixpacks_command .= " {$this->workdir}"; return $nixpacks_command; } @@ -904,10 +916,16 @@ private function generate_env_variables() foreach ($this->application->nixpacks_environment_variables as $env) { $this->env_args->push("--env {$env->key}={$env->value}"); } + foreach ($this->application->build_environment_variables as $env) { + $this->env_args->push("--env {$env->key}={$env->value}"); + } } else { foreach ($this->application->nixpacks_environment_variables_preview as $env) { $this->env_args->push("--env {$env->key}={$env->value}"); } + foreach ($this->application->build_environment_variables_preview as $env) { + $this->env_args->push("--env {$env->key}={$env->value}"); + } } $this->env_args = $this->env_args->implode(' '); @@ -1231,22 +1249,28 @@ private function build_image() }"); } else { if ($this->application->build_pack === 'nixpacks') { - $this->execute_remote_command( - [ - executeInDocker($this->deployment_uuid, "cp {$this->workdir}/Dockerfile {$this->workdir}/.nixpacks/Dockerfile") - ], - ); - } - if ($this->force_rebuild) { - $this->execute_remote_command([ - executeInDocker($this->deployment_uuid, "docker build --no-cache $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true - ]); + $this->nixpacks_plan = base64_encode($this->nixpacks_plan); + $this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d > {$this->workdir}/thegameplan.json"), "hidden" => true]); + if ($this->force_rebuild) { + $this->execute_remote_command([ + executeInDocker($this->deployment_uuid, "nixpacks build -c thegameplan.json --no-cache --no-error-without-start -n {$this->build_image_name} {$this->workdir}"), "hidden" => true + ]); + } else { + $this->execute_remote_command([ + executeInDocker($this->deployment_uuid, "nixpacks build -c thegameplan.json --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->build_image_name} {$this->workdir}"), "hidden" => true + ]); + } } else { - $this->execute_remote_command([ - executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true - ]); + if ($this->force_rebuild) { + $this->execute_remote_command([ + executeInDocker($this->deployment_uuid, "docker build --no-cache {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true + ]); + } else { + $this->execute_remote_command([ + executeInDocker($this->deployment_uuid, "docker build {$this->buildTarget} --network {$this->destination->network} -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->build_image_name {$this->workdir}"), "hidden" => true + ]); + } } - // } $dockerfile = base64_encode("FROM {$this->application->static_image} WORKDIR /usr/share/nginx/html/ @@ -1279,32 +1303,38 @@ private function build_image() executeInDocker($this->deployment_uuid, "echo '{$nginx_config}' | base64 -d > {$this->workdir}/nginx.conf") ], [ - executeInDocker($this->deployment_uuid, "docker build $this->addHosts --network host -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true + executeInDocker($this->deployment_uuid, "docker build {$this->addHosts} --network host -f {$this->workdir}/Dockerfile {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}"), "hidden" => true ] ); } else { // Pure Dockerfile based deployment if ($this->application->dockerfile) { $this->execute_remote_command([ - executeInDocker($this->deployment_uuid, "docker build --pull $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true + executeInDocker($this->deployment_uuid, "docker build --pull {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}"), "hidden" => true ]); } else { if ($this->application->build_pack === 'nixpacks') { - $this->execute_remote_command( - [ - executeInDocker($this->deployment_uuid, "cp {$this->workdir}/Dockerfile {$this->workdir}/.nixpacks/Dockerfile") - ], - ); - } - - if ($this->force_rebuild) { - $this->execute_remote_command([ - executeInDocker($this->deployment_uuid, "docker build --no-cache $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true - ]); + $this->nixpacks_plan = base64_encode($this->nixpacks_plan); + $this->execute_remote_command([executeInDocker($this->deployment_uuid, "echo '{$this->nixpacks_plan}' | base64 -d > {$this->workdir}/thegameplan.json"), "hidden" => true]); + if ($this->force_rebuild) { + $this->execute_remote_command([ + executeInDocker($this->deployment_uuid, "nixpacks build -c thegameplan.json --no-cache --no-error-without-start -n {$this->production_image_name} {$this->workdir}"), "hidden" => true + ]); + } else { + $this->execute_remote_command([ + executeInDocker($this->deployment_uuid, "nixpacks build -c thegameplan.json --cache-key '{$this->application->uuid}' --no-error-without-start -n {$this->production_image_name} {$this->workdir}"), "hidden" => true + ]); + } } else { - $this->execute_remote_command([ - executeInDocker($this->deployment_uuid, "docker build $this->buildTarget $this->addHosts --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t $this->production_image_name {$this->workdir}"), "hidden" => true - ]); + if ($this->force_rebuild) { + $this->execute_remote_command([ + executeInDocker($this->deployment_uuid, "docker build --no-cache {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}"), "hidden" => true + ]); + } else { + $this->execute_remote_command([ + executeInDocker($this->deployment_uuid, "docker build {$this->buildTarget} {$this->addHosts} --network host -f {$this->workdir}{$this->dockerfile_location} {$this->build_args} --progress plain -t {$this->production_image_name} {$this->workdir}"), "hidden" => true + ]); + } } } } diff --git a/config/queue.php b/config/queue.php index 29b79353a..2ef618584 100644 --- a/config/queue.php +++ b/config/queue.php @@ -65,7 +65,7 @@ 'driver' => 'redis', 'connection' => 'default', 'queue' => env('REDIS_QUEUE', 'default'), - 'retry_after' => 300, + 'retry_after' => 3600, 'block_for' => null, 'after_commit' => true, ], From 31e08a24c960cca1e6d9a235ae5d5254754c86a4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 08:42:37 +0100 Subject: [PATCH 05/15] fix: healthy status --- app/Jobs/ApplicationDeploymentJob.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 1fe0d54a3..ea5913847 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -679,7 +679,7 @@ private function health_check() "echo 'Attempt {$counter} of {$this->application->health_check_retries} | Healthcheck status: {$this->saved_outputs->get('health_check')}'" ], ); - if (Str::of($this->saved_outputs->get('health_check'))->contains('healthy')) { + if (Str::of($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'healthy') { $this->newVersionIsHealthy = true; $this->application->update(['status' => 'running']); $this->execute_remote_command( @@ -689,6 +689,10 @@ private function health_check() ); break; } + if (Str::of($this->saved_outputs->get('health_check'))->replace('"', '')->value() === 'unhealthy') { + $this->newVersionIsHealthy = false; + break; + } $counter++; sleep($this->application->health_check_interval); } From c9509ef6589f5f5001af1d89e11a9c3162fe5ab6 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 12:19:39 +0100 Subject: [PATCH 06/15] fix: show framework based notification in build logs --- app/Jobs/ApplicationDeploymentJob.php | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index ea5913847..c461c15f4 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -350,6 +350,9 @@ private function just_restart() $this->generate_image_names(); $this->check_image_locally_or_remotely(); if (str($this->saved_outputs->get('local_image_found'))->isNotEmpty()) { + $this->execute_remote_command([ + "echo 'Image found ({$this->production_image_name}) with the same Git Commit SHA. Restarting container.'", + ]); $this->create_workdir(); $this->generate_compose_file(); $this->rolling_update(); @@ -604,6 +607,24 @@ private function deploy_static_buildpack() $this->rolling_update(); } + private function framework_based_notification() + { + // Laravel old env variables + if ($this->pull_request_id === 0) { + $nixpacks_php_fallback_path = $this->application->environment_variables->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first(); + $nixpacks_php_root_dir = $this->application->environment_variables->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first(); + } else { + $nixpacks_php_fallback_path = $this->application->environment_variables_preview->where('key', 'NIXPACKS_PHP_FALLBACK_PATH')->first(); + $nixpacks_php_root_dir = $this->application->environment_variables_preview->where('key', 'NIXPACKS_PHP_ROOT_DIR')->first(); + } + if ($nixpacks_php_fallback_path?->value === '/index.php' && $nixpacks_php_root_dir?->value === '/app/public' && $this->newVersionIsHealthy === false) { + $this->execute_remote_command( + [ + "echo 'There was a change in how Laravel is deployed. Please update your environment variables to match the new deployment method. More details here: https://coolify.io/docs/frameworks/laravel#requirements'", 'type' => 'err' + ], + ); + } + } private function rolling_update() { if ($this->server->isSwarm()) { @@ -640,6 +661,7 @@ private function rolling_update() $this->application_deployment_queue->addLogEntry("Rolling update completed."); } } + $this->framework_based_notification(); } private function health_check() { @@ -873,7 +895,6 @@ private function cleanup_git() private function generate_nixpacks_confs() { $nixpacks_command = $this->nixpacks_build_cmd(); - ray($nixpacks_command); $this->execute_remote_command( [ "echo -n 'Generating nixpacks configuration with: $nixpacks_command'", From aa80392b4619dd5761852b39b9a4c627ac12d69b Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 12:25:50 +0100 Subject: [PATCH 07/15] small fix --- app/Livewire/Project/Application/Heading.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Livewire/Project/Application/Heading.php b/app/Livewire/Project/Application/Heading.php index 170f1db6e..a8a5f7d27 100644 --- a/app/Livewire/Project/Application/Heading.php +++ b/app/Livewire/Project/Application/Heading.php @@ -39,7 +39,7 @@ public function check_status($showNotification = false) } else { dispatch(new ServerStatusJob($this->application->destination->server)); } - if ($showNotification) $this->dispatch('success', 'Application status updated.'); + if ($showNotification) $this->dispatch('success', "Application ({$this->application->name}) status updated."); } public function force_deploy_without_cache() From 404c664500edc7f2ce863fb1b5bea14d4ef5b229 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 12:29:45 +0100 Subject: [PATCH 08/15] fix: traefik labels --- bootstrap/helpers/docker.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 21dfe3e3c..59f45358e 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -249,6 +249,10 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ // Set labels for http (redirect to https) $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); $labels->push("traefik.http.routers.{$http_label}.entryPoints=http"); + $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); + if ($port) { + $labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port"); + } if ($is_force_https_enabled) { $labels->push("traefik.http.routers.{$http_label}.middlewares=redirect-to-https"); } @@ -257,8 +261,8 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); $labels->push("traefik.http.routers.{$http_label}.entryPoints=http"); $labels->push("traefik.http.routers.{$http_label}.middlewares=gzip"); + $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); if ($port) { - $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); $labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port"); } if ($path !== '/') { @@ -266,10 +270,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ $labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}"); } } - } catch(\Throwable $e) { + } catch (\Throwable $e) { continue; } - } return $labels; @@ -278,7 +281,7 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview { $ports = $application->settings->is_static ? [80] : $application->ports_exposes_array; $onlyPort = null; - if (count($ports) === 1) { + if (count($ports) > 0) { $onlyPort = $ports[0]; } $pull_request_id = data_get($preview, 'pull_request_id', 0); From ee71aeaa369208dd71dc6acfe5f8430d315a14a2 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 12:48:46 +0100 Subject: [PATCH 09/15] fix: use ip for sslip in dev if remote server is used --- bootstrap/helpers/shared.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 08315b422..87a850fe4 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -408,7 +408,7 @@ function generateFqdn(Server $server, string $random) } function sslip(Server $server) { - if (isDev()) { + if (isDev() && $server->id === 0) { return "http://127.0.0.1.sslip.io"; } if ($server->ip === 'host.docker.internal') { From e7683ee9a5dea51ffee0b04b714caff068c86dd2 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 12:49:03 +0100 Subject: [PATCH 10/15] fix: service labels without ports (unknown ports) --- bootstrap/helpers/docker.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 59f45358e..0376fcc6e 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -249,9 +249,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ // Set labels for http (redirect to https) $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); $labels->push("traefik.http.routers.{$http_label}.entryPoints=http"); - $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); if ($port) { $labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port"); + $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); } if ($is_force_https_enabled) { $labels->push("traefik.http.routers.{$http_label}.middlewares=redirect-to-https"); @@ -261,9 +261,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ $labels->push("traefik.http.routers.{$http_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); $labels->push("traefik.http.routers.{$http_label}.entryPoints=http"); $labels->push("traefik.http.routers.{$http_label}.middlewares=gzip"); - $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); if ($port) { $labels->push("traefik.http.services.{$http_label}.loadbalancer.server.port=$port"); + $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); } if ($path !== '/') { $labels->push("traefik.http.routers.{$http_label}.middlewares={$http_label}-stripprefix"); From 6bc43bd999814563c8fb8af1f6de8b740545b629 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 13:00:07 +0100 Subject: [PATCH 11/15] fix: sort and rename (unique part) of labels --- bootstrap/helpers/docker.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 0376fcc6e..781888595 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -226,8 +226,8 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ if (is_null($port) && !is_null($onlyPort)) { $port = $onlyPort; } - $http_label = "{$uuid}-{$loop}-http"; - $https_label = "{$uuid}-{$loop}-https"; + $http_label = "http-{$loop}-{$uuid}"; + $https_label = "https-{$loop}-{$uuid}"; if ($schema === 'https') { // Set labels for https @@ -275,7 +275,7 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ } } - return $labels; + return $labels->sort(); } function generateLabelsApplication(Application $application, ?ApplicationPreview $preview = null): array { From 9ed30cb0dc7d2b58763a44a5c305256bc061b6f7 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 13:13:55 +0100 Subject: [PATCH 12/15] Remove unnecessary proxy configurations --- bootstrap/helpers/proxy.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php index a52c859e4..c8b626120 100644 --- a/bootstrap/helpers/proxy.php +++ b/bootstrap/helpers/proxy.php @@ -106,22 +106,6 @@ function generate_default_proxy_configuration(Server $server) // Global Middlewares "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https", "traefik.http.middlewares.gzip.compress=true", - // https WWW to non-WWW - "traefik.http.middlewares.https-www-to-non-www.redirectregex.regex=^https?://www\\.(.+)", - "traefik.http.middlewares.https-www-to-non-www.redirectregex.replacement=https://\$1", - "traefik.http.middlewares.https-www-to-non-www.redirectregex.permanent=true", - // https Non-WWW to WWW - "traefik.http.middlewares.https-non-www-to-www.redirectregex.regex=^https?://(?:www\\.)?(.+)", - "traefik.http.middlewares.https-non-www-to-www.redirectregex.replacement=https://www.\$\${1}", - "traefik.http.middlewares.https-non-www-to-www.redirectregex.permanent=true", - // http www to non-WWW - "traefik.http.middlewares.http-www-to-non-www.redirectregex.regex=^http://www\\.(.+)", - "traefik.http.middlewares.http-www-to-non-www.redirectregex.replacement=http://\$1", - "traefik.http.middlewares.http-www-to-non-www.redirectregex.permanent=true", - // http Non-WWW to WWW - "traefik.http.middlewares.http-non-www-to-www.redirectregex.regex=^http://(?:www\\.)?(.+)", - "traefik.http.middlewares.http-non-www-to-www.redirectregex.replacement=http://www.\$\${1}", - "traefik.http.middlewares.http-non-www-to-www.redirectregex.permanent=true", ]; $config = [ "version" => "3.8", From eef8c756df8140bbfc96fc8ad777f70ba0a40fc6 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 14:27:42 +0100 Subject: [PATCH 13/15] fix: settings menu --- app/Livewire/Settings/Index.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Livewire/Settings/Index.php b/app/Livewire/Settings/Index.php index 44c653b74..0c1dd50e9 100644 --- a/app/Livewire/Settings/Index.php +++ b/app/Livewire/Settings/Index.php @@ -17,16 +17,16 @@ public function mount() if (isInstanceAdmin()) { $settings = InstanceSettings::get(); $database = StandalonePostgresql::whereName('coolify-db')->first(); + $s3s = S3Storage::whereTeamId(0)->get() ?? []; if ($database) { if ($database->status !== 'running') { $database->status = 'running'; $database->save(); } - $s3s = S3Storage::whereTeamId(0)->get(); + $this->database = $database; } $this->settings = $settings; - $this->database = $database; - $this->s3s = $s3s ?? []; + $this->s3s = $s3s; } else { return redirect()->route('dashboard'); } From 7feba4bbaa59dfc779e3c661e69bbfdb19b2b30c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 14:27:55 +0100 Subject: [PATCH 14/15] fix: remove traefik debug in dev mode --- bootstrap/helpers/proxy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php index c8b626120..1c419afbf 100644 --- a/bootstrap/helpers/proxy.php +++ b/bootstrap/helpers/proxy.php @@ -155,7 +155,7 @@ function generate_default_proxy_configuration(Server $server) ], ]; if (isDev()) { - $config['services']['traefik']['command'][] = "--log.level=debug"; + // $config['services']['traefik']['command'][] = "--log.level=debug"; $config['services']['traefik']['command'][] = "--accesslog.filepath=/traefik/access.log"; $config['services']['traefik']['command'][] = "--accesslog.bufferingsize=100"; } From 3b080abadaf452ae7672936394bed2ce63edf0c1 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 9 Jan 2024 14:48:26 +0100 Subject: [PATCH 15/15] remove rays --- app/Models/Application.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Models/Application.php b/app/Models/Application.php index 36026de9c..e0cba3764 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -755,7 +755,6 @@ function rollingUpdateApplication(Server $server, ApplicationDeploymentQueue $de // if (count($this->ports_mappings_array) > 0) { // $deployment->addLogEntry('Application has ports mapped to the host system, rolling update is not supported.'); $containers = getCurrentApplicationContainerStatus($server, $this->id, $pullRequestId); - ray($containers); // if ($pullRequestId === 0) { // $containers = $containers->filter(function ($container) use ($containerName) { // return data_get($container, 'Names') !== $containerName; @@ -867,7 +866,6 @@ function generateGitImportCommands(string $deployment_uuid, int $pull_request_id } else { $git_clone_command = $this->setGitImportSettings($deployment_uuid, $git_clone_command_base); } - ray($git_clone_command); if ($exec_in_docker) { $commands = collect([ executeInDocker($deployment_uuid, "mkdir -p /root/.ssh"),