From 22f0af8d0eeac80c6d3edf25faa3a6fd2c9487f4 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 19 Aug 2026 11:41:41 +0200 Subject: [PATCH] feat(platform): support SMTP EHLO, page-preserving teams, and upgrades --- .../Api/NotificationsController.php | 6 ++-- app/Livewire/SwitchTeam.php | 10 ++++-- app/Livewire/Upgrade.php | 2 ++ resources/views/layouts/app.blade.php | 3 ++ .../views/livewire/settings/updates.blade.php | 5 +++ .../views/livewire/switch-team.blade.php | 4 +-- resources/views/livewire/upgrade.blade.php | 11 ++++++ tests/Feature/Api/NotificationsApiTest.php | 28 +++++++++++++++ tests/Feature/SwitchTeamTest.php | 32 +++++++++++++++++ tests/Feature/UpgradeComponentTest.php | 34 ++++++++++++++----- 10 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 tests/Feature/SwitchTeamTest.php diff --git a/app/Http/Controllers/Api/NotificationsController.php b/app/Http/Controllers/Api/NotificationsController.php index 99d0cb897..f5493d024 100644 --- a/app/Http/Controllers/Api/NotificationsController.php +++ b/app/Http/Controllers/Api/NotificationsController.php @@ -11,6 +11,7 @@ use App\Models\TelegramNotificationSettings; use App\Models\WebhookNotificationSettings; use App\Rules\SafeWebhookUrl; +use App\Rules\ValidHostname; use Illuminate\Database\Eloquent\Model; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -37,6 +38,7 @@ private function channelConfig(string $channel): array 'smtp_username' => 'sometimes|nullable|string|max:255', 'smtp_password' => 'sometimes|nullable|string|max:255', 'smtp_timeout' => 'sometimes|nullable|integer|min:0', + 'smtp_ehlo_domain' => ['sometimes', 'nullable', 'string', 'max:255', new ValidHostname], 'resend_enabled' => 'sometimes|boolean', 'resend_api_key' => 'sometimes|nullable|string|max:255', 'use_instance_email_settings' => 'sometimes|boolean', @@ -283,7 +285,7 @@ private function updateChannel(Request $request, string $channel): JsonResponse #[OA\Get( summary: 'Get email notification settings', - description: 'Get the current team email notification settings. Encrypted secrets are only returned when the token has `read:sensitive` (or `root`) and the user is a team admin/owner.', + description: 'Get the current team email notification settings, including `smtp_ehlo_domain`, the hostname sent with SMTP EHLO. Encrypted secrets are only returned when the token has `read:sensitive` (or `root`) and the user is a team admin/owner.', path: '/notifications/email', operationId: 'get-current-team-email-notifications', security: [['bearerAuth' => []]], @@ -301,7 +303,7 @@ public function email(Request $request): JsonResponse #[OA\Patch( summary: 'Update email notification settings', - description: 'Update the current team email notification settings.', + description: 'Update the current team email notification settings. Set `smtp_ehlo_domain` to a valid hostname to control the SMTP EHLO domain, or `null` to use the system default.', path: '/notifications/email', operationId: 'update-current-team-email-notifications', security: [['bearerAuth' => []]], diff --git a/app/Livewire/SwitchTeam.php b/app/Livewire/SwitchTeam.php index 145c285ab..d50f57c14 100644 --- a/app/Livewire/SwitchTeam.php +++ b/app/Livewire/SwitchTeam.php @@ -19,7 +19,7 @@ public function updatedSelectedTeamId() $this->switch_to($this->selectedTeamId); } - public function switch_to($team_id) + public function switch_to($team_id, ?string $currentUrl = null) { if (! auth()->user()->teams->contains($team_id)) { return; @@ -30,6 +30,12 @@ public function switch_to($team_id) } refreshSession($team_to_switch_to); - return redirect('dashboard'); + $parsedUrl = parse_url($currentUrl ?? '/dashboard'); + $redirectUrl = data_get($parsedUrl, 'path', '/dashboard'); + if ($query = data_get($parsedUrl, 'query')) { + $redirectUrl .= '?'.$query; + } + + return redirect($redirectUrl); } } diff --git a/app/Livewire/Upgrade.php b/app/Livewire/Upgrade.php index aad02c780..d548b3724 100644 --- a/app/Livewire/Upgrade.php +++ b/app/Livewire/Upgrade.php @@ -20,6 +20,8 @@ class Upgrade extends Component public bool $devMode = false; + public bool $fullButton = false; + protected $listeners = ['updateAvailable' => 'checkUpdate']; public function mount() diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 7e02ddb8d..a7de0b680 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -124,6 +124,9 @@ class="flex size-8 shrink-0 items-center justify-center rounded-lg bg-neutral-10
+ @if (isInstanceAdmin() && !isCloud()) + + @endif @@ -66,7 +66,7 @@ class="px-2 py-1 text-[10px] font-semibold uppercase tracking-wide text-neutral- Teams @foreach (auth()->user()->teams as $team) - diff --git a/resources/views/livewire/upgrade.blade.php b/resources/views/livewire/upgrade.blade.php index 97c08c035..b1ad048e1 100644 --- a/resources/views/livewire/upgrade.blade.php +++ b/resources/views/livewire/upgrade.blade.php @@ -6,6 +6,14 @@ })"> @if ($isUpgradeAvailable)
+ @if ($fullButton) + + Upgrade now + + + Updating… + + @else + @endif