Skip to content

Commit

Permalink
Merge pull request #741 from pinkary-project/feat--actions-for-verifi…
Browse files Browse the repository at this point in the history
…ed-users

Feat: actions for Email verified users
  • Loading branch information
nunomaduro authored Dec 26, 2024
2 parents 7ebfc21 + e34212c commit 1949151
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 0 deletions.
24 changes: 24 additions & 0 deletions app/Livewire/Concerns/NeedsVerifiedEmail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace App\Livewire\Concerns;

trait NeedsVerifiedEmail
{
/**
* Determine if the user does not have a verified email address.
*/
public function doesNotHaveVerifiedEmail(): bool
{
if (auth()->user()?->hasVerifiedEmail()) {
return false;
}

session()->flash('flash-message', 'You must verify your email address before you can continue.');

$this->redirectRoute('verification.notice', navigate: true);

return true;
}
}
14 changes: 14 additions & 0 deletions app/Livewire/Questions/Create.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace App\Livewire\Questions;

use App\Livewire\Concerns\NeedsVerifiedEmail;
use App\Models\Question;
use App\Models\User;
use App\Rules\MaxUploads;
Expand All @@ -28,6 +29,7 @@
*/
final class Create extends Component
{
use NeedsVerifiedEmail;
use WithFileUploads;

/**
Expand Down Expand Up @@ -81,6 +83,10 @@ final class Create extends Component
*/
public function updated(mixed $property): void
{
if ($this->doesNotHaveVerifiedEmail()) {
return;
}

if ($property === 'images') {
$this->runImageValidation();
$this->uploadImages();
Expand All @@ -92,6 +98,10 @@ public function updated(mixed $property): void
*/
public function runImageValidation(): void
{
if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$this->validate(
rules: [
'images' => [
Expand Down Expand Up @@ -209,6 +219,10 @@ public function store(Request $request): void
return;
}

if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$user = type($request->user())->as(User::class);

if (! app()->isLocal() && $user->questionsSent()->where('created_at', '>=', now()->subMinute())->count() >= 3) {
Expand Down
7 changes: 7 additions & 0 deletions app/Livewire/Questions/Edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace App\Livewire\Questions;

use App\Livewire\Concerns\NeedsVerifiedEmail;
use App\Models\Question;
use App\Models\User;
use App\Rules\NoBlankCharacters;
Expand All @@ -14,6 +15,8 @@

final class Edit extends Component
{
use NeedsVerifiedEmail;

/**
* The component's question ID.
*/
Expand Down Expand Up @@ -41,6 +44,10 @@ public function mount(string $questionId): void
*/
public function update(Request $request): void
{
if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$validated = $this->validate([
'answer' => ['required', 'string', 'max:1000', new NoBlankCharacters],
]);
Expand Down
31 changes: 31 additions & 0 deletions app/Livewire/Questions/Show.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace App\Livewire\Questions;

use App\Livewire\Concerns\NeedsVerifiedEmail;
use App\Models\Question;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
Expand All @@ -16,6 +17,8 @@

final class Show extends Component
{
use NeedsVerifiedEmail;

/**
* The component's question ID.
*/
Expand Down Expand Up @@ -96,6 +99,10 @@ public function ignore(): void
return;
}

if ($this->doesNotHaveVerifiedEmail()) {
return;
}

if ($this->inIndex) {
$this->dispatch('notification.created', message: 'Question ignored.');

Expand Down Expand Up @@ -125,6 +132,10 @@ public function bookmark(): void
return;
}

if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$question = Question::findOrFail($this->questionId);

$bookmark = $question->bookmarks()->firstOrCreate([
Expand All @@ -148,6 +159,10 @@ public function like(): void
return;
}

if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$question = Question::findOrFail($this->questionId);

$question->likes()->firstOrCreate([
Expand All @@ -166,6 +181,10 @@ public function pin(): void
return;
}

if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$user = type(auth()->user())->as(User::class);

$question = Question::findOrFail($this->questionId);
Expand All @@ -189,6 +208,10 @@ public function unpin(): void
return;
}

if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$question = Question::findOrFail($this->questionId);

$this->authorize('update', $question);
Expand All @@ -210,6 +233,10 @@ public function unbookmark(): void
return;
}

if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$question = Question::findOrFail($this->questionId);

if ($bookmark = $question->bookmarks()->where('user_id', auth()->id())->first()) {
Expand All @@ -235,6 +262,10 @@ public function unlike(): void
return;
}

if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$question = Question::findOrFail($this->questionId);

if ($like = $question->likes()->where('user_id', auth()->id())->first()) {
Expand Down
59 changes: 59 additions & 0 deletions tests/Unit/Livewire/Concerns/NeedsVerifiedEmailTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

use App\Livewire\Concerns\NeedsVerifiedEmail;
use App\Models\User;
use Livewire\Component;
use Livewire\Livewire;

it('can check if the user does not have a verified email address', function () {
$user = User::factory()->create([
'email_verified_at' => null,
]);

$component = Livewire::actingAs($user)->test(myComponentNeedsVerifiedEmail()::class);
$component->call('someMethod');
$component->assertRedirect(route('verification.notice'));
$component->assertSet('isConfirmed', false);

expect(session('flash-message'))->toBe('You must verify your email address before you can continue.');
});

it('can check if the user has a verified email address', function () {
$user = User::factory()->create();

$component = Livewire::actingAs($user)->test(myComponentNeedsVerifiedEmail()::class);
$component->call('someMethod');
$component->assertSet('isConfirmed', true);

expect(session('flash-message'))->toBeNull();
});

function myComponentNeedsVerifiedEmail(): Component
{
return new class() extends Component
{
use NeedsVerifiedEmail;

public bool $isConfirmed = false;

public function someMethod()
{
if ($this->doesNotHaveVerifiedEmail()) {
return;
}

$this->isConfirmed = true;
}

public function render()
{
return <<<'HTML'
<div>
<button wire:click="someMethod">Click me</button>
</div>
HTML;
}
};
}

0 comments on commit 1949151

Please sign in to comment.