diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index c32679c1..d41d0804 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -5,10 +5,12 @@ use App\Http\Controllers\Controller; use App\Http\Requests\User\StoreUserRequest; use App\Http\Requests\User\UpdateUserRequest; +use App\Mail\AccountDeletedMail; use App\Models\User; use App\Notifications\WelcomeNotification; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; +use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Storage; use Inertia\Inertia; use Spatie\Permission\Models\Permission; @@ -157,6 +159,10 @@ public function update(UpdateUserRequest $request, User $user) public function destroy(User $user) { + if (! empty($user->email)) { + Mail::to($user->email)->queue(new AccountDeletedMail($user->name)); + } + $user->delete(); return redirect() diff --git a/app/Mail/AccountDeletedMail.php b/app/Mail/AccountDeletedMail.php new file mode 100644 index 00000000..e496c7bc --- /dev/null +++ b/app/Mail/AccountDeletedMail.php @@ -0,0 +1,59 @@ +recipientName ? "Hello {$this->recipientName}," : 'প্রিয় শিক্ষার্থী,'; + $privacyUrl = url('/privacy-policy'); + $termsUrl = url('/terms-service'); + $archiveUrl = url('/'); + $forumUrl = url('/forum'); + $chatUrl = url('/chat'); + $trackerUrl = url('/tracker'); + + return new Content( + view: 'emails.default', + with: [ + 'subject' => 'আপনার অ্যাকাউন্ট ডিলিট করা হয়েছে', + 'greeting' => $name, + 'lines' => [ + "আমরা আপনার অ্যাকাউন্ট ডিলিট করার অনুরোধটি পেয়েছি। আপনার অ্যাকাউন্ট এবং এর সাথে সম্পর্কিত যাবতীয় তথ্য আমাদের Privacy Policy ও Terms & Conditions অনুযায়ী স্থায়ীভাবে মুছে ফেলা হয়েছে।", + 'ভবিষ্যতে যদি আবার HSCStack ব্যবহার করতে চান, তাহলে যেকোনো সময় নতুন করে একটি অ্যাকাউন্ট তৈরি করে আমাদের প্ল্যাটফর্মে ফিরে আসতে পারেন।', + 'HSCStack-এর উল্লেখযোগ্য ফিচারসমূহ:', + "• Resource Archive — HSC ও SSC-এর Science, Arts এবং Commerce বিভাগের ক্লাস, নোট ও বিভিন্ন শিক্ষামূলক রিসোর্স।", + "• Forum — যেকোনো প্রশ্ন করতে পারবেন এবং সহপাঠীদের কাছ থেকে উত্তর ও সহযোগিতা পেতে পারবেন।", + "• Global Chat — সারাদেশের শিক্ষার্থীদের সাথে যোগাযোগ ও মতবিনিময়ের সুযোগ।", + "• Study Tracker — আপনার পড়াশোনা ও সিলেবাসের অগ্রগতি সহজেই ট্র্যাক করুন।", + '• Community Interaction — অন্যান্য শিক্ষার্থীদের সাথে যুক্ত হয়ে আলোচনা, সহযোগিতা ও জ্ঞান বিনিময় করুন।', + 'আবারও ধন্যবাদ HSCStack-এর সাথে থাকার জন্য।', + 'ভবিষ্যতে আবার দেখা হবে! 💙', + ], + 'actionText' => 'Visit HSCStack', + 'actionUrl' => config('app.url', url('/')), + ], + ); + } +} diff --git a/resources/views/emails/default.blade.php b/resources/views/emails/default.blade.php index 6e39cab2..4637a72a 100644 --- a/resources/views/emails/default.blade.php +++ b/resources/views/emails/default.blade.php @@ -70,6 +70,11 @@ .content p { margin: 0 0 16px; } + .content a { + color: #4f46e5; + text-decoration: underline; + font-weight: 600; + } .action-button-container { margin: 28px 0 16px; text-align: left; @@ -153,7 +158,7 @@ @if(!empty($lines)) @foreach($lines as $line) -

{{ $line }}

+

{!! $line !!}

@endforeach @endif diff --git a/tests/Feature/AdminUserDeletionMailTest.php b/tests/Feature/AdminUserDeletionMailTest.php new file mode 100644 index 00000000..011e85f3 --- /dev/null +++ b/tests/Feature/AdminUserDeletionMailTest.php @@ -0,0 +1,56 @@ +seed(RolePermissionSeeder::class); +}); + +test('account deleted mailable renders expected subject, content and anchored links via emails.default', function () { + $mailable = new AccountDeletedMail('Rahim Ahmed'); + + $mailable->assertHasSubject('আপনার অ্যাকাউন্ট ডিলিট করা হয়েছে'); + + $html = $mailable->render(); + + expect($html) + ->toContain('আপনার অ্যাকাউন্ট ডিলিট করা হয়েছে') + ->toContain('আমরা আপনার অ্যাকাউন্ট ডিলিট করার অনুরোধটি পেয়েছি') + ->toContain('Privacy Policy') + ->toContain('Terms & Conditions') + ->toContain('/privacy-policy') + ->toContain('/terms-service') + ->toContain('Resource Archive') + ->toContain('Forum') + ->toContain('Global Chat') + ->toContain('Study Tracker') + ->toContain('Community Interaction') + ->toContain('ভবিষ্যতে আবার দেখা হবে! 💙'); +}); + +test('admin deleting a user queues account deleted mail and deletes user', function () { + Mail::fake(); + + $admin = User::factory()->create(); + $admin->assignRole('admin'); + + $userToDelete = User::factory()->create([ + 'name' => 'Karim Hasan', + 'email' => 'karim@example.com', + ]); + + $this->actingAs($admin) + ->delete("/admin/users/{$userToDelete->id}") + ->assertRedirect(route('admin.users.index')) + ->assertSessionHas('success'); + + expect(User::find($userToDelete->id))->toBeNull(); + + Mail::assertQueued(AccountDeletedMail::class, function (AccountDeletedMail $mail) use ($userToDelete) { + return $mail->hasTo($userToDelete->email) + && $mail->recipientName === 'Karim Hasan'; + }); +});