<?php
namespace App\Services;
use App\Services\{
EntityServices\OneTimeCodeEntityService,
EntityServices\UserEntityService
};
use App\Entity\{
OneTimeCode,
Tenant,
User
};
class OneTimeCodeService
{
const MAX_PER_USER = 10;
private $notifierService;
private $oneTimeCodeEntityService;
private $userEntityService;
public function __construct(
OneTimeCodeEntityService $oneTimeCodeEntityService,
UserEntityService $userEntityService
) {
$this->oneTimeCodeEntityService = $oneTimeCodeEntityService;
$this->userEntityService = $userEntityService;
}
/**
* ask OneTimeCode
*/
public function askCodeByEmail(Tenant $tenant, string $email): OneTimeCode
{
$user = $this->userEntityService->findUser($email, $tenant);
if ( is_null($user) ) {
throw new \Exception('User not found');
}
return $this->askCodeByUser($user);
}
/**
* ask OneTimeCode
*/
public function askCodeByUser(User $user): OneTimeCode
{
if ( self::MAX_PER_USER <= $this->oneTimeCodeEntityService->cleanAndCount($user) ) {
throw new \Exception('Max per User exceeded');
}
return $this->oneTimeCodeEntityService->createCode($user);
}
/**
* use OneTimeCode
*/
public function useCode(Tenant $tenant, string $code): User
{
$oneTimeCode = $this->oneTimeCodeEntityService->findCode($code);
if ( is_null($oneTimeCode) ) {
throw new \Exception('Code not found');
}
$isExpired = (bool)((new \DateTimeImmutable())->diff($oneTimeCode->getExpiredAt()))->invert;
$user = $oneTimeCode->getUser();
$isTenantMatch = $tenant === $user->getTenant();
$this->oneTimeCodeEntityService->removeCode($oneTimeCode);
if ( $isExpired ) {
throw new \Exception('Code expired');
} else if ( ! $isTenantMatch ) {
throw new \Exception('URL failed');
}
$this->oneTimeCodeEntityService->removeByUser(
$this->userEntityService->setEmailConfirmed( $user )
);
return $user;
}
/**
* find user by OneTimeCode
*/
public function findUserByCode(Tenant $tenant, string $code): ?User
{
$oneTimeCode = $this->oneTimeCodeEntityService->findCode($code);
if ( is_null($oneTimeCode) ) {
return null;
}
$isExpired = (bool)((new \DateTimeImmutable())->diff($oneTimeCode->getExpiredAt()))->invert;
$user = $oneTimeCode->getUser();
$isTenantMatch = $tenant === $user->getTenant();
if ( $isExpired or ! $isTenantMatch) {
// dd($isExpired, $isTenantMatch);
return null;
}
return $user;
}
}