diff --git a/.cursor/rules/security-patterns.mdc b/.cursor/rules/security-patterns.mdc index d47d03375..9cdbcaa0c 100644 --- a/.cursor/rules/security-patterns.mdc +++ b/.cursor/rules/security-patterns.mdc @@ -21,7 +21,9 @@ Coolify implements **defense-in-depth security** with multiple layers of protect - **Supported Providers**: - Google OAuth - Microsoft Azure AD + - Clerk - Authentik + - Discord - GitHub (via GitHub Apps) - GitLab diff --git a/.cursor/rules/technology-stack.mdc b/.cursor/rules/technology-stack.mdc index 1e894720c..81a2e3bb3 100644 --- a/.cursor/rules/technology-stack.mdc +++ b/.cursor/rules/technology-stack.mdc @@ -90,7 +90,7 @@ alwaysApply: false - **Purpose**: OAuth provider integration - **Providers**: - GitHub, GitLab, Google - - Microsoft Azure, Authentik + - Microsoft Azure, Authentik, Discord, Clerk - Custom OAuth implementations ## Background Processing diff --git a/app/Actions/Service/StartService.php b/app/Actions/Service/StartService.php index 1e7779a75..d48594e62 100644 --- a/app/Actions/Service/StartService.php +++ b/app/Actions/Service/StartService.php @@ -41,6 +41,6 @@ class StartService } } - return remote_process($commands, $service->server, type_uuid: $service->uuid); + return remote_process($commands, $service->server, type_uuid: $service->uuid, callEventOnFinish: 'ServiceStatusChanged'); } } diff --git a/app/Console/Commands/CleanupStuckedResources.php b/app/Console/Commands/CleanupStuckedResources.php index 0b5eef84d..81824675b 100644 --- a/app/Console/Commands/CleanupStuckedResources.php +++ b/app/Console/Commands/CleanupStuckedResources.php @@ -20,6 +20,7 @@ use App\Models\StandaloneMongodb; use App\Models\StandaloneMysql; use App\Models\StandalonePostgresql; use App\Models\StandaloneRedis; +use App\Models\Team; use Illuminate\Console\Command; class CleanupStuckedResources extends Command @@ -36,6 +37,12 @@ class CleanupStuckedResources extends Command private function cleanup_stucked_resources() { try { + $teams = Team::all()->filter(function ($team) { + return $team->members()->count() === 0 && $team->servers()->count() === 0; + }); + foreach ($teams as $team) { + $team->delete(); + } $servers = Server::all()->filter(function ($server) { return $server->isFunctional(); }); diff --git a/app/Helpers/SshMultiplexingHelper.php b/app/Helpers/SshMultiplexingHelper.php index 8da476b9e..8caa2880a 100644 --- a/app/Helpers/SshMultiplexingHelper.php +++ b/app/Helpers/SshMultiplexingHelper.php @@ -103,7 +103,11 @@ class SshMultiplexingHelper } $scp_command .= self::getCommonSshOptions($server, $sshKeyLocation, config('constants.ssh.connection_timeout'), config('constants.ssh.server_interval'), isScp: true); - $scp_command .= "{$source} {$server->user}@{$server->ip}:{$dest}"; + if ($server->isIpv6()) { + $scp_command .= "{$source} {$server->user}@[{$server->ip}]:{$dest}"; + } else { + $scp_command .= "{$source} {$server->user}@{$server->ip}:{$dest}"; + } return $scp_command; } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 14a2950af..09007ad96 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -144,7 +144,7 @@ class Controller extends BaseController } } - public function revoke_invitation() + public function revokeInvitation() { $invitation = TeamInvitation::whereUuid(request()->route('uuid'))->firstOrFail(); $user = User::whereEmail($invitation->email)->firstOrFail(); diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index eb7686c06..c9b7c9992 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -1381,8 +1381,8 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue if (is_object($this->source) && $this->source->getMorphClass() === \App\Models\GithubApp::class && $this->source->is_public === false) { $repository = githubApi($this->source, "repos/{$this->customRepository}"); $data = data_get($repository, 'data'); - if (isset($data->id)) { - $repository_project_id = $data->id; + $repository_project_id = data_get($data, 'id'); + if (isset($repository_project_id)) { if (blank($this->application->repository_project_id) || $this->application->repository_project_id !== $repository_project_id) { $this->application->repository_project_id = $repository_project_id; $this->application->save(); diff --git a/app/Livewire/Notifications/Email.php b/app/Livewire/Notifications/Email.php index 897e6cf06..128321ed2 100644 --- a/app/Livewire/Notifications/Email.php +++ b/app/Livewire/Notifications/Email.php @@ -254,10 +254,9 @@ class Email extends Component 'smtpEncryption.required' => 'Encryption type is required.', ]); - $this->settings->resend_enabled = false; - $this->settings->use_instance_email_settings = false; - $this->resendEnabled = false; - $this->useInstanceEmailSettings = false; + if ($this->smtpEnabled) { + $this->settings->resend_enabled = $this->resendEnabled = false; + } $this->settings->smtp_enabled = $this->smtpEnabled; $this->settings->smtp_from_address = $this->smtpFromAddress; @@ -293,11 +292,9 @@ class Email extends Component 'smtpFromAddress.email' => 'Please enter a valid email address.', 'smtpFromName.required' => 'From Name is required.', ]); - - $this->settings->smtp_enabled = false; - $this->settings->use_instance_email_settings = false; - $this->smtpEnabled = false; - $this->useInstanceEmailSettings = false; + if ($this->resendEnabled) { + $this->settings->smtp_enabled = $this->smtpEnabled = false; + } $this->settings->resend_enabled = $this->resendEnabled; $this->settings->resend_api_key = $this->resendApiKey; diff --git a/app/Livewire/Project/Application/Source.php b/app/Livewire/Project/Application/Source.php index e27a550c1..932a302ad 100644 --- a/app/Livewire/Project/Application/Source.php +++ b/app/Livewire/Project/Application/Source.php @@ -111,8 +111,19 @@ class Source extends Component $this->application->update([ 'source_id' => $sourceId, 'source_type' => $sourceType, - 'repository_project_id' => null, ]); + + ['repository' => $customRepository] = $this->application->customRepository(); + $repository = githubApi($this->application->source, "repos/{$customRepository}"); + $data = data_get($repository, 'data'); + $repository_project_id = data_get($data, 'id'); + if (isset($repository_project_id)) { + if ($this->application->repository_project_id !== $repository_project_id) { + $this->application->repository_project_id = $repository_project_id; + $this->application->save(); + } + } + $this->application->refresh(); $this->getSources(); $this->dispatch('success', 'Source updated!'); diff --git a/app/Livewire/Project/Service/Heading.php b/app/Livewire/Project/Service/Heading.php index eb7f469a8..d78fbe9ed 100644 --- a/app/Livewire/Project/Service/Heading.php +++ b/app/Livewire/Project/Service/Heading.php @@ -6,7 +6,6 @@ use App\Actions\Docker\GetContainersStatus; use App\Actions\Service\StartService; use App\Actions\Service\StopService; use App\Enums\ProcessStatus; -use App\Events\ServiceStatusChanged; use App\Models\Service; use Illuminate\Support\Facades\Auth; use Livewire\Component; @@ -96,7 +95,7 @@ class Heading extends Component public function start() { $activity = StartService::run($this->service, pullLatestImages: true); - $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); + $this->dispatch('activityMonitor', $activity->id); } public function forceDeploy() @@ -112,7 +111,7 @@ class Heading extends Component $activity->save(); } $activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true); - $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); + $this->dispatch('activityMonitor', $activity->id); } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); } @@ -136,7 +135,7 @@ class Heading extends Component return; } $activity = StartService::run($this->service, stopBeforeStart: true); - $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); + $this->dispatch('activityMonitor', $activity->id); } public function pullAndRestartEvent() @@ -148,7 +147,7 @@ class Heading extends Component return; } $activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true); - $this->dispatch('activityMonitor', $activity->id, ServiceStatusChanged::class); + $this->dispatch('activityMonitor', $activity->id); } public function render() diff --git a/app/Livewire/Server/Proxy.php b/app/Livewire/Server/Proxy.php index 9332c2517..1cf8c839e 100644 --- a/app/Livewire/Server/Proxy.php +++ b/app/Livewire/Server/Proxy.php @@ -19,7 +19,15 @@ class Proxy extends Component public ?string $redirect_url = null; - protected $listeners = ['saveConfiguration' => 'submit']; + public function getListeners() + { + $teamId = auth()->user()->currentTeam()->id; + + return [ + 'saveConfiguration' => 'submit', + "echo-private:team.{$teamId},ProxyStatusChangedUI" => '$refresh', + ]; + } protected $rules = [ 'server.settings.generate_exact_labels' => 'required|boolean', diff --git a/app/Livewire/Server/Security/Patches.php b/app/Livewire/Server/Security/Patches.php index 9392fc351..b7d17a61d 100644 --- a/app/Livewire/Server/Security/Patches.php +++ b/app/Livewire/Server/Security/Patches.php @@ -69,6 +69,7 @@ class Patches extends Component { if (! $this->packageManager || ! $this->osId) { $this->dispatch('error', message: 'Run “Check for updates” first.'); + return; } diff --git a/app/Livewire/Server/Show.php b/app/Livewire/Server/Show.php index d803ff6a6..d53f10d74 100644 --- a/app/Livewire/Server/Show.php +++ b/app/Livewire/Server/Show.php @@ -176,7 +176,7 @@ class Show extends Component $this->sentinelCustomUrl = $this->server->settings->sentinel_custom_url; $this->isSentinelEnabled = $this->server->settings->is_sentinel_enabled; $this->isSentinelDebugEnabled = $this->server->settings->is_sentinel_debug_enabled; - $this->sentinelUpdatedAt = $this->server->settings->updated_at; + $this->sentinelUpdatedAt = $this->server->sentinel_updated_at; $this->serverTimezone = $this->server->settings->server_timezone; } } diff --git a/app/Livewire/Settings/Index.php b/app/Livewire/Settings/Index.php index 3d90024b7..f9df7ee33 100644 --- a/app/Livewire/Settings/Index.php +++ b/app/Livewire/Settings/Index.php @@ -68,6 +68,9 @@ class Index extends Component #[Validate('boolean')] public bool $disable_two_step_confirmation; + #[Validate('boolean')] + public bool $is_sponsorship_popup_enabled; + public function render() { return view('livewire.settings.index'); @@ -96,6 +99,7 @@ class Index extends Component $this->update_check_frequency = $this->settings->update_check_frequency; $this->instance_timezone = $this->settings->instance_timezone; $this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation; + $this->is_sponsorship_popup_enabled = $this->settings->is_sponsorship_popup_enabled; } } @@ -134,6 +138,7 @@ class Index extends Component $this->settings->update_check_frequency = $this->update_check_frequency; $this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation; $this->settings->instance_timezone = $this->instance_timezone; + $this->settings->is_sponsorship_popup_enabled = $this->is_sponsorship_popup_enabled; if ($isSave) { $this->settings->save(); $this->dispatch('success', 'Settings updated!'); diff --git a/app/Livewire/Team/AdminView.php b/app/Livewire/Team/AdminView.php index cfb47d9d8..6d6915ae2 100644 --- a/app/Livewire/Team/AdminView.php +++ b/app/Livewire/Team/AdminView.php @@ -3,7 +3,6 @@ namespace App\Livewire\Team; use App\Models\InstanceSettings; -use App\Models\Team; use App\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; @@ -53,30 +52,12 @@ class AdminView extends Component } } - private function finalizeDeletion(User $user, Team $team) - { - $servers = $team->servers; - foreach ($servers as $server) { - $resources = $server->definedResources(); - foreach ($resources as $resource) { - $resource->forceDelete(); - } - $server->forceDelete(); - } - - $projects = $team->projects; - foreach ($projects as $project) { - $project->forceDelete(); - } - $team->members()->detach($user->id); - $team->delete(); - } - public function delete($id, $password) { if (! isInstanceAdmin()) { return redirect()->route('dashboard'); } + if (! data_get(InstanceSettings::get(), 'disable_two_step_confirmation')) { if (! Hash::check($password, Auth::user()->password)) { $this->addError('password', 'The provided password is incorrect.'); @@ -84,52 +65,22 @@ class AdminView extends Component return; } } + if (! auth()->user()->isInstanceAdmin()) { return $this->dispatch('error', 'You are not authorized to delete users'); } + $user = User::find($id); - $teams = $user->teams; - foreach ($teams as $team) { - $user_alone_in_team = $team->members->count() === 1; - if ($team->id === 0) { - if ($user_alone_in_team) { - return $this->dispatch('error', 'User is alone in the root team, cannot delete'); - } - } - if ($user_alone_in_team) { - $this->finalizeDeletion($user, $team); - - continue; - } - if ($user->isOwner()) { - $found_other_owner_or_admin = $team->members->filter(function ($member) { - return $member->pivot->role === 'owner' || $member->pivot->role === 'admin'; - })->where('id', '!=', $user->id)->first(); - - if ($found_other_owner_or_admin) { - $team->members()->detach($user->id); - - continue; - } else { - $found_other_member_who_is_not_owner = $team->members->filter(function ($member) { - return $member->pivot->role === 'member'; - })->first(); - if ($found_other_member_who_is_not_owner) { - $found_other_member_who_is_not_owner->pivot->role = 'owner'; - $found_other_member_who_is_not_owner->pivot->save(); - $team->members()->detach($user->id); - } else { - $this->finalizeDeletion($user, $team); - } - - continue; - } - } else { - $team->members()->detach($user->id); - } + if (! $user) { + return $this->dispatch('error', 'User not found'); + } + + try { + $user->delete(); + $this->getUsers(); + } catch (\Exception $e) { + return $this->dispatch('error', $e->getMessage()); } - $user->delete(); - $this->getUsers(); } public function render() diff --git a/app/Livewire/Team/Invitations.php b/app/Livewire/Team/Invitations.php index 93432efc8..3af0e0e92 100644 --- a/app/Livewire/Team/Invitations.php +++ b/app/Livewire/Team/Invitations.php @@ -3,6 +3,7 @@ namespace App\Livewire\Team; use App\Models\TeamInvitation; +use App\Models\User; use Livewire\Component; class Invitations extends Component @@ -14,8 +15,13 @@ class Invitations extends Component public function deleteInvitation(int $invitation_id) { try { - $initiation_found = TeamInvitation::ownedByCurrentTeam()->findOrFail($invitation_id); - $initiation_found->delete(); + $invitation = TeamInvitation::ownedByCurrentTeam()->findOrFail($invitation_id); + $user = User::whereEmail($invitation->email)->first(); + if (filled($user)) { + $user->deleteIfNotVerifiedAndForcePasswordReset(); + } + + $invitation->delete(); $this->refreshInvitations(); $this->dispatch('success', 'Invitation revoked.'); } catch (\Exception) { diff --git a/app/Livewire/Team/InviteLink.php b/app/Livewire/Team/InviteLink.php index 25f8a1ff5..fb0c51e54 100644 --- a/app/Livewire/Team/InviteLink.php +++ b/app/Livewire/Team/InviteLink.php @@ -29,15 +29,15 @@ class InviteLink extends Component public function viaEmail() { - $this->generate_invite_link(sendEmail: true); + $this->generateInviteLink(sendEmail: true); } public function viaLink() { - $this->generate_invite_link(sendEmail: false); + $this->generateInviteLink(sendEmail: false); } - private function generate_invite_link(bool $sendEmail = false) + private function generateInviteLink(bool $sendEmail = false) { try { $this->validate(); diff --git a/app/Models/OauthSetting.php b/app/Models/OauthSetting.php index bfd332c87..08e08d85b 100644 --- a/app/Models/OauthSetting.php +++ b/app/Models/OauthSetting.php @@ -27,6 +27,7 @@ class OauthSetting extends Model case 'azure': return filled($this->client_id) && filled($this->client_secret) && filled($this->tenant); case 'authentik': + case 'clerk': return filled($this->client_id) && filled($this->client_secret) && filled($this->base_url); default: return filled($this->client_id) && filled($this->client_secret); diff --git a/app/Models/Service.php b/app/Models/Service.php index c3c8f3215..a9302d7e7 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Enums\ProcessStatus; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; @@ -9,6 +10,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Storage; use OpenApi\Attributes as OA; +use Spatie\Activitylog\Models\Activity; use Spatie\Url\Url; use Visus\Cuid2\Cuid2; @@ -116,6 +118,18 @@ class Service extends BaseModel return (bool) str($this->status)->contains('exited'); } + public function isStarting(): bool + { + try { + $activity = Activity::where('properties->type_uuid', $this->uuid)->latest()->first(); + $status = data_get($activity, 'properties.status'); + + return $status === ProcessStatus::QUEUED->value || $status === ProcessStatus::IN_PROGRESS->value; + } catch (\Throwable) { + return false; + } + } + public function type() { return 'service'; @@ -159,6 +173,10 @@ class Service extends BaseModel public function getStatusAttribute() { + if ($this->isStarting()) { + return 'starting:unhealthy'; + } + $applications = $this->applications; $databases = $this->databases; diff --git a/app/Models/TeamInvitation.php b/app/Models/TeamInvitation.php index bc1a90d58..0fea1806b 100644 --- a/app/Models/TeamInvitation.php +++ b/app/Models/TeamInvitation.php @@ -33,6 +33,10 @@ class TeamInvitation extends Model return true; } else { $this->delete(); + $user = User::whereEmail($this->email)->first(); + if (filled($user)) { + $user->deleteIfNotVerifiedAndForcePasswordReset(); + } return false; } diff --git a/app/Models/User.php b/app/Models/User.php index f9515ad09..6cd1b66db 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -72,6 +72,93 @@ class User extends Authenticatable implements SendsEmail $new_team = Team::create($team); $user->teams()->attach($new_team, ['role' => 'owner']); }); + + static::deleting(function (User $user) { + \DB::transaction(function () use ($user) { + $teams = $user->teams; + foreach ($teams as $team) { + $user_alone_in_team = $team->members->count() === 1; + + // Prevent deletion if user is alone in root team + if ($team->id === 0 && $user_alone_in_team) { + throw new \Exception('User is alone in the root team, cannot delete'); + } + + if ($user_alone_in_team) { + static::finalizeTeamDeletion($user, $team); + // Delete any pending team invitations for this user + TeamInvitation::whereEmail($user->email)->delete(); + + continue; + } + + // Load the user's role for this team + $userRole = $team->members->where('id', $user->id)->first()?->pivot?->role; + + if ($userRole === 'owner') { + $found_other_owner_or_admin = $team->members->filter(function ($member) use ($user) { + return ($member->pivot->role === 'owner' || $member->pivot->role === 'admin') && $member->id !== $user->id; + })->first(); + + if ($found_other_owner_or_admin) { + $team->members()->detach($user->id); + + continue; + } else { + $found_other_member_who_is_not_owner = $team->members->filter(function ($member) { + return $member->pivot->role === 'member'; + })->first(); + + if ($found_other_member_who_is_not_owner) { + $found_other_member_who_is_not_owner->pivot->role = 'owner'; + $found_other_member_who_is_not_owner->pivot->save(); + $team->members()->detach($user->id); + } else { + static::finalizeTeamDeletion($user, $team); + } + + continue; + } + } else { + $team->members()->detach($user->id); + } + } + }); + }); + } + + /** + * Finalize team deletion by cleaning up all associated resources + */ + private static function finalizeTeamDeletion(User $user, Team $team) + { + $servers = $team->servers; + foreach ($servers as $server) { + $resources = $server->definedResources(); + foreach ($resources as $resource) { + $resource->forceDelete(); + } + $server->forceDelete(); + } + + $projects = $team->projects; + foreach ($projects as $project) { + $project->forceDelete(); + } + + $team->members()->detach($user->id); + $team->delete(); + } + + /** + * Delete the user if they are not verified and have a force password reset. + * This is used to clean up users that have been invited, did not accept the invitation (and did not verify their email and have a force password reset). + */ + public function deleteIfNotVerifiedAndForcePasswordReset() + { + if ($this->hasVerifiedEmail() === false && $this->force_password_reset === true) { + $this->delete(); + } } public function recreate_personal_team() diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index b960dd8e3..2d9910add 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -9,9 +9,12 @@ use Illuminate\Foundation\Events\MaintenanceModeEnabled; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use SocialiteProviders\Authentik\AuthentikExtendSocialite; use SocialiteProviders\Azure\AzureExtendSocialite; +use SocialiteProviders\Clerk\ClerkExtendSocialite; +use SocialiteProviders\Discord\DiscordExtendSocialite; use SocialiteProviders\Google\GoogleExtendSocialite; use SocialiteProviders\Infomaniak\InfomaniakExtendSocialite; use SocialiteProviders\Manager\SocialiteWasCalled; +use SocialiteProviders\Zitadel\ZitadelExtendSocialite; class EventServiceProvider extends ServiceProvider { @@ -25,8 +28,11 @@ class EventServiceProvider extends ServiceProvider SocialiteWasCalled::class => [ AzureExtendSocialite::class.'@handle', AuthentikExtendSocialite::class.'@handle', + ClerkExtendSocialite::class.'@handle', + DiscordExtendSocialite::class.'@handle', GoogleExtendSocialite::class.'@handle', InfomaniakExtendSocialite::class.'@handle', + ZitadelExtendSocialite::class.'@handle', ], ]; diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index d1fccf416..2150126cd 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -49,7 +49,7 @@ class RouteServiceProvider extends ServiceProvider return Limit::perMinute(1000)->by($request->user()?->id ?: $request->ip()); } - return Limit::perMinute(config('api.throttle'))->by($request->user()?->id ?: $request->ip()); + return Limit::perMinute((int) config('api.rate_limit'))->by($request->user()?->id ?: $request->ip()); }); RateLimiter::for('5', function (Request $request) { return Limit::perMinute(5)->by($request->user()?->id ?: $request->ip()); diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 930f95041..944c51e3c 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -359,7 +359,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ { $labels = collect([]); $labels->push('traefik.enable=true'); - $labels->push('traefik.http.middlewares.gzip.compress=true'); + if ($is_gzip_enabled) { + $labels->push('traefik.http.middlewares.gzip.compress=true'); + } $labels->push('traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https'); $is_http_basic_auth_enabled = $is_http_basic_auth_enabled && $http_basic_auth_username !== null && $http_basic_auth_password !== null; diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 2f1b934bb..328e84b9d 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -2991,12 +2991,6 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $applicationFound = ServiceApplication::where('name', $serviceName)->where('service_id', $resource->id)->first(); if ($applicationFound) { $savedService = $applicationFound; - // $savedService = ServiceDatabase::firstOrCreate([ - // 'name' => $applicationFound->name, - // 'image' => $applicationFound->image, - // 'service_id' => $applicationFound->service_id, - // ]); - // $applicationFound->delete(); } else { $savedService = ServiceDatabase::firstOrCreate([ 'name' => $serviceName, @@ -3007,15 +3001,23 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $savedService = ServiceApplication::firstOrCreate([ 'name' => $serviceName, 'service_id' => $resource->id, + ], [ + 'is_gzip_enabled' => true, ]); } - // Check if image changed if ($savedService->image !== $image) { $savedService->image = $image; $savedService->save(); } } + + // Pocketbase does not need gzip for SSE. + if (str($savedService->image)->contains('pocketbase') && $savedService->is_gzip_enabled) { + $savedService->is_gzip_enabled = false; + $savedService->save(); + } + $environment = collect(data_get($service, 'environment', [])); $buildArgs = collect(data_get($service, 'build.args', [])); $environment = $environment->merge($buildArgs); @@ -3060,12 +3062,18 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int $port = null; } if ($isApplication) { - $fqdn = generateFqdn($server, "$uuid"); + $fqdn = $resource->fqdn; + if (blank($resource->fqdn)) { + $fqdn = generateFqdn($server, "$uuid"); + } } elseif ($isService) { - if ($fqdnFor) { - $fqdn = generateFqdn($server, "$fqdnFor-$uuid"); - } else { - $fqdn = generateFqdn($server, "{$savedService->name}-$uuid"); + $fqdn = $savedService->fqdn; + if (blank($savedService->fqdn)) { + if ($fqdnFor) { + $fqdn = generateFqdn($server, "$fqdnFor-$uuid"); + } else { + $fqdn = generateFqdn($server, "{$savedService->name}-$uuid"); + } } } @@ -3090,7 +3098,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int } if (substr_count(str($key)->value(), '_') === 2) { - $resource->environment_variables()->firstOrCreate([ + $resource->environment_variables()->updateOrCreate([ 'key' => $key->value(), 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, @@ -3102,7 +3110,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int } if (substr_count(str($key)->value(), '_') === 3) { $newKey = str($key)->beforeLast('_'); - $resource->environment_variables()->firstOrCreate([ + $resource->environment_variables()->updateOrCreate([ 'key' => $newKey->value(), 'resourceable_type' => get_class($resource), 'resourceable_id' => $resource->id, diff --git a/bootstrap/helpers/socialite.php b/bootstrap/helpers/socialite.php index fe19752cb..961f6809b 100644 --- a/bootstrap/helpers/socialite.php +++ b/bootstrap/helpers/socialite.php @@ -22,15 +22,26 @@ function get_socialite_provider(string $provider) return Socialite::driver('azure')->setConfig($azure_config); } - if ($provider == 'authentik') { - $authentik_config = new \SocialiteProviders\Manager\Config( + if ($provider == 'authentik' || $provider == 'clerk') { + $authentik_clerk_config = new \SocialiteProviders\Manager\Config( $oauth_setting->client_id, $oauth_setting->client_secret, $oauth_setting->redirect_uri, ['base_url' => $oauth_setting->base_url], ); - return Socialite::driver('authentik')->setConfig($authentik_config); + return Socialite::driver($provider)->setConfig($authentik_clerk_config); + } + + if ($provider == 'zitadel') { + $zitadel_config = new \SocialiteProviders\Manager\Config( + $oauth_setting->client_id, + $oauth_setting->client_secret, + $oauth_setting->redirect_uri, + ['base_url' => $oauth_setting->base_url], + ); + + return Socialite::driver('zitadel')->setConfig($zitadel_config); } if ($provider == 'google') { @@ -53,6 +64,7 @@ function get_socialite_provider(string $provider) $provider_class_map = [ 'bitbucket' => \Laravel\Socialite\Two\BitbucketProvider::class, + 'discord' => \SocialiteProviders\Discord\Provider::class, 'github' => \Laravel\Socialite\Two\GithubProvider::class, 'gitlab' => \Laravel\Socialite\Two\GitlabProvider::class, 'infomaniak' => \SocialiteProviders\Infomaniak\Provider::class, diff --git a/composer.json b/composer.json index 3fb1206ce..854ba1dab 100644 --- a/composer.json +++ b/composer.json @@ -36,12 +36,15 @@ "poliander/cron": "^3.2.1", "purplepixie/phpdns": "^2.2", "pusher/pusher-php-server": "^7.2.7", - "resend/resend-laravel": "^0.17.0", + "resend/resend-laravel": "^0.19.0", "sentry/sentry-laravel": "^4.13", "socialiteproviders/authentik": "^5.2", + "socialiteproviders/clerk": "^5.0", + "socialiteproviders/discord": "^4.2", "socialiteproviders/google": "^4.1", "socialiteproviders/infomaniak": "^4.0", "socialiteproviders/microsoft-azure": "^5.2", + "socialiteproviders/zitadel": "^4.1", "spatie/laravel-activitylog": "^4.10.1", "spatie/laravel-data": "^4.13.1", "spatie/laravel-ray": "^1.39.1", diff --git a/composer.lock b/composer.lock index 14ae57fcb..d655ad48d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "ae74a752b941c9b981288c2934479eb8", + "content-hash": "f1d647186c558d85c525f8a6314474d4", "packages": [ { "name": "amphp/amp", @@ -870,16 +870,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.343.20", + "version": "3.347.0", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "bf40b00d2e1cbd2a5d8c903743073440d8ebb5dc" + "reference": "c66a35e650f077caddd7db8d3a1f58b2c2b8c78b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/bf40b00d2e1cbd2a5d8c903743073440d8ebb5dc", - "reference": "bf40b00d2e1cbd2a5d8c903743073440d8ebb5dc", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/c66a35e650f077caddd7db8d3a1f58b2c2b8c78b", + "reference": "c66a35e650f077caddd7db8d3a1f58b2c2b8c78b", "shasum": "" }, "require": { @@ -961,9 +961,9 @@ "support": { "forum": "https://github.com/aws/aws-sdk-php/discussions", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.343.20" + "source": "https://github.com/aws/aws-sdk-php/tree/3.347.0" }, - "time": "2025-05-28T18:10:03+00:00" + "time": "2025-06-23T18:12:15+00:00" }, { "name": "bacon/bacon-qr-code", @@ -1021,16 +1021,16 @@ }, { "name": "brick/math", - "version": "0.12.3", + "version": "0.13.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", "shasum": "" }, "require": { @@ -1069,7 +1069,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.3" + "source": "https://github.com/brick/math/tree/0.13.1" }, "funding": [ { @@ -1077,7 +1077,7 @@ "type": "github" } ], - "time": "2025-02-28T13:11:00+00:00" + "time": "2025-03-29T13:50:30+00:00" }, { "name": "carbonphp/carbon-doctrine-types", @@ -1373,16 +1373,16 @@ }, { "name": "doctrine/dbal", - "version": "4.2.3", + "version": "4.2.4", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "33d2d7fe1269b2301640c44cf2896ea607b30e3e" + "reference": "b37d160498ea91a2382a2ebe825c4ea6254fc0ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/33d2d7fe1269b2301640c44cf2896ea607b30e3e", - "reference": "33d2d7fe1269b2301640c44cf2896ea607b30e3e", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/b37d160498ea91a2382a2ebe825c4ea6254fc0ec", + "reference": "b37d160498ea91a2382a2ebe825c4ea6254fc0ec", "shasum": "" }, "require": { @@ -1392,15 +1392,15 @@ "psr/log": "^1|^2|^3" }, "require-dev": { - "doctrine/coding-standard": "12.0.0", + "doctrine/coding-standard": "13.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.2", - "phpstan/phpstan": "2.1.1", - "phpstan/phpstan-phpunit": "2.0.3", + "phpstan/phpstan": "2.1.17", + "phpstan/phpstan-phpunit": "2.0.6", "phpstan/phpstan-strict-rules": "^2", - "phpunit/phpunit": "10.5.39", - "slevomat/coding-standard": "8.13.1", - "squizlabs/php_codesniffer": "3.10.2", + "phpunit/phpunit": "10.5.46", + "slevomat/coding-standard": "8.16.2", + "squizlabs/php_codesniffer": "3.13.1", "symfony/cache": "^6.3.8|^7.0", "symfony/console": "^5.4|^6.3|^7.0" }, @@ -1459,7 +1459,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/4.2.3" + "source": "https://github.com/doctrine/dbal/tree/4.2.4" }, "funding": [ { @@ -1475,7 +1475,7 @@ "type": "tidelift" } ], - "time": "2025-03-07T18:29:05+00:00" + "time": "2025-06-15T23:15:01+00:00" }, { "name": "doctrine/deprecations", @@ -2613,16 +2613,16 @@ }, { "name": "laravel/fortify", - "version": "v1.25.4", + "version": "v1.27.0", "source": { "type": "git", "url": "https://github.com/laravel/fortify.git", - "reference": "f185600e2d3a861834ad00ee3b7863f26ac25d3f" + "reference": "0fb2ec99dfee77ed66884668fc06683acca91ebd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/fortify/zipball/f185600e2d3a861834ad00ee3b7863f26ac25d3f", - "reference": "f185600e2d3a861834ad00ee3b7863f26ac25d3f", + "url": "https://api.github.com/repos/laravel/fortify/zipball/0fb2ec99dfee77ed66884668fc06683acca91ebd", + "reference": "0fb2ec99dfee77ed66884668fc06683acca91ebd", "shasum": "" }, "require": { @@ -2674,24 +2674,24 @@ "issues": "https://github.com/laravel/fortify/issues", "source": "https://github.com/laravel/fortify" }, - "time": "2025-01-26T19:34:46+00:00" + "time": "2025-06-11T14:30:52+00:00" }, { "name": "laravel/framework", - "version": "v12.16.0", + "version": "v12.19.3", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "293bb1c70224faebfd3d4328e201c37115da055f" + "reference": "4e6ec689ef704bb4bd282f29d9dd658dfb4fb262" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/293bb1c70224faebfd3d4328e201c37115da055f", - "reference": "293bb1c70224faebfd3d4328e201c37115da055f", + "url": "https://api.github.com/repos/laravel/framework/zipball/4e6ec689ef704bb4bd282f29d9dd658dfb4fb262", + "reference": "4e6ec689ef704bb4bd282f29d9dd658dfb4fb262", "shasum": "" }, "require": { - "brick/math": "^0.11|^0.12", + "brick/math": "^0.11|^0.12|^0.13", "composer-runtime-api": "^2.2", "doctrine/inflector": "^2.0.5", "dragonmantank/cron-expression": "^3.4", @@ -2889,20 +2889,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2025-05-27T15:49:44+00:00" + "time": "2025-06-18T12:56:23+00:00" }, { "name": "laravel/horizon", - "version": "v5.32.1", + "version": "v5.33.1", "source": { "type": "git", "url": "https://github.com/laravel/horizon.git", - "reference": "e78d9689d85b3d4769dc64def5eb6d94e5776beb" + "reference": "50057bca1f1dcc9fbd5ff6d65143833babd784b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/horizon/zipball/e78d9689d85b3d4769dc64def5eb6d94e5776beb", - "reference": "e78d9689d85b3d4769dc64def5eb6d94e5776beb", + "url": "https://api.github.com/repos/laravel/horizon/zipball/50057bca1f1dcc9fbd5ff6d65143833babd784b3", + "reference": "50057bca1f1dcc9fbd5ff6d65143833babd784b3", "shasum": "" }, "require": { @@ -2967,22 +2967,22 @@ ], "support": { "issues": "https://github.com/laravel/horizon/issues", - "source": "https://github.com/laravel/horizon/tree/v5.32.1" + "source": "https://github.com/laravel/horizon/tree/v5.33.1" }, - "time": "2025-05-19T13:13:30+00:00" + "time": "2025-06-16T13:48:30+00:00" }, { "name": "laravel/pail", - "version": "v1.2.2", + "version": "v1.2.3", "source": { "type": "git", "url": "https://github.com/laravel/pail.git", - "reference": "f31f4980f52be17c4667f3eafe034e6826787db2" + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/pail/zipball/f31f4980f52be17c4667f3eafe034e6826787db2", - "reference": "f31f4980f52be17c4667f3eafe034e6826787db2", + "url": "https://api.github.com/repos/laravel/pail/zipball/8cc3d575c1f0e57eeb923f366a37528c50d2385a", + "reference": "8cc3d575c1f0e57eeb923f366a37528c50d2385a", "shasum": "" }, "require": { @@ -3002,7 +3002,7 @@ "orchestra/testbench-core": "^8.13|^9.0|^10.0", "pestphp/pest": "^2.20|^3.0", "pestphp/pest-plugin-type-coverage": "^2.3|^3.0", - "phpstan/phpstan": "^1.10", + "phpstan/phpstan": "^1.12.27", "symfony/var-dumper": "^6.3|^7.0" }, "type": "library", @@ -3038,6 +3038,7 @@ "description": "Easily delve into your Laravel application's log files directly from the command line.", "homepage": "https://github.com/laravel/pail", "keywords": [ + "dev", "laravel", "logs", "php", @@ -3047,7 +3048,7 @@ "issues": "https://github.com/laravel/pail/issues", "source": "https://github.com/laravel/pail" }, - "time": "2025-01-28T15:15:15+00:00" + "time": "2025-06-05T13:55:57+00:00" }, { "name": "laravel/prompts", @@ -4695,16 +4696,16 @@ }, { "name": "nesbot/carbon", - "version": "3.9.1", + "version": "3.10.1", "source": { "type": "git", "url": "https://github.com/CarbonPHP/carbon.git", - "reference": "ced71f79398ece168e24f7f7710462f462310d4d" + "reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/ced71f79398ece168e24f7f7710462f462310d4d", - "reference": "ced71f79398ece168e24f7f7710462f462310d4d", + "url": "https://api.github.com/repos/CarbonPHP/carbon/zipball/1fd1935b2d90aef2f093c5e35f7ae1257c448d00", + "reference": "1fd1935b2d90aef2f093c5e35f7ae1257c448d00", "shasum": "" }, "require": { @@ -4712,9 +4713,9 @@ "ext-json": "*", "php": "^8.1", "psr/clock": "^1.0", - "symfony/clock": "^6.3 || ^7.0", + "symfony/clock": "^6.3.12 || ^7.0", "symfony/polyfill-mbstring": "^1.0", - "symfony/translation": "^4.4.18 || ^5.2.1|| ^6.0 || ^7.0" + "symfony/translation": "^4.4.18 || ^5.2.1 || ^6.0 || ^7.0" }, "provide": { "psr/clock-implementation": "1.0" @@ -4722,14 +4723,13 @@ "require-dev": { "doctrine/dbal": "^3.6.3 || ^4.0", "doctrine/orm": "^2.15.2 || ^3.0", - "friendsofphp/php-cs-fixer": "^3.57.2", + "friendsofphp/php-cs-fixer": "^3.75.0", "kylekatarnls/multi-tester": "^2.5.3", - "ondrejmirtes/better-reflection": "^6.25.0.4", "phpmd/phpmd": "^2.15.0", - "phpstan/extension-installer": "^1.3.1", - "phpstan/phpstan": "^1.11.2", - "phpunit/phpunit": "^10.5.20", - "squizlabs/php_codesniffer": "^3.9.0" + "phpstan/extension-installer": "^1.4.3", + "phpstan/phpstan": "^2.1.17", + "phpunit/phpunit": "^10.5.46", + "squizlabs/php_codesniffer": "^3.13.0" }, "bin": [ "bin/carbon" @@ -4797,7 +4797,7 @@ "type": "tidelift" } ], - "time": "2025-05-01T19:51:51+00:00" + "time": "2025-06-21T15:19:35+00:00" }, { "name": "nette/schema", @@ -4863,16 +4863,16 @@ }, { "name": "nette/utils", - "version": "v4.0.6", + "version": "v4.0.7", "source": { "type": "git", "url": "https://github.com/nette/utils.git", - "reference": "ce708655043c7050eb050df361c5e313cf708309" + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nette/utils/zipball/ce708655043c7050eb050df361c5e313cf708309", - "reference": "ce708655043c7050eb050df361c5e313cf708309", + "url": "https://api.github.com/repos/nette/utils/zipball/e67c4061eb40b9c113b218214e42cb5a0dda28f2", + "reference": "e67c4061eb40b9c113b218214e42cb5a0dda28f2", "shasum": "" }, "require": { @@ -4943,22 +4943,22 @@ ], "support": { "issues": "https://github.com/nette/utils/issues", - "source": "https://github.com/nette/utils/tree/v4.0.6" + "source": "https://github.com/nette/utils/tree/v4.0.7" }, - "time": "2025-03-30T21:06:30+00:00" + "time": "2025-06-03T04:55:08+00:00" }, { "name": "nikic/php-parser", - "version": "v5.4.0", + "version": "v5.5.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", "shasum": "" }, "require": { @@ -5001,9 +5001,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" }, - "time": "2024-12-30T11:07:19+00:00" + "time": "2025-05-31T08:24:38+00:00" }, { "name": "nubs/random-name-generator", @@ -5488,16 +5488,16 @@ }, { "name": "php-di/php-di", - "version": "7.0.10", + "version": "7.0.11", "source": { "type": "git", "url": "https://github.com/PHP-DI/PHP-DI.git", - "reference": "0d1ed64126577e9a095b3204dcaee58cf76432c2" + "reference": "32f111a6d214564520a57831d397263e8946c1d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/0d1ed64126577e9a095b3204dcaee58cf76432c2", - "reference": "0d1ed64126577e9a095b3204dcaee58cf76432c2", + "url": "https://api.github.com/repos/PHP-DI/PHP-DI/zipball/32f111a6d214564520a57831d397263e8946c1d2", + "reference": "32f111a6d214564520a57831d397263e8946c1d2", "shasum": "" }, "require": { @@ -5545,7 +5545,7 @@ ], "support": { "issues": "https://github.com/PHP-DI/PHP-DI/issues", - "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.10" + "source": "https://github.com/PHP-DI/PHP-DI/tree/7.0.11" }, "funding": [ { @@ -5557,23 +5557,24 @@ "type": "tidelift" } ], - "time": "2025-04-22T08:53:15+00:00" + "time": "2025-06-03T07:45:57+00:00" }, { "name": "phpdocumentor/reflection", - "version": "6.1.0", + "version": "6.3.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/Reflection.git", - "reference": "bb4dea805a645553d6d989b23dad9f8041f39502" + "reference": "d91b3270832785602adcc24ae2d0974ba99a8ff8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/bb4dea805a645553d6d989b23dad9f8041f39502", - "reference": "bb4dea805a645553d6d989b23dad9f8041f39502", + "url": "https://api.github.com/repos/phpDocumentor/Reflection/zipball/d91b3270832785602adcc24ae2d0974ba99a8ff8", + "reference": "d91b3270832785602adcc24ae2d0974ba99a8ff8", "shasum": "" }, "require": { + "composer-runtime-api": "^2", "nikic/php-parser": "~4.18 || ^5.0", "php": "8.1.*|8.2.*|8.3.*|8.4.*", "phpdocumentor/reflection-common": "^2.1", @@ -5584,7 +5585,8 @@ }, "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^1.0", - "doctrine/coding-standard": "^12.0", + "doctrine/coding-standard": "^13.0", + "eliashaeussler/phpunit-attributes": "^1.7", "mikey179/vfsstream": "~1.2", "mockery/mockery": "~1.6.0", "phpspec/prophecy-phpunit": "^2.0", @@ -5592,7 +5594,7 @@ "phpstan/phpstan": "^1.8", "phpstan/phpstan-webmozart-assert": "^1.2", "phpunit/phpunit": "^10.0", - "psalm/phar": "^5.24", + "psalm/phar": "^6.0", "rector/rector": "^1.0.0", "squizlabs/php_codesniffer": "^3.8" }, @@ -5604,6 +5606,9 @@ } }, "autoload": { + "files": [ + "src/php-parser/Modifiers.php" + ], "psr-4": { "phpDocumentor\\": "src/phpDocumentor" } @@ -5622,9 +5627,9 @@ ], "support": { "issues": "https://github.com/phpDocumentor/Reflection/issues", - "source": "https://github.com/phpDocumentor/Reflection/tree/6.1.0" + "source": "https://github.com/phpDocumentor/Reflection/tree/6.3.0" }, - "time": "2024-11-22T15:11:54+00:00" + "time": "2025-06-06T13:39:18+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -5878,16 +5883,16 @@ }, { "name": "phpseclib/phpseclib", - "version": "3.0.43", + "version": "3.0.45", "source": { "type": "git", "url": "https://github.com/phpseclib/phpseclib.git", - "reference": "709ec107af3cb2f385b9617be72af8cf62441d02" + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/709ec107af3cb2f385b9617be72af8cf62441d02", - "reference": "709ec107af3cb2f385b9617be72af8cf62441d02", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/bd81b90d5963c6b9d87de50357585375223f4dd8", + "reference": "bd81b90d5963c6b9d87de50357585375223f4dd8", "shasum": "" }, "require": { @@ -5968,7 +5973,7 @@ ], "support": { "issues": "https://github.com/phpseclib/phpseclib/issues", - "source": "https://github.com/phpseclib/phpseclib/tree/3.0.43" + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.45" }, "funding": [ { @@ -5984,7 +5989,7 @@ "type": "tidelift" } ], - "time": "2024-12-14T21:12:59+00:00" + "time": "2025-06-22T22:54:43+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -6658,16 +6663,16 @@ }, { "name": "psy/psysh", - "version": "v0.12.8", + "version": "v0.12.9", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "85057ceedee50c49d4f6ecaff73ee96adb3b3625" + "reference": "1b801844becfe648985372cb4b12ad6840245ace" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/85057ceedee50c49d4f6ecaff73ee96adb3b3625", - "reference": "85057ceedee50c49d4f6ecaff73ee96adb3b3625", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/1b801844becfe648985372cb4b12ad6840245ace", + "reference": "1b801844becfe648985372cb4b12ad6840245ace", "shasum": "" }, "require": { @@ -6731,9 +6736,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.12.8" + "source": "https://github.com/bobthecow/psysh/tree/v0.12.9" }, - "time": "2025-03-16T03:05:19+00:00" + "time": "2025-06-23T02:35:06+00:00" }, { "name": "purplepixie/phpdns", @@ -6966,20 +6971,20 @@ }, { "name": "ramsey/uuid", - "version": "4.7.6", + "version": "4.8.1", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" @@ -6988,26 +6993,23 @@ "rhumsaa/uuid": "self.version" }, "require-dev": { - "captainhook/captainhook": "^5.10", + "captainhook/captainhook": "^5.25", "captainhook/plugin-composer": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "doctrine/annotations": "^1.8", - "ergebnis/composer-normalize": "^2.15", - "mockery/mockery": "^1.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", "paragonie/random-lib": "^2", - "php-mock/php-mock": "^2.2", - "php-mock/php-mock-mockery": "^1.3", - "php-parallel-lint/php-parallel-lint": "^1.1", - "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9", - "ramsey/composer-repl": "^1.4", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.9" + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" }, "suggest": { "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", @@ -7042,39 +7044,29 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.6" + "source": "https://github.com/ramsey/uuid/tree/4.8.1" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", - "type": "tidelift" - } - ], - "time": "2024-04-27T21:32:50+00:00" + "time": "2025-06-01T06:28:46+00:00" }, { "name": "resend/resend-laravel", - "version": "v0.17.0", + "version": "v0.19.0", "source": { "type": "git", "url": "https://github.com/resend/resend-laravel.git", - "reference": "fbdf51872ff296af545d72acc6de03c0d910202c" + "reference": "ce11e363c42c1d6b93983dfebbaba3f906863c3a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/resend/resend-laravel/zipball/fbdf51872ff296af545d72acc6de03c0d910202c", - "reference": "fbdf51872ff296af545d72acc6de03c0d910202c", + "url": "https://api.github.com/repos/resend/resend-laravel/zipball/ce11e363c42c1d6b93983dfebbaba3f906863c3a", + "reference": "ce11e363c42c1d6b93983dfebbaba3f906863c3a", "shasum": "" }, "require": { "illuminate/http": "^10.0|^11.0|^12.0", "illuminate/support": "^10.0|^11.0|^12.0", "php": "^8.1", - "resend/resend-php": "^0.16.0", + "resend/resend-php": "^0.18.0", "symfony/mailer": "^6.2|^7.0" }, "require-dev": { @@ -7121,22 +7113,22 @@ ], "support": { "issues": "https://github.com/resend/resend-laravel/issues", - "source": "https://github.com/resend/resend-laravel/tree/v0.17.0" + "source": "https://github.com/resend/resend-laravel/tree/v0.19.0" }, - "time": "2025-03-25T00:42:52+00:00" + "time": "2025-05-06T21:36:51+00:00" }, { "name": "resend/resend-php", - "version": "v0.16.0", + "version": "v0.18.0", "source": { "type": "git", "url": "https://github.com/resend/resend-php.git", - "reference": "6e9be898c9e0035a5da3c2904e86d0b12999c2fc" + "reference": "d6194782ff1952627bcdd52e5958572c4bd98043" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/resend/resend-php/zipball/6e9be898c9e0035a5da3c2904e86d0b12999c2fc", - "reference": "6e9be898c9e0035a5da3c2904e86d0b12999c2fc", + "url": "https://api.github.com/repos/resend/resend-php/zipball/d6194782ff1952627bcdd52e5958572c4bd98043", + "reference": "d6194782ff1952627bcdd52e5958572c4bd98043", "shasum": "" }, "require": { @@ -7178,9 +7170,9 @@ ], "support": { "issues": "https://github.com/resend/resend-php/issues", - "source": "https://github.com/resend/resend-php/tree/v0.16.0" + "source": "https://github.com/resend/resend-php/tree/v0.18.0" }, - "time": "2025-03-24T22:12:48+00:00" + "time": "2025-05-06T21:18:26+00:00" }, { "name": "revolt/event-loop", @@ -7256,16 +7248,16 @@ }, { "name": "sentry/sentry", - "version": "4.11.1", + "version": "4.14.1", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-php.git", - "reference": "53dc0bcb6a667cac5b760b46f98d5380e63e02ca" + "reference": "a28c4a6f5fda2bf730789a638501d7a737a64eda" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/53dc0bcb6a667cac5b760b46f98d5380e63e02ca", - "reference": "53dc0bcb6a667cac5b760b46f98d5380e63e02ca", + "url": "https://api.github.com/repos/getsentry/sentry-php/zipball/a28c4a6f5fda2bf730789a638501d7a737a64eda", + "reference": "a28c4a6f5fda2bf730789a638501d7a737a64eda", "shasum": "" }, "require": { @@ -7329,7 +7321,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-php/issues", - "source": "https://github.com/getsentry/sentry-php/tree/4.11.1" + "source": "https://github.com/getsentry/sentry-php/tree/4.14.1" }, "funding": [ { @@ -7341,27 +7333,27 @@ "type": "custom" } ], - "time": "2025-05-12T11:30:33+00:00" + "time": "2025-06-23T15:25:52+00:00" }, { "name": "sentry/sentry-laravel", - "version": "4.13.0", + "version": "4.15.1", "source": { "type": "git", "url": "https://github.com/getsentry/sentry-laravel.git", - "reference": "d232ac494258e0d50a77c575a5af5f1a426d3f87" + "reference": "7e0675e8e06d1ec5cb623792892920000a3aedb5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/d232ac494258e0d50a77c575a5af5f1a426d3f87", - "reference": "d232ac494258e0d50a77c575a5af5f1a426d3f87", + "url": "https://api.github.com/repos/getsentry/sentry-laravel/zipball/7e0675e8e06d1ec5cb623792892920000a3aedb5", + "reference": "7e0675e8e06d1ec5cb623792892920000a3aedb5", "shasum": "" }, "require": { "illuminate/support": "^6.0 | ^7.0 | ^8.0 | ^9.0 | ^10.0 | ^11.0 | ^12.0", "nyholm/psr7": "^1.0", "php": "^7.2 | ^8.0", - "sentry/sentry": "^4.10", + "sentry/sentry": "^4.14.1", "symfony/psr-http-message-bridge": "^1.0 | ^2.0 | ^6.0 | ^7.0" }, "require-dev": { @@ -7418,7 +7410,7 @@ ], "support": { "issues": "https://github.com/getsentry/sentry-laravel/issues", - "source": "https://github.com/getsentry/sentry-laravel/tree/4.13.0" + "source": "https://github.com/getsentry/sentry-laravel/tree/4.15.1" }, "funding": [ { @@ -7430,7 +7422,7 @@ "type": "custom" } ], - "time": "2025-02-18T10:09:29+00:00" + "time": "2025-06-24T12:39:03+00:00" }, { "name": "socialiteproviders/authentik", @@ -7482,6 +7474,106 @@ }, "time": "2023-11-07T22:21:16+00:00" }, + { + "name": "socialiteproviders/clerk", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/SocialiteProviders/Clerk.git", + "reference": "41e123036001ff37851b9622a910010c0e487d6a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SocialiteProviders/Clerk/zipball/41e123036001ff37851b9622a910010c0e487d6a", + "reference": "41e123036001ff37851b9622a910010c0e487d6a", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^8.0", + "socialiteproviders/manager": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "SocialiteProviders\\Clerk\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignacio Cano", + "email": "dev@nacho.sh" + } + ], + "description": "Clerk OAuth2 Provider for Laravel Socialite", + "keywords": [ + "clerk", + "laravel", + "oauth", + "provider", + "socialite" + ], + "support": { + "docs": "https://socialiteproviders.com/clerk", + "issues": "https://github.com/socialiteproviders/providers/issues", + "source": "https://github.com/socialiteproviders/providers" + }, + "time": "2024-02-19T12:17:59+00:00" + }, + { + "name": "socialiteproviders/discord", + "version": "4.2.0", + "source": { + "type": "git", + "url": "https://github.com/SocialiteProviders/Discord.git", + "reference": "c71c379acfdca5ba4aa65a3db5ae5222852a919c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SocialiteProviders/Discord/zipball/c71c379acfdca5ba4aa65a3db5ae5222852a919c", + "reference": "c71c379acfdca5ba4aa65a3db5ae5222852a919c", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^7.4 || ^8.0", + "socialiteproviders/manager": "~4.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "SocialiteProviders\\Discord\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christopher Eklund", + "email": "eklundchristopher@gmail.com" + } + ], + "description": "Discord OAuth2 Provider for Laravel Socialite", + "keywords": [ + "discord", + "laravel", + "oauth", + "provider", + "socialite" + ], + "support": { + "docs": "https://socialiteproviders.com/discord", + "issues": "https://github.com/socialiteproviders/providers/issues", + "source": "https://github.com/socialiteproviders/providers" + }, + "time": "2023-07-24T23:28:47+00:00" + }, { "name": "socialiteproviders/google", "version": "4.1.0", @@ -7699,6 +7791,49 @@ }, "time": "2024-03-15T03:02:10+00:00" }, + { + "name": "socialiteproviders/zitadel", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/SocialiteProviders/Zitadel.git", + "reference": "2e1c0843a9531eb0e31a04b31683a63f1a7d1865" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SocialiteProviders/Zitadel/zipball/2e1c0843a9531eb0e31a04b31683a63f1a7d1865", + "reference": "2e1c0843a9531eb0e31a04b31683a63f1a7d1865", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "^8.1", + "socialiteproviders/manager": "^4.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Socialiteproviders\\Zitadel\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gurkirat Singh", + "email": "tbhaxor@gmail.com" + } + ], + "description": "Zitadel OAuth2 Provider for Laravel Socialite", + "support": { + "docs": "https://socialiteproviders.com/zoho", + "issues": "https://github.com/socialiteproviders/providers/issues", + "source": "https://github.com/socialiteproviders/providers" + }, + "time": "2024-08-26T06:14:57+00:00" + }, { "name": "spatie/backtrace", "version": "1.7.4", @@ -7764,16 +7899,16 @@ }, { "name": "spatie/laravel-activitylog", - "version": "4.10.1", + "version": "4.10.2", "source": { "type": "git", "url": "https://github.com/spatie/laravel-activitylog.git", - "reference": "466f30f7245fe3a6e328ad5e6812bd43b4bddea5" + "reference": "bb879775d487438ed9a99e64f09086b608990c10" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/466f30f7245fe3a6e328ad5e6812bd43b4bddea5", - "reference": "466f30f7245fe3a6e328ad5e6812bd43b4bddea5", + "url": "https://api.github.com/repos/spatie/laravel-activitylog/zipball/bb879775d487438ed9a99e64f09086b608990c10", + "reference": "bb879775d487438ed9a99e64f09086b608990c10", "shasum": "" }, "require": { @@ -7839,7 +7974,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-activitylog/issues", - "source": "https://github.com/spatie/laravel-activitylog/tree/4.10.1" + "source": "https://github.com/spatie/laravel-activitylog/tree/4.10.2" }, "funding": [ { @@ -7851,20 +7986,20 @@ "type": "github" } ], - "time": "2025-02-10T15:38:25+00:00" + "time": "2025-06-15T06:59:49+00:00" }, { "name": "spatie/laravel-data", - "version": "4.15.1", + "version": "4.16.1", "source": { "type": "git", "url": "https://github.com/spatie/laravel-data.git", - "reference": "cb97afe6c0dadeb2e76ea1b7220cd04ed33dcca9" + "reference": "e652b52bdaca4774abb4a6024736850a1c4ab50b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-data/zipball/cb97afe6c0dadeb2e76ea1b7220cd04ed33dcca9", - "reference": "cb97afe6c0dadeb2e76ea1b7220cd04ed33dcca9", + "url": "https://api.github.com/repos/spatie/laravel-data/zipball/e652b52bdaca4774abb4a6024736850a1c4ab50b", + "reference": "e652b52bdaca4774abb4a6024736850a1c4ab50b", "shasum": "" }, "require": { @@ -7926,7 +8061,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-data/issues", - "source": "https://github.com/spatie/laravel-data/tree/4.15.1" + "source": "https://github.com/spatie/laravel-data/tree/4.16.1" }, "funding": [ { @@ -7934,7 +8069,7 @@ "type": "github" } ], - "time": "2025-04-10T06:06:27+00:00" + "time": "2025-06-24T08:19:42+00:00" }, { "name": "spatie/laravel-package-tools", @@ -12235,16 +12370,16 @@ }, { "name": "filp/whoops", - "version": "2.18.0", + "version": "2.18.3", "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e" + "reference": "59a123a3d459c5a23055802237cb317f609867e5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", - "reference": "a7de6c3c6c3c022f5cfc337f8ede6a14460cf77e", + "url": "https://api.github.com/repos/filp/whoops/zipball/59a123a3d459c5a23055802237cb317f609867e5", + "reference": "59a123a3d459c5a23055802237cb317f609867e5", "shasum": "" }, "require": { @@ -12294,7 +12429,7 @@ ], "support": { "issues": "https://github.com/filp/whoops/issues", - "source": "https://github.com/filp/whoops/tree/2.18.0" + "source": "https://github.com/filp/whoops/tree/2.18.3" }, "funding": [ { @@ -12302,7 +12437,7 @@ "type": "github" } ], - "time": "2025-03-15T12:00:00+00:00" + "time": "2025-06-16T00:02:10+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -12357,16 +12492,16 @@ }, { "name": "laravel/dusk", - "version": "v8.3.2", + "version": "v8.3.3", "source": { "type": "git", "url": "https://github.com/laravel/dusk.git", - "reference": "bb701836357bf6f6c6658ef90b5a0f8232affb0f" + "reference": "077d448cd993a08f97bfccf0ea3d6478b3908f7e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/dusk/zipball/bb701836357bf6f6c6658ef90b5a0f8232affb0f", - "reference": "bb701836357bf6f6c6658ef90b5a0f8232affb0f", + "url": "https://api.github.com/repos/laravel/dusk/zipball/077d448cd993a08f97bfccf0ea3d6478b3908f7e", + "reference": "077d448cd993a08f97bfccf0ea3d6478b3908f7e", "shasum": "" }, "require": { @@ -12425,9 +12560,9 @@ ], "support": { "issues": "https://github.com/laravel/dusk/issues", - "source": "https://github.com/laravel/dusk/tree/v8.3.2" + "source": "https://github.com/laravel/dusk/tree/v8.3.3" }, - "time": "2025-02-20T14:42:00+00:00" + "time": "2025-06-10T13:59:27+00:00" }, { "name": "laravel/pint", @@ -12497,16 +12632,16 @@ }, { "name": "laravel/telescope", - "version": "v5.8.0", + "version": "v5.9.1", "source": { "type": "git", "url": "https://github.com/laravel/telescope.git", - "reference": "9be1b8851b8ffe67689e7960135f8b32a966f23d" + "reference": "403d4ad1ecfe126139f5cf29cabd6b1c816c46a2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/telescope/zipball/9be1b8851b8ffe67689e7960135f8b32a966f23d", - "reference": "9be1b8851b8ffe67689e7960135f8b32a966f23d", + "url": "https://api.github.com/repos/laravel/telescope/zipball/403d4ad1ecfe126139f5cf29cabd6b1c816c46a2", + "reference": "403d4ad1ecfe126139f5cf29cabd6b1c816c46a2", "shasum": "" }, "require": { @@ -12560,9 +12695,9 @@ ], "support": { "issues": "https://github.com/laravel/telescope/issues", - "source": "https://github.com/laravel/telescope/tree/v5.8.0" + "source": "https://github.com/laravel/telescope/tree/v5.9.1" }, - "time": "2025-05-26T17:22:18+00:00" + "time": "2025-06-10T21:42:27+00:00" }, { "name": "mockery/mockery", @@ -12709,23 +12844,23 @@ }, { "name": "nunomaduro/collision", - "version": "v8.8.0", + "version": "v8.8.1", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8" + "reference": "44ccb82e3e21efb5446748d2a3c81a030ac22bd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/4cf9f3b47afff38b139fb79ce54fc71799022ce8", - "reference": "4cf9f3b47afff38b139fb79ce54fc71799022ce8", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/44ccb82e3e21efb5446748d2a3c81a030ac22bd5", + "reference": "44ccb82e3e21efb5446748d2a3c81a030ac22bd5", "shasum": "" }, "require": { - "filp/whoops": "^2.18.0", - "nunomaduro/termwind": "^2.3.0", + "filp/whoops": "^2.18.1", + "nunomaduro/termwind": "^2.3.1", "php": "^8.2.0", - "symfony/console": "^7.2.5" + "symfony/console": "^7.3.0" }, "conflict": { "laravel/framework": "<11.44.2 || >=13.0.0", @@ -12733,15 +12868,15 @@ }, "require-dev": { "brianium/paratest": "^7.8.3", - "larastan/larastan": "^3.2", - "laravel/framework": "^11.44.2 || ^12.6", - "laravel/pint": "^1.21.2", - "laravel/sail": "^1.41.0", - "laravel/sanctum": "^4.0.8", + "larastan/larastan": "^3.4.2", + "laravel/framework": "^11.44.2 || ^12.18", + "laravel/pint": "^1.22.1", + "laravel/sail": "^1.43.1", + "laravel/sanctum": "^4.1.1", "laravel/tinker": "^2.10.1", - "orchestra/testbench-core": "^9.12.0 || ^10.1", - "pestphp/pest": "^3.8.0", - "sebastian/environment": "^7.2.0 || ^8.0" + "orchestra/testbench-core": "^9.12.0 || ^10.4", + "pestphp/pest": "^3.8.2", + "sebastian/environment": "^7.2.1 || ^8.0" }, "type": "library", "extra": { @@ -12804,7 +12939,7 @@ "type": "patreon" } ], - "time": "2025-04-03T14:33:09+00:00" + "time": "2025-06-11T01:04:21+00:00" }, { "name": "pestphp/pest", @@ -13444,16 +13579,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "11.0.9", + "version": "11.0.10", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7" + "reference": "1a800a7446add2d79cc6b3c01c45381810367d76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/14d63fbcca18457e49c6f8bebaa91a87e8e188d7", - "reference": "14d63fbcca18457e49c6f8bebaa91a87e8e188d7", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1a800a7446add2d79cc6b3c01c45381810367d76", + "reference": "1a800a7446add2d79cc6b3c01c45381810367d76", "shasum": "" }, "require": { @@ -13510,15 +13645,27 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/11.0.9" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/show" }, "funding": [ { "url": "https://github.com/sebastianbergmann", "type": "github" + }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/php-code-coverage", + "type": "tidelift" } ], - "time": "2025-02-25T13:26:39+00:00" + "time": "2025-06-18T08:56:18+00:00" }, { "name": "phpunit/php-file-iterator", @@ -13868,21 +14015,21 @@ }, { "name": "rector/rector", - "version": "2.0.16", + "version": "2.0.18", "source": { "type": "git", "url": "https://github.com/rectorphp/rector.git", - "reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2" + "reference": "be3a452085b524a04056e3dfe72d861948711062" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/rectorphp/rector/zipball/f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2", - "reference": "f1366d1f8c7490541c8f7af6e5c7cef7cca1b5a2", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/be3a452085b524a04056e3dfe72d861948711062", + "reference": "be3a452085b524a04056e3dfe72d861948711062", "shasum": "" }, "require": { "php": "^7.4|^8.0", - "phpstan/phpstan": "^2.1.14" + "phpstan/phpstan": "^2.1.17" }, "conflict": { "rector/rector-doctrine": "*", @@ -13915,7 +14062,7 @@ ], "support": { "issues": "https://github.com/rectorphp/rector/issues", - "source": "https://github.com/rectorphp/rector/tree/2.0.16" + "source": "https://github.com/rectorphp/rector/tree/2.0.18" }, "funding": [ { @@ -13923,7 +14070,7 @@ "type": "github" } ], - "time": "2025-05-12T16:37:16+00:00" + "time": "2025-06-11T11:19:37+00:00" }, { "name": "sebastian/cli-parser", diff --git a/config/api.php b/config/api.php index 72d50f4ff..83bac8f03 100644 --- a/config/api.php +++ b/config/api.php @@ -1,5 +1,5 @@ env('API_THROTTLE', 200), + 'rate_limit' => env('API_RATE_LIMIT', 200), ]; diff --git a/config/constants.php b/config/constants.php index 226b7963b..78d77d78e 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.419', + 'version' => '4.0.0-beta.420', 'helper_version' => '1.0.8', 'realtime_version' => '1.0.9', 'self_hosted' => env('SELF_HOSTED', true), diff --git a/config/services.php b/config/services.php index d1c4a3699..7add50a5c 100644 --- a/config/services.php +++ b/config/services.php @@ -46,6 +46,13 @@ return [ 'redirect' => env('AUTHENTIK_REDIRECT_URI'), ], + 'clerk' => [ + 'client_id' => env('CLERK_CLIENT_ID'), + 'client_secret' => env('CLERK_CLIENT_SECRET'), + 'redirect' => env('CLERK_REDIRECT_URI'), + 'base_url' => env('CLERK_BASE_URL'), + ], + 'google' => [ 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), @@ -53,4 +60,11 @@ return [ 'tenant' => env('GOOGLE_TENANT'), ], + 'zitadel' => [ + 'client_id' => env('ZITADEL_CLIENT_ID'), + 'client_secret' => env('ZITADEL_CLIENT_SECRET'), + 'redirect' => env('ZITADEL_REDIRECT_URI'), + 'base_url' => env('ZITADEL_BASE_URL'), + ] + ]; diff --git a/database/migrations/2025_06_25_131350_add_is_sponsorship_popup_enabled_to_instance_settings_table.php b/database/migrations/2025_06_25_131350_add_is_sponsorship_popup_enabled_to_instance_settings_table.php new file mode 100644 index 000000000..7307da953 --- /dev/null +++ b/database/migrations/2025_06_25_131350_add_is_sponsorship_popup_enabled_to_instance_settings_table.php @@ -0,0 +1,28 @@ +boolean('is_sponsorship_popup_enabled')->default(true); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('instance_settings', function (Blueprint $table) { + $table->dropColumn('is_sponsorship_popup_enabled'); + }); + } +}; diff --git a/database/seeders/OauthSettingSeeder.php b/database/seeders/OauthSettingSeeder.php index fa692d2dc..2e5e6fcc4 100644 --- a/database/seeders/OauthSettingSeeder.php +++ b/database/seeders/OauthSettingSeeder.php @@ -17,11 +17,14 @@ class OauthSettingSeeder extends Seeder $providers = collect([ 'azure', 'bitbucket', + 'clerk', + 'discord', 'github', 'gitlab', 'google', 'authentik', 'infomaniak', + 'zitadel', ]); $isOauthSeeded = OauthSetting::count() > 0; diff --git a/lang/ar.json b/lang/ar.json index 9befd1e4a..263924c24 100644 --- a/lang/ar.json +++ b/lang/ar.json @@ -3,6 +3,8 @@ "auth.login.authentik": "تسجيل الدخول باستخدام Authentik", "auth.login.azure": "تسجيل الدخول باستخدام Microsoft", "auth.login.bitbucket": "تسجيل الدخول باستخدام Bitbucket", + "auth.login.clerk": "تسجيل الدخول باستخدام Clerk", + "auth.login.discord": "تسجيل الدخول باستخدام Discord", "auth.login.github": "تسجيل الدخول باستخدام GitHub", "auth.login.gitlab": "تسجيل الدخول باستخدام Gitlab", "auth.login.google": "تسجيل الدخول باستخدام Google", diff --git a/lang/az.json b/lang/az.json index 973c70c2f..92f56ddbc 100644 --- a/lang/az.json +++ b/lang/az.json @@ -3,6 +3,8 @@ "auth.login.authentik": "Authentik ilə daxil ol", "auth.login.azure": "Azure ilə daxil ol", "auth.login.bitbucket": "Bitbucket ilə daxil ol", + "auth.login.clerk": "Clerk ilə daxil ol", + "auth.login.discord": "Discord ilə daxil ol", "auth.login.github": "Github ilə daxil ol", "auth.login.gitlab": "GitLab ilə daxil ol", "auth.login.google": "Google ilə daxil ol", diff --git a/lang/cs.json b/lang/cs.json index 270fd272b..00455aa81 100644 --- a/lang/cs.json +++ b/lang/cs.json @@ -2,6 +2,8 @@ "auth.login": "Přihlásit se", "auth.login.azure": "Přihlásit se pomocí Microsoftu", "auth.login.bitbucket": "Přihlásit se pomocí Bitbucketu", + "auth.login.clerk": "Přihlásit se pomocí Clerk", + "auth.login.discord": "Přihlásit se pomocí Discordu", "auth.login.github": "Přihlásit se pomocí GitHubu", "auth.login.gitlab": "Přihlásit se pomocí Gitlabu", "auth.login.google": "Přihlásit se pomocí Google", diff --git a/lang/de.json b/lang/de.json index c5644e3a7..f56b21710 100644 --- a/lang/de.json +++ b/lang/de.json @@ -2,10 +2,13 @@ "auth.login": "Anmelden", "auth.login.azure": "Mit Microsoft anmelden", "auth.login.bitbucket": "Mit Bitbucket anmelden", + "auth.login.clerk": "Mit Clerk anmelden", + "auth.login.discord": "Mit Discord anmelden", "auth.login.github": "Mit GitHub anmelden", "auth.login.gitlab": "Mit GitLab anmelden", "auth.login.google": "Mit Google anmelden", "auth.login.infomaniak": "Mit Infomaniak anmelden", + "auth.login.zitadel": "Mit Zitadel anmelden", "auth.already_registered": "Bereits registriert?", "auth.confirm_password": "Passwort bestätigen", "auth.forgot_password": "Passwort vergessen", diff --git a/lang/en.json b/lang/en.json index cdca68601..4a398a9f9 100644 --- a/lang/en.json +++ b/lang/en.json @@ -3,10 +3,13 @@ "auth.login.authentik": "Login with Authentik", "auth.login.azure": "Login with Microsoft", "auth.login.bitbucket": "Login with Bitbucket", + "auth.login.clerk": "Login with Clerk", + "auth.login.discord": "Login with Discord", "auth.login.github": "Login with GitHub", "auth.login.gitlab": "Login with Gitlab", "auth.login.google": "Login with Google", "auth.login.infomaniak": "Login with Infomaniak", + "auth.login.zitadel": "Login with Zitadel", "auth.already_registered": "Already registered?", "auth.confirm_password": "Confirm password", "auth.forgot_password": "Forgot password", diff --git a/lang/es.json b/lang/es.json index aceacd462..73363a9bf 100644 --- a/lang/es.json +++ b/lang/es.json @@ -2,6 +2,8 @@ "auth.login": "Iniciar Sesión", "auth.login.azure": "Acceder con Microsoft", "auth.login.bitbucket": "Acceder con Bitbucket", + "auth.login.clerk": "Acceder con Clerk", + "auth.login.discord": "Acceder con Discord", "auth.login.github": "Acceder con GitHub", "auth.login.gitlab": "Acceder con Gitlab", "auth.login.google": "Acceder con Google", diff --git a/lang/fa.json b/lang/fa.json index 7a714e626..d68049e77 100644 --- a/lang/fa.json +++ b/lang/fa.json @@ -2,6 +2,8 @@ "auth.login": "ورود", "auth.login.azure": "ورود با مایکروسافت", "auth.login.bitbucket": "ورود با Bitbucket", + "auth.login.clerk": "ورود با Clerk", + "auth.login.discord": "ورود با Discord", "auth.login.github": "ورود با گیت هاب", "auth.login.gitlab": "ورود با گیت لب", "auth.login.google": "ورود با گوگل", diff --git a/lang/fr.json b/lang/fr.json index 68763d5e0..2516d0f69 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -3,6 +3,8 @@ "auth.login.authentik": "Connexion avec Authentik", "auth.login.azure": "Connexion avec Microsoft", "auth.login.bitbucket": "Connexion avec Bitbucket", + "auth.login.clerk": "Connexion avec Clerk", + "auth.login.discord": "Connexion avec Discord", "auth.login.github": "Connexion avec GitHub", "auth.login.gitlab": "Connexion avec Gitlab", "auth.login.google": "Connexion avec Google", diff --git a/lang/id.json b/lang/id.json index d35556402..b0e38197a 100644 --- a/lang/id.json +++ b/lang/id.json @@ -3,6 +3,8 @@ "auth.login.authentik": "Masuk dengan Authentik", "auth.login.azure": "Masuk dengan Microsoft", "auth.login.bitbucket": "Masuk dengan Bitbucket", + "auth.login.clerk": "Masuk dengan Clerk", + "auth.login.discord": "Masuk dengan Discord", "auth.login.github": "Masuk dengan GitHub", "auth.login.gitlab": "Masuk dengan Gitlab", "auth.login.google": "Masuk dengan Google", diff --git a/lang/it.json b/lang/it.json index 1923251a5..c0edc314b 100644 --- a/lang/it.json +++ b/lang/it.json @@ -3,6 +3,8 @@ "auth.login.authentik": "Accedi con Authentik", "auth.login.azure": "Accedi con Microsoft", "auth.login.bitbucket": "Accedi con Bitbucket", + "auth.login.clerk": "Accedi con Clerk", + "auth.login.discord": "Accedi con Discord", "auth.login.github": "Accedi con GitHub", "auth.login.gitlab": "Accedi con Gitlab", "auth.login.google": "Accedi con Google", diff --git a/lang/ja.json b/lang/ja.json index 4d4589900..87d87d99b 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -2,6 +2,8 @@ "auth.login": "ログイン", "auth.login.azure": "Microsoftでログイン", "auth.login.bitbucket": "Bitbucketでログイン", + "auth.login.clerk": "Clerkでログイン", + "auth.login.discord": "Discordでログイン", "auth.login.github": "GitHubでログイン", "auth.login.gitlab": "Gitlabでログイン", "auth.login.google": "Googleでログイン", diff --git a/lang/no.json b/lang/no.json index 29d5af124..a84f6aa6c 100644 --- a/lang/no.json +++ b/lang/no.json @@ -3,6 +3,8 @@ "auth.login.authentik": "Logg inn med Authentik", "auth.login.azure": "Logg inn med Microsoft", "auth.login.bitbucket": "Logg inn med Bitbucket", + "auth.login.clerk": "Logg inn med Clerk", + "auth.login.discord": "Logg inn med Discord", "auth.login.github": "Logg inn med GitHub", "auth.login.gitlab": "Logg inn med Gitlab", "auth.login.google": "Logg inn med Google", diff --git a/lang/pt-br.json b/lang/pt-br.json index 2e793890f..c3a102995 100644 --- a/lang/pt-br.json +++ b/lang/pt-br.json @@ -3,6 +3,8 @@ "auth.login.authentik": "Entrar com Authentik", "auth.login.azure": "Entrar com Microsoft", "auth.login.bitbucket": "Entrar com Bitbucket", + "auth.login.clerk": "Entrar com Clerk", + "auth.login.discord": "Entrar com Discord", "auth.login.github": "Entrar com GitHub", "auth.login.gitlab": "Entrar com Gitlab", "auth.login.google": "Entrar com Google", diff --git a/lang/pt.json b/lang/pt.json index c5f393e65..80ff8c146 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -2,6 +2,8 @@ "auth.login": "Entrar", "auth.login.azure": "Entrar com Microsoft", "auth.login.bitbucket": "Entrar com Bitbucket", + "auth.login.clerk": "Entrar com Clerk", + "auth.login.discord": "Entrar com Discord", "auth.login.github": "Entrar com GitHub", "auth.login.gitlab": "Entrar com Gitlab", "auth.login.google": "Entrar com Google", diff --git a/lang/ro.json b/lang/ro.json index 4c7968cfa..5588ea6f4 100644 --- a/lang/ro.json +++ b/lang/ro.json @@ -2,6 +2,8 @@ "auth.login": "Autentificare", "auth.login.azure": "Autentificare prin Microsoft", "auth.login.bitbucket": "Autentificare prin Bitbucket", + "auth.login.clerk": "Autentificare prin Clerk", + "auth.login.discord": "Autentificare prin Discord", "auth.login.github": "Autentificare prin GitHub", "auth.login.gitlab": "Autentificare prin Gitlab", "auth.login.google": "Autentificare prin Google", diff --git a/lang/tr.json b/lang/tr.json index 663c756f9..74f693dc9 100644 --- a/lang/tr.json +++ b/lang/tr.json @@ -2,6 +2,8 @@ "auth.login": "Giriş", "auth.login.azure": "Microsoft ile Giriş Yap", "auth.login.bitbucket": "Bitbucket ile Giriş Yap", + "auth.login.clerk": "Clerk ile Giriş Yap", + "auth.login.discord": "Discord ile Giriş Yap", "auth.login.github": "GitHub ile Giriş Yap", "auth.login.gitlab": "GitLab ile Giriş Yap", "auth.login.google": "Google ile Giriş Yap", diff --git a/lang/vi.json b/lang/vi.json index bb43fd34d..46edac599 100644 --- a/lang/vi.json +++ b/lang/vi.json @@ -2,6 +2,8 @@ "auth.login": "Đăng Nhập", "auth.login.azure": "Đăng Nhập Bằng Microsoft", "auth.login.bitbucket": "Đăng Nhập Bằng Bitbucket", + "auth.login.clerk": "Đăng Nhập Bằng Clerk", + "auth.login.discord": "Đăng Nhập Bằng Discord", "auth.login.github": "Đăng Nhập Bằng GitHub", "auth.login.gitlab": "Đăng Nhập Bằng Gitlab", "auth.login.google": "Đăng Nhập Bằng Google", diff --git a/lang/zh-cn.json b/lang/zh-cn.json index 944887a5f..d46c71e07 100644 --- a/lang/zh-cn.json +++ b/lang/zh-cn.json @@ -2,6 +2,8 @@ "auth.login": "登录", "auth.login.azure": "使用 Microsoft 登录", "auth.login.bitbucket": "使用 Bitbucket 登录", + "auth.login.clerk": "使用 Clerk 登录", + "auth.login.discord": "使用 Discord 登录", "auth.login.github": "使用 GitHub 登录", "auth.login.gitlab": "使用 Gitlab 登录", "auth.login.google": "使用 Google 登录", diff --git a/lang/zh-tw.json b/lang/zh-tw.json index c42ebb33e..c0784c7b7 100644 --- a/lang/zh-tw.json +++ b/lang/zh-tw.json @@ -2,6 +2,8 @@ "auth.login": "登入", "auth.login.azure": "使用 Microsoft 登入", "auth.login.bitbucket": "使用 Bitbucket 登入", + "auth.login.clerk": "使用 Clerk 登入", + "auth.login.discord": "使用 Discord 登入", "auth.login.github": "使用 GitHub 登入", "auth.login.gitlab": "使用 Gitlab 登入", "auth.login.google": "使用 Google 登入", diff --git a/other/nightly/versions.json b/other/nightly/versions.json index eda548570..9fde1e53b 100644 --- a/other/nightly/versions.json +++ b/other/nightly/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.419" + "version": "4.0.0-beta.420" }, "nightly": { - "version": "4.0.0-beta.420" + "version": "4.0.0-beta.421" }, "helper": { "version": "1.0.8" diff --git a/public/heart.png b/public/heart.png new file mode 100644 index 000000000..c44a21301 Binary files /dev/null and b/public/heart.png differ diff --git a/public/svgs/hoarder.svg b/public/svgs/karakeep.svg similarity index 100% rename from public/svgs/hoarder.svg rename to public/svgs/karakeep.svg diff --git a/public/svgs/miniflux.svg b/public/svgs/miniflux.svg new file mode 100644 index 000000000..33ae73a87 --- /dev/null +++ b/public/svgs/miniflux.svg @@ -0,0 +1 @@ +icon \ No newline at end of file diff --git a/public/svgs/pingvinshare.svg b/public/svgs/pingvinshare.svg new file mode 100644 index 000000000..4f1f7a7bc --- /dev/null +++ b/public/svgs/pingvinshare.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/resources/css/utilities.css b/resources/css/utilities.css index 4993b2302..fe0cd10ed 100644 --- a/resources/css/utilities.css +++ b/resources/css/utilities.css @@ -122,7 +122,7 @@ } @utility navbar-main { - @apply flex flex-col gap-4 justify-items-start pb-2 border-b-2 border-solid h-fit md:flex-row sm:justify-between dark:border-coolgray-200 md:items-center; + @apply flex flex-col gap-4 justify-items-start pb-2 border-b-2 border-solid h-fit md:flex-row sm:justify-between dark:border-coolgray-200 border-neutral-200 md:items-center; } @utility loading { diff --git a/resources/views/components/loading-on-button.blade.php b/resources/views/components/loading-on-button.blade.php index 78a1f9726..a451023aa 100644 --- a/resources/views/components/loading-on-button.blade.php +++ b/resources/views/components/loading-on-button.blade.php @@ -3,7 +3,7 @@ @if (isset($text))
{{ $text }}
@endif - - @@ -362,7 +362,7 @@ @endpersist @endif -
  • + {{--
  • @@ -372,7 +372,7 @@ Onboarding -
  • + --}}
  • @@ -410,7 +410,7 @@
    @csrf - + + @endisset + diff --git a/resources/views/components/status/index.blade.php b/resources/views/components/status/index.blade.php index fe9569c8a..65beace65 100644 --- a/resources/views/components/status/index.blade.php +++ b/resources/views/components/status/index.blade.php @@ -13,11 +13,18 @@ @endif @if (!str($resource->status)->contains('exited') && $showRefreshButton) - + @endif diff --git a/resources/views/components/status/services.blade.php b/resources/views/components/status/services.blade.php index 5a52335a7..677cc6f45 100644 --- a/resources/views/components/status/services.blade.php +++ b/resources/views/components/status/services.blade.php @@ -1,5 +1,7 @@ @if (str($complexStatus)->contains('running')) +@elseif(str($complexStatus)->contains('starting')) + @elseif(str($complexStatus)->contains('restarting')) @elseif(str($complexStatus)->contains('degraded')) @@ -8,11 +10,18 @@ @endif @if (!str($complexStatus)->contains('exited') && $showRefreshButton) - + @endif diff --git a/resources/views/livewire/boarding/index.blade.php b/resources/views/livewire/boarding/index.blade.php index f5ed24c51..68b328b30 100644 --- a/resources/views/livewire/boarding/index.blade.php +++ b/resources/views/livewire/boarding/index.blade.php @@ -4,7 +4,7 @@
    + class="flex flex-col items-center justify-center p-10 mx-2 mt-10 bg-white border rounded-lg shadow-sm lg:p-20 dark:bg-transparent dark:border-none max-w-7xl border-neutral-200"> @if ($currentState === 'welcome')

    Welcome to Coolify

    Let me help you set up the basics.
    @@ -21,8 +21,8 @@ Git integrations, deploy databases and services, monitor these resources with notifications and alerts - without vendor lock-in.
    -
    Coolify Home. + without vendor lock-in.
    + Coolify Home.

    @@ -277,8 +277,7 @@ + label="Description" id="remoteServerDescription" wire:model="remoteServerDescription" />
    @@ -323,7 +322,8 @@

    This will install the latest Docker Engine on your server, configure a few things to be able - to run optimal.

    Minimum Docker Engine version is: {{ $minDockerVersion }}

    To manually install + to run optimal.

    Minimum Docker Engine version is: {{ $minDockerVersion }}

    To + manually install Docker Engine, check this diff --git a/resources/views/livewire/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php index d9b99bc12..eb75bcd59 100644 --- a/resources/views/livewire/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -17,9 +17,9 @@

    Projects

    @if ($projects->count() > 0) -
    +
    @foreach ($projects as $project) -
    @@ -68,7 +68,6 @@ $server->settings->is_reachable, 'border-red-500' => !$server->settings->is_reachable, ])>
    @@ -124,7 +123,7 @@ @if ($servers->count() > 0 && $projects->count() > 0)
    -
    +

    Deployments

    @if (count($deploymentsPerServer) > 0) diff --git a/resources/views/livewire/layout-popups.blade.php b/resources/views/livewire/layout-popups.blade.php index c639b4627..835fa32d5 100644 --- a/resources/views/livewire/layout-popups.blade.php +++ b/resources/views/livewire/layout-popups.blade.php @@ -4,9 +4,10 @@ notification: true, realtime: false, }, + isDevelopment: {{ isDev() ? 'true' : 'false' }}, init() { - this.popups.sponsorship = localStorage.getItem('popupSponsorship') !== 'false'; - this.popups.notification = localStorage.getItem('popupNotification') !== 'false'; + this.popups.sponsorship = this.shouldShowMonthlyPopup('popupSponsorship'); + this.popups.notification = this.shouldShowMonthlyPopup('popupNotification'); this.popups.realtime = localStorage.getItem('popupRealtime'); let checkNumber = 1; @@ -31,6 +32,35 @@ } }, 2000); } + }, + shouldShowMonthlyPopup(storageKey) { + const disabledTimestamp = localStorage.getItem(storageKey); + + // If never disabled, show the popup + if (!disabledTimestamp || disabledTimestamp === 'false') { + return true; + } + + // If disabled timestamp is not a valid number, show the popup + const disabledTime = parseInt(disabledTimestamp); + if (isNaN(disabledTime)) { + return true; + } + + const now = new Date(); + const disabledDate = new Date(disabledTime); + + {{-- if (this.isDevelopment) { + // In development: check if 10 seconds have passed + const timeDifference = now.getTime() - disabledDate.getTime(); + const tenSecondsInMs = 10 * 1000; + return timeDifference >= tenSecondsInMs; + } else { --}} + // In production: check if we're in a different month or year + const isDifferentMonth = now.getMonth() !== disabledDate.getMonth() || + now.getFullYear() !== disabledDate.getFullYear(); + return isDifferentMonth; + {{-- } --}} } }"> @auth @@ -56,35 +86,60 @@ @endif @endauth - - - - Love Coolify as we do? - - - - - - Please - consider donating on
    GitHub or OpenCollective.

    - It enables us to keep creating features without paywalls, ensuring our work remains free and - open. - - - Disable This Popup - - - + @if (instanceSettings()->is_sponsorship_popup_enabled && !isCloud()) + + + +
    + +
    +
    Love Coolify? Support our work. +
    +
    + We are already profitable thanks to YOU + but...
    We + would + like to + make + more cool features. +
    +
    + For this we need your help to support our work financially. +
    +
    +
    + GitHub + Sponsors + Open + Collective + Stripe +
    + Maybe next time +
    +
    +
    +
    +
    +
    + @endif @if (currentTeam()->subscriptionPastOverDue()) -
    WARNING: Your subscription is in over-due. If your latest +
    WARNING: Your subscription is in over-due. If your + latest payment is not paid within a week, all automations will be deactivated. Visit /subscription to check your subscription status or pay your + class="underline dark:text-white">/subscription to check your subscription status or pay + your invoice (or check your email for the invoice).
    @@ -128,11 +183,13 @@ @endif