Skip to content

Commit

Permalink
fix(verify email) fix verify email process
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohammad-Alavi committed Jan 22, 2022
1 parent 30eb7ac commit 4f03e51
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,42 @@

namespace App\Containers\AppSection\Authentication\Actions;

use App\Containers\AppSection\Authentication\Exceptions\InvalidEmailVerificationDataException;
use App\Containers\AppSection\Authentication\Notifications\EmailVerified;
use App\Containers\AppSection\Authentication\UI\API\Requests\VerifyEmailRequest;
use App\Containers\AppSection\User\Models\User;
use App\Containers\AppSection\User\Tasks\FindUserByIdTask;
use App\Ship\Exceptions\NotFoundException;
use App\Ship\Parents\Actions\Action;
use Throwable;

class VerifyEmailAction extends Action
{
/**
* @param VerifyEmailRequest $request
* @throws NotFoundException
* @throws Throwable
*/
public function run(VerifyEmailRequest $request): void
{
if (!$request->user()->hasVerifiedEmail()) {
$request->user()->markEmailAsVerified();
$user = app(FindUserByIdTask::class)->run($request->id);

$request->user()->notify(new EmailVerified());
throw_unless($this->validateData($request, $user), InvalidEmailVerificationDataException::class);

if (!$user->hasVerifiedEmail()) {
$user->markEmailAsVerified();

$user->notify(new EmailVerified());
}
}

/**
* @param VerifyEmailRequest $request
* @param User $user
* @return bool
*/
private function validateData(VerifyEmailRequest $request, User $user): bool
{
return hash_equals((string)$request->hash, sha1($user->getEmailForVerification()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace App\Containers\AppSection\Authentication\Exceptions;

use App\Ship\Parents\Exceptions\Exception;
use Symfony\Component\HttpFoundation\Response;

class InvalidEmailVerificationDataException extends Exception
{
protected $code = Response::HTTP_UNPROCESSABLE_ENTITY;
protected $message = 'Invalid Email Verification Data Provided.';
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@

use App\Containers\AppSection\Authentication\Actions\VerifyEmailAction;
use App\Containers\AppSection\Authentication\UI\API\Requests\VerifyEmailRequest;
use App\Ship\Exceptions\NotFoundException;
use App\Ship\Parents\Controllers\ApiController;
use Illuminate\Http\JsonResponse;
use Throwable;

class VerifyEmailController extends ApiController
{
/**
* @throws NotFoundException
* @throws Throwable
*/
public function verifyEmail(VerifyEmailRequest $request): JsonResponse
{
app(VerifyEmailAction::class)->run($request);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@

namespace App\Containers\AppSection\Authentication\UI\API\Requests;

use App\Containers\AppSection\Authorization\Traits\IsResourceOwnerTrait;
use App\Ship\Parents\Requests\Request;

class VerifyEmailRequest extends Request
{
use IsResourceOwnerTrait;

/**
* Define which Roles and/or Permissions has access to this request.
*/
Expand Down Expand Up @@ -38,7 +35,7 @@ class VerifyEmailRequest extends Request
public function rules(): array
{
return [
'id' => 'required',
// 'id' => 'required',
];
}

Expand All @@ -49,13 +46,6 @@ public function authorize(): bool
{
return $this->check([
'hasAccess',
'isResourceOwner',
'isHashEqualsUserEmail',
]);
}

protected function isHashEqualsUserEmail(): bool
{
return hash_equals((string)$this->hash, sha1($this->user()->getEmailForVerification()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* @apiGroup Authentication
* @apiName VerifyEmail
*
* @api {GET} /v1/email/verify/:id/:hash Verify Email
* @api {POST} /v1/email/verify/:id/:hash Verify Email
* @apiDescription Verify user email
*
* @apiVersion 1.0.0
* @apiPermission Authenticated
* @apiPermission none
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
Expand All @@ -18,6 +18,5 @@
use App\Containers\AppSection\Authentication\UI\API\Controllers\VerifyEmailController;
use Illuminate\Support\Facades\Route;

Route::post('email/verify/{id}/{hash}', [VerifyEmailController::class, 'verifyEmail'])
->middleware(['auth:api']);
Route::post('email/verify/{id}/{hash}', [VerifyEmailController::class, 'verifyEmail']);

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace App\Containers\AppSection\Authentication\UI\API\Tests\Functional;

use App\Containers\AppSection\Authentication\Notifications\EmailVerified;
use App\Containers\AppSection\Authentication\UI\API\Tests\ApiTestCase;
use App\Containers\AppSection\User\Models\User;
use Illuminate\Support\Facades\Notification;

/**
* Class VerifyEmailTest.
*
* @group authentication
* @group api
*/
class VerifyEmailTest extends ApiTestCase
{
protected string $endpoint = 'post@v1/email/verify/{id}/{hash}';

protected array $access = [
'roles' => '',
'permissions' => '',
];

public function testVerifyEmail(): void
{
Notification::fake();
$unverifiedUser = User::factory()->unverified()->create();
// enable email verification
config(['appSection-authentication.require_email_verification' => true]);

$response = $this->injectId($unverifiedUser->id)
->injectId(sha1($unverifiedUser->getEmailForVerification()), skipEncoding: true, replace: '{hash}')
->makeCall();

$response->assertStatus(200);
$unverifiedUser->refresh();
$this->assertTrue($unverifiedUser->hasVerifiedEmail());
Notification::assertSentTo($unverifiedUser, EmailVerified::class);
}
}

0 comments on commit 4f03e51

Please sign in to comment.