From d48b35e8451b9128313078864e67b9f99110294e Mon Sep 17 00:00:00 2001 From: Miguel Nogueira Date: Sun, 10 Aug 2025 11:01:24 +0100 Subject: [PATCH] fix: make sure approved invites are not deleted daily even though people would have time to use approved invites (24 hrs at least), it would be better to delete them when they expire instead. Signed-off-by: Miguel Nogueira --- app/Jobs/ExpiredInviteCleanup.php | 27 +++++++++++++------ app/Jobs/InviteLifecycleCleanup.php | 12 +++++++-- .../administration/invites.blade.php | 2 +- routes/console.php | 9 +++++-- 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/app/Jobs/ExpiredInviteCleanup.php b/app/Jobs/ExpiredInviteCleanup.php index d1f9e96..87d2dba 100644 --- a/app/Jobs/ExpiredInviteCleanup.php +++ b/app/Jobs/ExpiredInviteCleanup.php @@ -6,6 +6,7 @@ use App\Invitation; use Carbon\Carbon; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Queue\Queueable; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Mail; use App\Mail\InviteExpiringSoon; @@ -26,27 +27,37 @@ class ExpiredInviteCleanup implements ShouldQueue */ public function handle(): void { - // 1. Notify invites expiring within the next 24 hours that haven't been notified yet - Invitation::where('status', 'pending') + Log::info('Cleaning up expired invites.'); + + $notified = 0; + $deleted = 0; + + Invitation::where('status', 'approved') ->where('notified', false) ->whereBetween('expiration', [Carbon::now(), Carbon::now()->addDay()]) - ->chunkById(100, function ($invites) { + ->chunkById(100, function ($invites) use (&$notified) { foreach ($invites as $invite) { Mail::to($invite->requestor_email) - ->send(new InviteExpiringSoon($invite)); + ->queue(new InviteExpiringSoon($invite)); + $notified++; $invite->notified = true; $invite->save(); + + Log::debug("Notified approved invite {$invite->invitation_code}, sent to {$invite->requestor_email}."); } }); - // 2. Delete invites that have actually expired - Invitation::where('status', 'pending') - ->where('expiration', '<', Carbon::now()) - ->chunkById(100, function ($invites) { + Invitation::where('expiration', '<', Carbon::now()) + ->where('status', '!=', 'denied') + ->chunkById(100, function ($invites) use (&$deleted, &$notified) { foreach ($invites as $invite) { + Log::debug("Deleted invite {$invite->invitation_code} for {$invite->requestor_email}."); $invite->delete(); + $deleted++; } }); + + Log::info("Deleted {$deleted} invites and notified {$notified} approved invites close to expiration."); } } diff --git a/app/Jobs/InviteLifecycleCleanup.php b/app/Jobs/InviteLifecycleCleanup.php index 4beaf04..641d8ec 100644 --- a/app/Jobs/InviteLifecycleCleanup.php +++ b/app/Jobs/InviteLifecycleCleanup.php @@ -5,6 +5,7 @@ namespace App\Jobs; use App\Invitation; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Queue\Queueable; +use Illuminate\Support\Facades\Log; // General Housekeeping Job: Drop Approved and Completed Invites class InviteLifecycleCleanup implements ShouldQueue @@ -24,11 +25,18 @@ class InviteLifecycleCleanup implements ShouldQueue */ public function handle(): void { - Invitation::whereIn('status', ['approved', 'completed']) - ->chunkById(100, function ($invites) { + Log::info("Invite lifecycle: processing completed invites."); + $deleted = 0; + + Invitation::where('status', '=', 'completed') + ->chunkById(100, function ($invites) use (&$deleted) { foreach ($invites as $invite) { + Log::debug("Deleted invite {$invite->invitation_code} for {$invite->requestor_email}."); $invite->delete(); + $deleted++; } }); + + Log::info("Deleted {$deleted} completed invitations."); } } diff --git a/resources/views/dashboard/administration/invites.blade.php b/resources/views/dashboard/administration/invites.blade.php index 3df72a5..b6b8ccb 100644 --- a/resources/views/dashboard/administration/invites.blade.php +++ b/resources/views/dashboard/administration/invites.blade.php @@ -133,7 +133,7 @@

{{ __('Here, you can manage the invitation system, and approve any invite requests that might have come through. You can also send invites from here if necessary.') }}

{!! __('Remember: invitations are unique on an email/IP address basis. The same user won\'t be able to request an invite twice. This restriction also applies to you. Check if there\'s already an invite before sending one out.') !!}

-

{!! __('Invite lifecycle: Approved and Completed invites are wiped from the system on a daily basis. Expired invites are wiped 1 day after expiration. Denied invites are never wiped.') !!}

+

{!! __('Invite lifecycle: Completed invites are wiped from the system every 12 hours. Expired invites are wiped 1 day after expiration. Denied invites are never wiped ') !!}

diff --git a/routes/console.php b/routes/console.php index 661d0bb..41e56a4 100644 --- a/routes/console.php +++ b/routes/console.php @@ -36,5 +36,10 @@ Schedule::command('votes:evaluate')->daily(); Schedule::job(new ProcessDueSuspensions())->daily(); Schedule::job(new ProcessExpiredAbsences())->daily(); -Schedule::job(new InviteLifecycleCleanup())->daily(); -Schedule::job(new ExpiredInviteCleanup())->daily(); +// Schedule::job(new InviteLifecycleCleanup())->cron("0 */12 * * *"); +// Schedule::job(new ExpiredInviteCleanup())->daily(); + +// debug + +Schedule::job(new InviteLifecycleCleanup())->everyFiveMinutes(); +Schedule::job(new ExpiredInviteCleanup())->everyMinute();