From 92a75685b588127a96ad72a9f9715551799d7a18 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 11 Sep 2023 23:06:24 +0200 Subject: [PATCH 01/18] version plus plus --- 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 417d21025..3e42e7029 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.34', + 'release' => '4.0.0-beta.35', 'server_name' => env('APP_ID', 'coolify'), // 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 44c9c0c1a..c31bdf903 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ Date: Tue, 12 Sep 2023 09:45:20 +0200 Subject: [PATCH 02/18] fix: remove nixpkgarchive --- ..._nixpkgsarchive_to_applications_remove.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 database/migrations/2023_08_22_071058_add_nixpkgsarchive_to_applications_remove.php diff --git a/database/migrations/2023_08_22_071058_add_nixpkgsarchive_to_applications_remove.php b/database/migrations/2023_08_22_071058_add_nixpkgsarchive_to_applications_remove.php new file mode 100644 index 000000000..69845d4d0 --- /dev/null +++ b/database/migrations/2023_08_22_071058_add_nixpkgsarchive_to_applications_remove.php @@ -0,0 +1,22 @@ +dropColumn('nixpkgsarchive'); + }); + } + + public function down(): void + { + Schema::table('teams', function (Blueprint $table) { + $table->string('nixpkgsarchive')->nullable(); + }); + } +}; From be306511727f52c329f907f8ad40782c97ea3e91 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 09:46:10 +0200 Subject: [PATCH 03/18] fix: remove nixpkgarchive from ui --- app/Http/Livewire/Project/Application/General.php | 2 -- app/Jobs/ApplicationDeploymentJob.php | 8 -------- .../views/livewire/project/application/general.blade.php | 4 ---- 3 files changed, 14 deletions(-) diff --git a/app/Http/Livewire/Project/Application/General.php b/app/Http/Livewire/Project/Application/General.php index 0f68a8a2c..bd0006b23 100644 --- a/app/Http/Livewire/Project/Application/General.php +++ b/app/Http/Livewire/Project/Application/General.php @@ -48,7 +48,6 @@ class General extends Component 'application.ports_exposes' => 'required', 'application.ports_mappings' => 'nullable', 'application.dockerfile' => 'nullable', - 'application.nixpkgsarchive' => 'nullable', ]; protected $validationAttributes = [ 'application.name' => 'name', @@ -67,7 +66,6 @@ class General extends Component 'application.ports_exposes' => 'Ports exposes', 'application.ports_mappings' => 'Ports mappings', 'application.dockerfile' => 'Dockerfile', - 'application.nixpkgsarchive' => 'Nixpkgs archive', ]; public function instantSave() diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 7a61029e0..a92bf4939 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -413,7 +413,6 @@ private function cleanup_git() private function generate_nixpacks_confs() { - ray('nixpkgsarchive', $this->application->nixpkgsarchive); $this->execute_remote_command( [ "echo -n 'Generating nixpacks configuration.'", @@ -422,13 +421,6 @@ private function generate_nixpacks_confs() [$this->execute_in_builder("cp {$this->workdir}/.nixpacks/Dockerfile {$this->workdir}/Dockerfile")], [$this->execute_in_builder("rm -f {$this->workdir}/.nixpacks/Dockerfile")] ); - - // if ($this->application->nixpkgsarchive) { - // $this->execute_remote_command([ - // $this->execute_in_builder("cat {$this->workdir}/nixpacks.toml"), "hidden" => true, "save" => 'nixpacks_toml' - // ]); - - // } } private function nixpacks_build_cmd() diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index 768f19d7e..a893e519d 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -32,10 +32,6 @@ - {{-- @if ($application->build_pack === 'nixpacks') - - @endif --}} @if ($application->settings->is_static) From 6da4e7837474adc2f7cfe72c2c6ddc1ee831a83a Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 11:19:21 +0200 Subject: [PATCH 04/18] feat: trial --- app/Console/Commands/WaitlistInvite.php | 1 - app/Http/Livewire/Help.php | 2 +- .../Livewire/Subscription/PricingPlans.php | 14 +++++ app/Jobs/SubscriptionTrialEndedJob.php | 44 ++++++++++++++ app/Jobs/SubscriptionTrialEndsSoonJob.php | 44 ++++++++++++++ app/Models/Subscription.php | 4 +- app/Models/Team.php | 16 ++++++ ...23_08_22_071059_add_stripe_trial_ended.php | 30 ++++++++++ .../views/components/emails/footer.blade.php | 2 +- .../views/components/pricing-plans.blade.php | 1 + resources/views/emails/trial-ended.blade.php | 7 +++ .../views/emails/trial-ends-soon.blade.php | 7 +++ routes/webhooks.php | 57 +++++++++++++++---- 13 files changed, 214 insertions(+), 15 deletions(-) create mode 100755 app/Jobs/SubscriptionTrialEndedJob.php create mode 100755 app/Jobs/SubscriptionTrialEndsSoonJob.php create mode 100644 database/migrations/2023_08_22_071059_add_stripe_trial_ended.php create mode 100644 resources/views/emails/trial-ended.blade.php create mode 100644 resources/views/emails/trial-ends-soon.blade.php diff --git a/app/Console/Commands/WaitlistInvite.php b/app/Console/Commands/WaitlistInvite.php index dd629d706..f3eefbcfa 100644 --- a/app/Console/Commands/WaitlistInvite.php +++ b/app/Console/Commands/WaitlistInvite.php @@ -92,7 +92,6 @@ private function remove_from_waitlist() } private function send_email() { - ray($this->next_patient->email, $this->password); $token = Crypt::encryptString("{$this->next_patient->email}@@@$this->password"); $loginLink = route('auth.link', ['token' => $token]); $mail = new MailMessage(); diff --git a/app/Http/Livewire/Help.php b/app/Http/Livewire/Help.php index 9f3ca434f..505224d2c 100644 --- a/app/Http/Livewire/Help.php +++ b/app/Http/Livewire/Help.php @@ -30,7 +30,7 @@ public function submit() try { $this->rateLimit(1, 60); $this->validate(); - $subscriptionType = auth()->user()?->subscription?->type() ?? 'unknown'; + $subscriptionType = auth()->user()?->subscription?->type(); $debug = "Route: {$this->path}"; $mail = new MailMessage(); $mail->view( diff --git a/app/Http/Livewire/Subscription/PricingPlans.php b/app/Http/Livewire/Subscription/PricingPlans.php index 80cc81dcf..d200ecd15 100644 --- a/app/Http/Livewire/Subscription/PricingPlans.php +++ b/app/Http/Livewire/Subscription/PricingPlans.php @@ -10,6 +10,7 @@ class PricingPlans extends Component { public function subscribeStripe($type) { + $team = currentTeam(); Stripe::setApiKey(config('subscription.stripe_api_key')); switch ($type) { case 'basic-monthly': @@ -50,10 +51,23 @@ public function subscribeStripe($type) 'automatic_tax' => [ 'enabled' => true, ], + 'mode' => 'subscription', 'success_url' => route('dashboard', ['success' => true]), 'cancel_url' => route('subscription.index', ['cancelled' => true]), ]; + + if (!data_get($team,'subscription.stripe_trial_already_ended')) { + $payload['subscription_data'] = [ + 'trial_period_days' => 30, + 'trial_settings' => [ + 'end_behavior' => [ + 'missing_payment_method' => 'cancel', + ] + ], + ]; + $payload['payment_method_collection'] = 'if_required'; + } $customer = currentTeam()->subscription?->stripe_customer_id ?? null; if ($customer) { $payload['customer'] = $customer; diff --git a/app/Jobs/SubscriptionTrialEndedJob.php b/app/Jobs/SubscriptionTrialEndedJob.php new file mode 100755 index 000000000..39acd19a2 --- /dev/null +++ b/app/Jobs/SubscriptionTrialEndedJob.php @@ -0,0 +1,44 @@ +team); + $mail = new MailMessage(); + $mail->subject('Action required: You trial in Coolify Cloud ended.'); + $mail->view('emails.trial-ended', [ + 'stripeCustomerPortal' => $session->url, + ]); + $this->team->members()->each(function ($member) use ($mail) { + if ($member->isAdmin()) { + ray('Sending trial ended email to ' . $member->email); + send_user_an_email($mail, $member->email); + send_internal_notification('Trial reminder email sent to ' . $member->email); + } + }); + } catch (\Throwable $e) { + send_internal_notification('SubscriptionTrialEndsSoonJob failed with: ' . $e->getMessage()); + ray($e->getMessage()); + throw $e; + } + } +} diff --git a/app/Jobs/SubscriptionTrialEndsSoonJob.php b/app/Jobs/SubscriptionTrialEndsSoonJob.php new file mode 100755 index 000000000..84bd8ee66 --- /dev/null +++ b/app/Jobs/SubscriptionTrialEndsSoonJob.php @@ -0,0 +1,44 @@ +team); + $mail = new MailMessage(); + $mail->subject('You trial in Coolify Cloud ends soon.'); + $mail->view('emails.trial-ends-soon', [ + 'stripeCustomerPortal' => $session->url, + ]); + $this->team->members()->each(function ($member) use ($mail) { + if ($member->isAdmin()) { + ray('Sending trial ending email to ' . $member->email); + send_user_an_email($mail, $member->email); + send_internal_notification('Trial reminder email sent to ' . $member->email); + } + }); + } catch (\Throwable $e) { + send_internal_notification('SubscriptionTrialEndsSoonJob failed with: ' . $e->getMessage()); + ray($e->getMessage()); + throw $e; + } + } +} diff --git a/app/Models/Subscription.php b/app/Models/Subscription.php index 4acd7fe8a..d69d95981 100644 --- a/app/Models/Subscription.php +++ b/app/Models/Subscription.php @@ -33,7 +33,7 @@ public function type() } if (isStripe()) { if (!$this->stripe_plan_id) { - return 'unknown'; + return 'zero'; } $subscription = Subscription::where('id', $this->id)->first(); if (!$subscription) { @@ -54,6 +54,6 @@ public function type() return Str::of($stripePlanId)->after('stripe_price_id_')->before('_')->lower(); } } - return 'unknown'; + return 'zero'; } } diff --git a/app/Models/Team.php b/app/Models/Team.php index 485811a17..558c8dc3b 100644 --- a/app/Models/Team.php +++ b/app/Models/Team.php @@ -120,4 +120,20 @@ public function s3s() { return $this->hasMany(S3Storage::class); } + public function trialEnded() { + foreach ($this->servers as $server) { + $server->settings()->update([ + 'is_usable' => false, + 'is_reachable' => false, + ]); + } + } + public function trialEndedButSubscribed() { + foreach ($this->servers as $server) { + $server->settings()->update([ + 'is_usable' => true, + 'is_reachable' => true, + ]); + } + } } diff --git a/database/migrations/2023_08_22_071059_add_stripe_trial_ended.php b/database/migrations/2023_08_22_071059_add_stripe_trial_ended.php new file mode 100644 index 000000000..591f8382d --- /dev/null +++ b/database/migrations/2023_08_22_071059_add_stripe_trial_ended.php @@ -0,0 +1,30 @@ +boolean('stripe_trial_already_ended')->default(false)->after('stripe_cancel_at_period_end'); + + + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('subscriptions', function (Blueprint $table) { + $table->dropColumn('stripe_trial_already_ended'); + }); + } +}; diff --git a/resources/views/components/emails/footer.blade.php b/resources/views/components/emails/footer.blade.php index 44f47ef93..fba408cae 100644 --- a/resources/views/components/emails/footer.blade.php +++ b/resources/views/components/emails/footer.blade.php @@ -3,4 +3,4 @@ Thank you,
{{ config('app.name') ?? 'Coolify' }} -{{ Illuminate\Mail\Markdown::parse('[Contact Support](https://docs.coollabs.io)') }} +{{ Illuminate\Mail\Markdown::parse('[Contact Support](https://docs.coollabs.io/contact)') }} diff --git a/resources/views/components/pricing-plans.blade.php b/resources/views/components/pricing-plans.blade.php index c231f1d21..ce8d81c20 100644 --- a/resources/views/components/pricing-plans.blade.php +++ b/resources/views/components/pricing-plans.blade.php @@ -21,6 +21,7 @@ class="sr-only"> +
30 days trial included on all plans, without credit card details.
Save 1 month annually with the yearly plans.
diff --git a/resources/views/emails/trial-ended.blade.php b/resources/views/emails/trial-ended.blade.php new file mode 100644 index 000000000..aeb00fa92 --- /dev/null +++ b/resources/views/emails/trial-ended.blade.php @@ -0,0 +1,7 @@ + + +Your trial ended. All automations and integrations are disabled for all of your servers. + +Please update payment details [here]({{$stripeCustomerPortal}}) or in [Coolify Cloud](https://app.coolify.io) to continue using our services. + + diff --git a/resources/views/emails/trial-ends-soon.blade.php b/resources/views/emails/trial-ends-soon.blade.php new file mode 100644 index 000000000..2e6909016 --- /dev/null +++ b/resources/views/emails/trial-ends-soon.blade.php @@ -0,0 +1,7 @@ + + +Your trial ends soon. Please update payment details [here]({{$stripeCustomerPortal}}), + +Your servers & deployed resources will be untouched, but you won't be able to deploy new resources and lost all automations and integrations. + + diff --git a/routes/webhooks.php b/routes/webhooks.php index f05df9c5a..6a9de6403 100644 --- a/routes/webhooks.php +++ b/routes/webhooks.php @@ -1,6 +1,7 @@ firstOrFail(); + $planId = data_get($data, 'lines.data.0.plan.id'); $subscription->update([ + 'stripe_plan_id' => $planId, 'stripe_invoice_paid' => true, ]); break; - // case 'invoice.payment_failed': - // $customerId = data_get($data, 'customer'); - // $subscription = Subscription::where('stripe_customer_id', $customerId)->first(); - // if ($subscription) { - // SubscriptionInvoiceFailedJob::dispatch($subscription->team); - // } - // break; case 'customer.subscription.updated': $customerId = data_get($data, 'customer'); $subscription = Subscription::where('stripe_customer_id', $customerId)->firstOrFail(); + $trialEndedAlready = data_get($subscription, 'stripe_trial_already_ended'); + $status = data_get($data, 'status'); $subscriptionId = data_get($data, 'items.data.0.subscription'); $planId = data_get($data, 'items.data.0.plan.id'); $cancelAtPeriodEnd = data_get($data, 'cancel_at_period_end'); @@ -297,7 +295,19 @@ 'stripe_plan_id' => $planId, 'stripe_cancel_at_period_end' => $cancelAtPeriodEnd, ]); - ray($feedback, $comment, $alreadyCancelAtPeriodEnd, $cancelAtPeriodEnd); + if ($status === 'paused') { + $subscription->update([ + 'stripe_invoice_paid' => false, + ]); + send_internal_notification('Subscription paused for team: ' . $subscription->team->id); + } + + // Trial ended but subscribed, reactive servers + if ($trialEndedAlready && $status === 'active') { + $team = data_get($subscription, 'team'); + $team->trialEndedButSubscribed(); + } + if ($feedback) { $reason = "Cancellation feedback for {$subscription->team->id}: '" . $feedback . "'"; if ($comment) { @@ -305,7 +315,6 @@ } send_internal_notification($reason); } - ray($alreadyCancelAtPeriodEnd !== $cancelAtPeriodEnd); if ($alreadyCancelAtPeriodEnd !== $cancelAtPeriodEnd) { if ($cancelAtPeriodEnd) { send_internal_notification('Subscription cancelled at period end for team: ' . $subscription->team->id); @@ -315,16 +324,44 @@ } break; case 'customer.subscription.deleted': + // End subscription $customerId = data_get($data, 'customer'); $subscription = Subscription::where('stripe_customer_id', $customerId)->firstOrFail(); + $team = data_get($subscription, 'team'); + $team->trialEnded(); $subscription->update([ 'stripe_subscription_id' => null, 'stripe_plan_id' => null, 'stripe_cancel_at_period_end' => false, 'stripe_invoice_paid' => false, + 'stripe_trial_already_ended' => true, ]); send_internal_notification('Subscription cancelled: ' . $subscription->team->id); break; + case 'customer.subscription.trial_will_end': + $customerId = data_get($data, 'customer'); + $subscription = Subscription::where('stripe_customer_id', $customerId)->firstOrFail(); + $team = data_get($subscription, 'team'); + if (!$team) { + throw new Exception('No team found for subscription: ' . $subscription->id); + } + SubscriptionTrialEndsSoonJob::dispatch($team); + break; + case 'customer.subscription.paused': + $customerId = data_get($data, 'customer'); + $subscription = Subscription::where('stripe_customer_id', $customerId)->firstOrFail(); + $team = data_get($subscription, 'team'); + if (!$team) { + throw new Exception('No team found for subscription: ' . $subscription->id); + } + $team->trialEnded(); + $subscription->update([ + 'stripe_trial_already_ended' => true, + 'stripe_invoice_paid' => false, + ]); + SubscriptionTrialEndedJob::dispatch($team); + send_internal_notification('Subscription paused for team: ' . $subscription->team->id); + break; default: // Unhandled event type } From 5d27e89bfa0e4e6eb17a3b3f9700f0aba67e13aa Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 11:23:31 +0200 Subject: [PATCH 05/18] feat: dynamic trial period --- app/Http/Livewire/Subscription/PricingPlans.php | 2 +- config/constants.php | 1 + resources/views/components/pricing-plans.blade.php | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/Http/Livewire/Subscription/PricingPlans.php b/app/Http/Livewire/Subscription/PricingPlans.php index d200ecd15..a310b69f4 100644 --- a/app/Http/Livewire/Subscription/PricingPlans.php +++ b/app/Http/Livewire/Subscription/PricingPlans.php @@ -59,7 +59,7 @@ public function subscribeStripe($type) if (!data_get($team,'subscription.stripe_trial_already_ended')) { $payload['subscription_data'] = [ - 'trial_period_days' => 30, + 'trial_period_days' => config('constants.limits.trial_period'), 'trial_settings' => [ 'end_behavior' => [ 'missing_payment_method' => 'cancel', diff --git a/config/constants.php b/config/constants.php index 0021f8a5c..4cb112855 100644 --- a/config/constants.php +++ b/config/constants.php @@ -10,6 +10,7 @@ ], ], 'limits' => [ + 'trial_period'=> 14, 'server' => [ 'zero' => 0, 'self-hosted' => 999999999999, diff --git a/resources/views/components/pricing-plans.blade.php b/resources/views/components/pricing-plans.blade.php index ce8d81c20..552247a74 100644 --- a/resources/views/components/pricing-plans.blade.php +++ b/resources/views/components/pricing-plans.blade.php @@ -21,7 +21,7 @@ class="sr-only">
-
30 days trial included on all plans, without credit card details.
+
{{config('constants.limits.trial_period')}} days trial included on all plans, without credit card details.
Save 1 month annually with the yearly plans.
From 6266a5e500c03b1b774309956f7b7e3b5b14f8c0 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 12:03:17 +0200 Subject: [PATCH 06/18] internal: trial emails --- app/Console/Commands/TestEmail.php | 34 +++++++++++++++++-- .../emails/before-trial-conversion.blade.php | 8 +++++ 2 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 resources/views/emails/before-trial-conversion.blade.php diff --git a/app/Console/Commands/TestEmail.php b/app/Console/Commands/TestEmail.php index 4e29d7962..33129350a 100644 --- a/app/Console/Commands/TestEmail.php +++ b/app/Console/Commands/TestEmail.php @@ -7,6 +7,7 @@ use App\Models\ApplicationPreview; use App\Models\ScheduledDatabaseBackup; use App\Models\StandalonePostgresql; +use App\Models\Team; use App\Models\TeamInvitation; use App\Models\User; use App\Models\Waitlist; @@ -62,9 +63,13 @@ public function handle() 'invitation-link' => 'Invitation Link', 'waitlist-invitation-link' => 'Waitlist Invitation Link', 'waitlist-confirmation' => 'Waitlist Confirmation', + 'realusers-before-trial' => 'REAL - Registered Users Before Trial without Subscription', ], ); - $this->email = text('Email Address to send to'); + $emailsGathered = ['realusers-before-trial']; + if (!in_array($type, $emailsGathered)) { + $this->email = text('Email Address to send to'); + } set_transanctional_email_settings(); $this->mail = new MailMessage(); @@ -159,16 +164,39 @@ public function handle() $found = Waitlist::where('email', $this->email)->first(); if ($found) { SendConfirmationForWaitlistJob::dispatch($this->email, $found->uuid); - } else { throw new Exception('Waitlist not found'); } break; + case 'realusers-before-trial': + $this->mail = new MailMessage(); + $this->mail->view('emails.before-trial-conversion'); + $this->mail->subject('Trial period has been added for all subscription plans.'); + $teams = Team::doesntHave('subscription')->where('id', '!=', 0)->get(); + if (!$teams || $teams->isEmpty()) { + echo 'No teams found.' . PHP_EOL; + return; + } + $emails = []; + foreach ($teams as $team) { + foreach($team->members as $member) { + if ($member->email) { + $emails[] = $member->email; + } + } + } + $emails = array_unique($emails); + foreach ($emails as $email) { + $this->sendEmail($email); + } } } - private function sendEmail() + private function sendEmail(string $email = null) { + if ($email) { + $this->email = $email; + } Mail::send( [], [], diff --git a/resources/views/emails/before-trial-conversion.blade.php b/resources/views/emails/before-trial-conversion.blade.php new file mode 100644 index 000000000..c9531ff2b --- /dev/null +++ b/resources/views/emails/before-trial-conversion.blade.php @@ -0,0 +1,8 @@ + +We would like to inform you that a {{config('constants.limits.trial_period')}} days of trial has been added to all subscription plans. + +You can try out Coolify, without payment information for free. If you like it, you can upgrade to a paid plan at any time. + +[Click here](https://app.coolify.io/subscription) to start your trial. + + From c76a1b1ba58d3c666887b3df7f07b331252f167d Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 13:10:39 +0200 Subject: [PATCH 07/18] fix: webhooks should not run if server is not functional --- routes/webhooks.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/routes/webhooks.php b/routes/webhooks.php index 6a9de6403..c3c80dba3 100644 --- a/routes/webhooks.php +++ b/routes/webhooks.php @@ -119,6 +119,11 @@ return response('Nothing to do. No applications found.'); } foreach ($applications as $application) { + $isFunctional = $application->destination->server->isFunctional(); + if (!$isFunctional) { + ray('Server is not functional: ' . $application->destination->server->name); + continue; + } if ($x_github_event === 'push') { if ($application->isDeployable()) { ray('Deploying ' . $application->name . ' with branch ' . $branch); From ab021ee53566d4d75474da99b87b5fdf74b869e0 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 13:14:01 +0200 Subject: [PATCH 08/18] fix: server is functional check --- app/Http/Livewire/Server/New/ByIp.php | 2 +- app/Http/Livewire/Server/Proxy/Status.php | 2 +- app/Jobs/DockerCleanupJob.php | 4 ++-- app/Models/Server.php | 3 +++ resources/views/livewire/destination/show.blade.php | 2 +- resources/views/livewire/server/form.blade.php | 4 ++-- resources/views/livewire/server/proxy.blade.php | 2 +- 7 files changed, 11 insertions(+), 8 deletions(-) diff --git a/app/Http/Livewire/Server/New/ByIp.php b/app/Http/Livewire/Server/New/ByIp.php index d0b44ecaf..20377dc5d 100644 --- a/app/Http/Livewire/Server/New/ByIp.php +++ b/app/Http/Livewire/Server/New/ByIp.php @@ -58,7 +58,7 @@ public function submit() { $this->validate(); try { - if (!$this->private_key_id) { + if (is_null($this->private_key_id)) { return $this->emit('error', 'You must select a private key'); } $server = Server::create([ diff --git a/app/Http/Livewire/Server/Proxy/Status.php b/app/Http/Livewire/Server/Proxy/Status.php index 9ecf318a8..a0b90b7be 100644 --- a/app/Http/Livewire/Server/Proxy/Status.php +++ b/app/Http/Livewire/Server/Proxy/Status.php @@ -17,7 +17,7 @@ public function proxyStatusUpdated() public function getProxyStatus() { try { - if (data_get($this->server, 'settings.is_usable') && data_get($this->server, 'settings.is_reachable')) { + if ($this->server->isFunctional()) { $container = getContainerStatus(server: $this->server, container_id: 'coolify-proxy'); $this->server->proxy->status = $container; $this->server->save(); diff --git a/app/Jobs/DockerCleanupJob.php b/app/Jobs/DockerCleanupJob.php index fbb9ac2c7..b1fccbe4b 100644 --- a/app/Jobs/DockerCleanupJob.php +++ b/app/Jobs/DockerCleanupJob.php @@ -36,11 +36,11 @@ public function handle(): void return; } try { - ray()->showQueries()->color('orange'); + // ray()->showQueries()->color('orange'); $servers = Server::all(); foreach ($servers as $server) { if ( - !$server->settings->is_reachable && !$server->settings->is_usable + !$server->isFunctional() ) { continue; } diff --git a/app/Models/Server.php b/app/Models/Server.php index 973d2d628..f45cf3b2d 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -153,4 +153,7 @@ public function isProxyShouldRun() } return $shouldRun; } + public function isFunctional() { + return $this->settings->is_reachable && $this->settings->is_usable; + } } diff --git a/resources/views/livewire/destination/show.blade.php b/resources/views/livewire/destination/show.blade.php index 1ab18826e..942c094c3 100644 --- a/resources/views/livewire/destination/show.blade.php +++ b/resources/views/livewire/destination/show.blade.php @@ -1,5 +1,5 @@
- @if ($server->settings->is_usable) + @if ($server->isFunctional()) - @if (!$server->settings->is_reachable || !$server->settings->is_usable) + @if (!$server->isFunctional()) You can't use this server until it is validated. @else Server validated. @@ -57,7 +57,7 @@ Install Docker Engine 24.0 @endif - @if ($server->settings->is_usable) + @if ($server->isFunctional())

Settings

diff --git a/resources/views/livewire/server/proxy.blade.php b/resources/views/livewire/server/proxy.blade.php index abfb7f69f..0b38ad940 100644 --- a/resources/views/livewire/server/proxy.blade.php +++ b/resources/views/livewire/server/proxy.blade.php @@ -1,5 +1,5 @@
- @if (data_get($server,'settings.is_usable')) + @if ($server->isFunctional()) @if (data_get($server,'proxy.type')) From 8ba18b2ce1ceda6b0ab743dce3ebb038ae794dea Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 13:19:55 +0200 Subject: [PATCH 09/18] fix: confirm email before sending --- .../Commands/{TestEmail.php => Emails.php} | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) rename app/Console/Commands/{TestEmail.php => Emails.php} (92%) diff --git a/app/Console/Commands/TestEmail.php b/app/Console/Commands/Emails.php similarity index 92% rename from app/Console/Commands/TestEmail.php rename to app/Console/Commands/Emails.php index 33129350a..d6a882740 100644 --- a/app/Console/Commands/TestEmail.php +++ b/app/Console/Commands/Emails.php @@ -25,30 +25,31 @@ use Mail; use Str; +use function Laravel\Prompts\confirm; use function Laravel\Prompts\select; use function Laravel\Prompts\text; -class TestEmail extends Command +class Emails extends Command { /** * The name and signature of the console command. * * @var string */ - protected $signature = 'email:test'; + protected $signature = 'emails'; /** * The console command description. * * @var string */ - protected $description = 'Send a test email to the admin'; + protected $description = 'Send out test / prod emails'; /** * Execute the console command. */ private ?MailMessage $mail = null; - private string $email = 'andras.bacsai@protonmail.com'; + private ?string $email = null; public function handle() { $type = select( @@ -180,16 +181,24 @@ public function handle() } $emails = []; foreach ($teams as $team) { - foreach($team->members as $member) { + foreach ($team->members as $member) { if ($member->email) { $emails[] = $member->email; } } } $emails = array_unique($emails); + $this->info("Sending to " . count($emails) . " emails."); foreach ($emails as $email) { - $this->sendEmail($email); + $this->info($email); } + $confirmed = confirm('Are you sure?'); + if ($confirmed) { + foreach ($emails as $email) { + $this->sendEmail($email); + } + } + break; } } private function sendEmail(string $email = null) @@ -205,5 +214,6 @@ private function sendEmail(string $email = null) ->subject($this->mail->subject) ->html((string)$this->mail->render()) ); + $this->info("Email sent to $this->email successfully. 📧"); } } From 9baf0161c7b42b518730d0f7c0623ec9e9b84246 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 14:51:35 +0200 Subject: [PATCH 10/18] fix: help should send cc on email --- app/Http/Livewire/Help.php | 2 +- bootstrap/helpers/shared.php | 30 +++++++++++++------ .../components/navbar-subscription.blade.php | 12 ++++++++ 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/app/Http/Livewire/Help.php b/app/Http/Livewire/Help.php index 505224d2c..acfdc5c58 100644 --- a/app/Http/Livewire/Help.php +++ b/app/Http/Livewire/Help.php @@ -41,7 +41,7 @@ public function submit() ] ); $mail->subject("[HELP - {$subscriptionType}]: {$this->subject}"); - send_user_an_email($mail, 'hi@coollabs.io'); + send_user_an_email($mail, 'hi@coollabs.io', auth()->user()?->email); $this->emit('success', 'Your message has been sent successfully. We will get in touch with you as soon as possible.'); } catch (\Throwable $e) { return general_error_handler($e, $this); diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index edb54ab64..f42ac83d7 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -262,21 +262,33 @@ function send_internal_notification(string $message): void ray($e->getMessage()); } } -function send_user_an_email(MailMessage $mail, string $email): void +function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null): void { $settings = InstanceSettings::get(); $type = set_transanctional_email_settings($settings); if (!$type) { throw new Exception('No email settings found.'); } - Mail::send( - [], - [], - fn (Message $message) => $message - ->to($email) - ->subject($mail->subject) - ->html((string) $mail->render()) - ); + if ($cc) { + Mail::send( + [], + [], + fn (Message $message) => $message + ->to($email) + ->cc($cc) + ->subject($mail->subject) + ->html((string) $mail->render()) + ); + } else { + Mail::send( + [], + [], + fn (Message $message) => $message + ->to($email) + ->subject($mail->subject) + ->html((string) $mail->render()) + ); + } } function isEmailEnabled($notifiable) { diff --git a/resources/views/components/navbar-subscription.blade.php b/resources/views/components/navbar-subscription.blade.php index 73e67410b..3770a2d31 100644 --- a/resources/views/components/navbar-subscription.blade.php +++ b/resources/views/components/navbar-subscription.blade.php @@ -10,6 +10,18 @@ +
  • +
    + + + + + + +
    +
  • @csrf From d0cd926517b47abc951e57ec978ae9848eb8f33d Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 14:53:54 +0200 Subject: [PATCH 11/18] fix: sub type --- app/Http/Livewire/Help.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Livewire/Help.php b/app/Http/Livewire/Help.php index acfdc5c58..d467a11f9 100644 --- a/app/Http/Livewire/Help.php +++ b/app/Http/Livewire/Help.php @@ -30,7 +30,7 @@ public function submit() try { $this->rateLimit(1, 60); $this->validate(); - $subscriptionType = auth()->user()?->subscription?->type(); + $subscriptionType = auth()->user()?->subscription?->type() ?? 'Free'; $debug = "Route: {$this->path}"; $mail = new MailMessage(); $mail->view( From bb9abafa823dfe10959ee394e874fdc896e997f2 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 15:00:05 +0200 Subject: [PATCH 12/18] test gh runner --- .github/workflows/development-build.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/development-build.yml b/.github/workflows/development-build.yml index 681cbda3a..51415444f 100644 --- a/.github/workflows/development-build.yml +++ b/.github/workflows/development-build.yml @@ -13,7 +13,7 @@ env: jobs: amd64: - runs-on: ubuntu-latest + runs-on: [self-hosted, x64] steps: - uses: actions/checkout@v3 - name: Login to ghcr.io @@ -52,7 +52,7 @@ jobs: push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:next-aarch64 merge-manifest: - runs-on: ubuntu-latest + runs-on: [self-hosted, x64] permissions: contents: read packages: write From 01e942c6a00cab33fe5a7f460ec4c11eac69a54f Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Tue, 12 Sep 2023 15:06:07 +0200 Subject: [PATCH 13/18] fix: show help modal everywhere --- resources/views/layouts/base.blade.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/resources/views/layouts/base.blade.php b/resources/views/layouts/base.blade.php index 7f07b857b..4e6ed3cdf 100644 --- a/resources/views/layouts/base.blade.php +++ b/resources/views/layouts/base.blade.php @@ -28,14 +28,12 @@ @livewireScripts - @if (isSubscriptionActive() || isDev()) - - - - - - - @endif + + + +