@@ -40,7 +40,7 @@ class InstallDocker
 | 
			
		||||
                "echo ####### Restarting Docker Engine...",
 | 
			
		||||
                "systemctl restart docker",
 | 
			
		||||
                "echo ####### Creating default network...",
 | 
			
		||||
                "docker network create --attachable coolify",
 | 
			
		||||
                "docker network create --attachable coolify >/dev/null 2>&1 || true",
 | 
			
		||||
                "echo ####### Done!"
 | 
			
		||||
            ], $server);
 | 
			
		||||
            $found = StandaloneDocker::where('server_id', $server->id);
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ use Mail;
 | 
			
		||||
use Str;
 | 
			
		||||
 | 
			
		||||
use function Laravel\Prompts\select;
 | 
			
		||||
use function Laravel\Prompts\text;
 | 
			
		||||
 | 
			
		||||
class TestEmail extends Command
 | 
			
		||||
{
 | 
			
		||||
@@ -44,9 +45,10 @@ class TestEmail extends Command
 | 
			
		||||
     * Execute the console command.
 | 
			
		||||
     */
 | 
			
		||||
    private ?MailMessage $mail = null;
 | 
			
		||||
    private string $email = 'andras.bacsai@protonmail.com';
 | 
			
		||||
    public function handle()
 | 
			
		||||
    {
 | 
			
		||||
        $email = select(
 | 
			
		||||
        $type = select(
 | 
			
		||||
            'Which Email should be sent?',
 | 
			
		||||
            options: [
 | 
			
		||||
                'emails-test' => 'Test',
 | 
			
		||||
@@ -60,15 +62,15 @@ class TestEmail extends Command
 | 
			
		||||
                'waitlist-confirmation' => 'Waitlist Confirmation',
 | 
			
		||||
            ],
 | 
			
		||||
        );
 | 
			
		||||
        $type = set_transanctional_email_settings();
 | 
			
		||||
        if (!$type) {
 | 
			
		||||
            throw new Exception('No email settings found.');
 | 
			
		||||
        }
 | 
			
		||||
        $this->email = text('Email Address to send to');
 | 
			
		||||
        set_transanctional_email_settings();
 | 
			
		||||
 | 
			
		||||
        $this->mail = new MailMessage();
 | 
			
		||||
        $this->mail->subject("Test Email");
 | 
			
		||||
        switch ($email) {
 | 
			
		||||
        switch ($type) {
 | 
			
		||||
            case 'emails-test':
 | 
			
		||||
                $this->mail = (new Test())->toMail();
 | 
			
		||||
                $this->sendEmail();
 | 
			
		||||
                break;
 | 
			
		||||
            case 'application-deployment-success':
 | 
			
		||||
                $application = Application::all()->first();
 | 
			
		||||
@@ -172,11 +174,7 @@ class TestEmail extends Command
 | 
			
		||||
            [],
 | 
			
		||||
            [],
 | 
			
		||||
            fn (Message $message) => $message
 | 
			
		||||
                ->from(
 | 
			
		||||
                    'internal@example.com',
 | 
			
		||||
                    'Test Email',
 | 
			
		||||
                )
 | 
			
		||||
                ->to('test@example.com')
 | 
			
		||||
                ->to($this->email)
 | 
			
		||||
                ->subject($this->mail->subject)
 | 
			
		||||
                ->html((string)$this->mail->render())
 | 
			
		||||
        );
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ use App\Actions\Server\InstallDocker;
 | 
			
		||||
use App\Models\PrivateKey;
 | 
			
		||||
use App\Models\Project;
 | 
			
		||||
use App\Models\Server;
 | 
			
		||||
use App\Models\Team;
 | 
			
		||||
use Illuminate\Support\Collection;
 | 
			
		||||
use Livewire\Component;
 | 
			
		||||
 | 
			
		||||
@@ -70,9 +71,10 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA==
 | 
			
		||||
    }
 | 
			
		||||
    public function skipBoarding()
 | 
			
		||||
    {
 | 
			
		||||
        currentTeam()->update([
 | 
			
		||||
        Team::find(currentTeam()->id)->update([
 | 
			
		||||
            'show_boarding' => false
 | 
			
		||||
        ]);
 | 
			
		||||
        ray(currentTeam());
 | 
			
		||||
        refreshSession();
 | 
			
		||||
        return redirect()->route('dashboard');
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,6 @@ class Email extends Component
 | 
			
		||||
            $this->validate([
 | 
			
		||||
                'settings.resend_api_key' => 'required'
 | 
			
		||||
            ]);
 | 
			
		||||
            $this->settings->smtp_enabled = false;
 | 
			
		||||
            $this->settings->save();
 | 
			
		||||
            $this->emit('success', 'Settings saved successfully.');
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
@@ -68,9 +67,18 @@ class Email extends Component
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public function instantSaveResend() {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->settings->smtp_enabled = false;
 | 
			
		||||
            $this->submitResend();
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    public function instantSave()
 | 
			
		||||
    {
 | 
			
		||||
        try {
 | 
			
		||||
            $this->settings->resend_enabled = false;
 | 
			
		||||
            $this->submit();
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
            return general_error_handler($e, $this);
 | 
			
		||||
@@ -89,7 +97,6 @@ class Email extends Component
 | 
			
		||||
                'settings.smtp_password' => 'nullable',
 | 
			
		||||
                'settings.smtp_timeout' => 'nullable',
 | 
			
		||||
            ]);
 | 
			
		||||
            $this->settings->resend_enabled = false;
 | 
			
		||||
            $this->settings->save();
 | 
			
		||||
            $this->emit('success', 'Settings saved successfully.');
 | 
			
		||||
        } catch (\Exception $e) {
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@ class SwitchTeam extends Component
 | 
			
		||||
        if (!$team_to_switch_to) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        session(['currentTeam' => $team_to_switch_to]);
 | 
			
		||||
        refreshSession($team_to_switch_to);
 | 
			
		||||
        return redirect(request()->header('Referer'));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@ class IsBoardingFlow
 | 
			
		||||
     */
 | 
			
		||||
    public function handle(Request $request, Closure $next): Response
 | 
			
		||||
    {
 | 
			
		||||
        // ray()->showQueries()->color('orange');
 | 
			
		||||
        ray()->showQueries()->color('orange');
 | 
			
		||||
        if (showBoarding() && !in_array($request->path(), allowedPathsForBoardingAccounts())) {
 | 
			
		||||
            return redirect('boarding');
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ namespace App\Models;
 | 
			
		||||
 | 
			
		||||
use App\Notifications\Channels\SendsEmail;
 | 
			
		||||
use App\Notifications\TransactionalEmails\ResetPassword as TransactionalEmailsResetPassword;
 | 
			
		||||
use Cache;
 | 
			
		||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
 | 
			
		||||
use Illuminate\Foundation\Auth\User as Authenticatable;
 | 
			
		||||
use Illuminate\Notifications\Notifiable;
 | 
			
		||||
@@ -94,7 +95,9 @@ class User extends Authenticatable implements SendsEmail
 | 
			
		||||
 | 
			
		||||
    public function currentTeam()
 | 
			
		||||
    {
 | 
			
		||||
        return Cache::remember('team:' . auth()->user()->id, 3600, function() {
 | 
			
		||||
            return Team::find(session('currentTeam')->id);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public function otherTeams()
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ class DeploymentFailed extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public Application $application;
 | 
			
		||||
    public string $deployment_uuid;
 | 
			
		||||
    public ?ApplicationPreview $preview = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ class DeploymentSuccess extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public Application $application;
 | 
			
		||||
    public string $deployment_uuid;
 | 
			
		||||
    public ApplicationPreview|null $preview = null;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ class StatusChanged extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public $application;
 | 
			
		||||
 | 
			
		||||
    public string $application_name;
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ class BackupFailed extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public string $name;
 | 
			
		||||
    public string $frequency;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ class BackupSuccess extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public string $name;
 | 
			
		||||
    public string $frequency;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ class GeneralNotification extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public function __construct(public string $message)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ class NotReachable extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public function __construct(public Server $server)
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ class Test extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public function __construct(public string|null $emails = null)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ class InvitationLink extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public function via(): array
 | 
			
		||||
    {
 | 
			
		||||
        return [TransactionalEmailChannel::class];
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,7 @@ class Test extends Notification implements ShouldQueue
 | 
			
		||||
{
 | 
			
		||||
    use Queueable;
 | 
			
		||||
 | 
			
		||||
    public $tries = 5;
 | 
			
		||||
    public function __construct(public string $emails)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -57,9 +57,15 @@ function showBoarding(): bool
 | 
			
		||||
{
 | 
			
		||||
    return currentTeam()->show_boarding ?? false;
 | 
			
		||||
}
 | 
			
		||||
function refreshSession(): void
 | 
			
		||||
function refreshSession(?Team $team = null): void
 | 
			
		||||
{
 | 
			
		||||
    if (!$team) {
 | 
			
		||||
        $team = Team::find(currentTeam()->id);
 | 
			
		||||
    }
 | 
			
		||||
    Cache::forget('team:' . auth()->user()->id);
 | 
			
		||||
    Cache::remember('team:' . auth()->user()->id, 3600, function() use ($team) {
 | 
			
		||||
        return $team;
 | 
			
		||||
    });
 | 
			
		||||
    session(['currentTeam' => $team]);
 | 
			
		||||
}
 | 
			
		||||
function general_error_handler(Throwable | null $err = null, $that = null, $isJson = false, $customErrorMessage = null): mixed
 | 
			
		||||
 
 | 
			
		||||
@@ -3,11 +3,11 @@
 | 
			
		||||
return [
 | 
			
		||||
 | 
			
		||||
    // @see https://docs.sentry.io/product/sentry-basics/dsn-explainer/
 | 
			
		||||
    'dsn' => 'https://abe219b6573947128ecf523c835f5f38@o1082494.ingest.sentry.io/4505347448045568',
 | 
			
		||||
    'dsn' => 'https://62de992090e4e0cb28f18231835ea006@o1082494.ingest.sentry.io/4505347448045568',
 | 
			
		||||
 | 
			
		||||
    // 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.28',
 | 
			
		||||
    'release' => '4.0.0-beta.29',
 | 
			
		||||
    'server_name' => env('APP_ID', 'coolify'),
 | 
			
		||||
    // When left empty or `null` the Laravel environment will be used
 | 
			
		||||
    'environment' => config('app.env'),
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,3 @@
 | 
			
		||||
<?php
 | 
			
		||||
 | 
			
		||||
return '4.0.0-beta.28';
 | 
			
		||||
return '4.0.0-beta.29';
 | 
			
		||||
 
 | 
			
		||||
@@ -20,20 +20,31 @@
 | 
			
		||||
            id="team.discord_webhook_url" label="Webhook" />
 | 
			
		||||
    </form>
 | 
			
		||||
    @if (data_get($team, 'discord_enabled'))
 | 
			
		||||
        <h3 class="mt-4">Subscribe to events</h3>
 | 
			
		||||
        <h2 class="mt-4">Subscribe to events</h2>
 | 
			
		||||
        <div class="w-64">
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            @if (isDev())
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.discord_notifications_test" label="Test" />
 | 
			
		||||
            <h3 class="mt-4">Test</h3>
 | 
			
		||||
            <div class="flex items-end gap-10">
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.discord_notifications_test" label="Enabled" />
 | 
			
		||||
            </div>
 | 
			
		||||
            @endif
 | 
			
		||||
            <h4 class="mt-4">General</h4>
 | 
			
		||||
            <h3 class="mt-4">Container Status Changes</h3>
 | 
			
		||||
            <div class="flex items-end gap-10">
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.discord_notifications_status_changes"
 | 
			
		||||
                label="Container Status Changes" />
 | 
			
		||||
            <h4 class="mt-4">Applications</h4>
 | 
			
		||||
                label="Enabled" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <h3 class="mt-4">Application Deployments</h3>
 | 
			
		||||
            <div class="flex items-end gap-10">
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.discord_notifications_deployments"
 | 
			
		||||
                label="Deployments" />
 | 
			
		||||
            <h4 class="mt-4">Databases</h4>
 | 
			
		||||
                label="Enabled" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <h3 class="mt-4">Backup Status</h3>
 | 
			
		||||
            <div class="flex items-end gap-10">
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.discord_notifications_database_backups"
 | 
			
		||||
                label="Backup Statuses" />
 | 
			
		||||
                label="Enabled" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
                    Copy from Instance Settings
 | 
			
		||||
                </x-forms.button>
 | 
			
		||||
            @endif
 | 
			
		||||
            @if (isEmailEnabled($team) || data_get($team, 'use_instance_email_settings'))
 | 
			
		||||
            @if (isEmailEnabled($team) && auth()->user()->isAdminFromSession())
 | 
			
		||||
                <x-forms.button onclick="sendTestEmail.showModal()"
 | 
			
		||||
                    class="text-white normal-case btn btn-xs no-animation btn-primary">
 | 
			
		||||
                    Send Test Email
 | 
			
		||||
@@ -41,7 +41,6 @@
 | 
			
		||||
                label="Use hosted email service (Pro+ subscription required)" />
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
    <h3 class="pb-4">Custom Email Service</h3>
 | 
			
		||||
    @if (!$team->use_instance_email_settings)
 | 
			
		||||
        <form class="flex flex-col items-end gap-2 pb-4 xl:flex-row" wire:submit.prevent='submitFromFields'>
 | 
			
		||||
            <x-forms.input required id="team.smtp_from_name" helper="Name used in emails." label="From Name" />
 | 
			
		||||
@@ -110,19 +109,27 @@
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
    @if (isEmailEnabled($team) || data_get($team, 'use_instance_email_settings'))
 | 
			
		||||
        <h3 class="mt-4">Subscribe to events</h3>
 | 
			
		||||
        <h2 class="mt-4">Subscribe to events</h2>
 | 
			
		||||
        <div class="w-64">
 | 
			
		||||
            @if (isDev())
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_test" label="Test" />
 | 
			
		||||
                <h3 class="mt-4">Test</h3>
 | 
			
		||||
                <div class="flex items-end gap-10">
 | 
			
		||||
                    <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_test" label="Enabled" />
 | 
			
		||||
                </div>
 | 
			
		||||
            @endif
 | 
			
		||||
            <h4 class="mt-4">General</h4>
 | 
			
		||||
            <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_status_changes"
 | 
			
		||||
                label="Container Status Changes" />
 | 
			
		||||
            <h4 class="mt-4">Applications</h4>
 | 
			
		||||
            <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_deployments" label="Deployments" />
 | 
			
		||||
            <h4 class="mt-4">Databases</h4>
 | 
			
		||||
            <h3 class="mt-4">Container Status Changes</h3>
 | 
			
		||||
            <div class="flex items-end gap-10">
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_status_changes" label="Enabled" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <h3 class="mt-4">Application Deployments</h3>
 | 
			
		||||
            <div class="flex items-end gap-10">
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_deployments" label="Enabled" />
 | 
			
		||||
            </div>
 | 
			
		||||
            <h3 class="mt-4">Backup Status</h3>
 | 
			
		||||
            <div class="flex items-end gap-10">
 | 
			
		||||
                <x-forms.checkbox instantSave="saveModel" id="team.smtp_notifications_database_backups"
 | 
			
		||||
                label="Backup Statuses" />
 | 
			
		||||
                    label="Enabled" />
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    @endif
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@
 | 
			
		||||
            <x-forms.button type="submit">
 | 
			
		||||
                Save
 | 
			
		||||
            </x-forms.button>
 | 
			
		||||
            @if ($settings->resend_enabled || $settings->smtp_enabled)
 | 
			
		||||
            @if (isEmailEnabled($settings))
 | 
			
		||||
                <x-forms.button onclick="sendTestEmail.showModal()"
 | 
			
		||||
                    class="text-white normal-case btn btn-xs no-animation btn-primary">
 | 
			
		||||
                    Send Test Email
 | 
			
		||||
@@ -67,14 +67,15 @@
 | 
			
		||||
            <summary class="text-xl collapse-title">
 | 
			
		||||
                <div>Resend</div>
 | 
			
		||||
                <div class="w-32">
 | 
			
		||||
                    <x-forms.checkbox instantSave='submitResend' id="settings.resend_enabled" label="Enabled" />
 | 
			
		||||
                    <x-forms.checkbox instantSave='instantSaveResend' id="settings.resend_enabled" label="Enabled" />
 | 
			
		||||
                </div>
 | 
			
		||||
            </summary>
 | 
			
		||||
            <div class="collapse-content">
 | 
			
		||||
                <form wire:submit.prevent='submitResend' class="flex flex-col">
 | 
			
		||||
                    <div class="flex flex-col gap-4">
 | 
			
		||||
                        <div class="flex flex-col w-full gap-2 xl:flex-row">
 | 
			
		||||
                            <x-forms.input type="password" id="settings.resend_api_key" placeholder="API key" label="Host" />
 | 
			
		||||
                            <x-forms.input type="password" id="settings.resend_api_key" placeholder="API key"
 | 
			
		||||
                                label="Host" />
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="flex justify-end gap-4 pt-6">
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
            "version": "3.12.36"
 | 
			
		||||
        },
 | 
			
		||||
        "v4": {
 | 
			
		||||
            "version": "4.0.0-beta.28"
 | 
			
		||||
            "version": "4.0.0-beta.29"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user