<?php
namespace App\Adapter;
use Exception;
use Throwable;
use App\Adapter\Request\DeleteRequest;
use App\Adapter\Request\GetRequest;
use App\Adapter\Request\PostRequest;
use App\Dto\Input\AuthDTO;
use App\Dto\Input\MediaDTO;
use App\Dto\Input\RegisterDTO;
use App\Dto\Input\ResetPasswordDTO;
use App\Dto\Output\AuthOutputDTO;
use App\Exception\ClientFromMediaNotFoundException;
use App\Exception\ExpiredCodeException;
use App\Mapper\ClientMapper;
use App\Model\Client;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpClient\Exception\ClientException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
class AuthAdapter extends AbstractAdapter
{
public function __construct(
HttpClientInterface $carfitClient,
LoggerInterface $securityLogger,
array $carfitEndpoint
) {
parent::__construct($carfitClient, $securityLogger, $carfitEndpoint);
}
/**
* @throws Exception|CustomUserMessageAuthenticationException
*/
public function login(AuthDTO $dto): Client
{
$request = new PostRequest($this->carfitEndpoint['login']);
$request->setBody([
'email' => $dto->email,
'password' => $dto->password,
]);
try {
$content = $this->call($request);
$outputDto = new AuthOutputDTO();
$outputDto->token = $content['token'];
$outputDto->email = $dto->email;
$outputDto->password = $dto->password;
return ClientMapper::fromAuthDTO($outputDto);
} catch (ClientException $exception) {
$this->logger->error($exception->getMessage());
throw new CustomUserMessageAuthenticationException('auth.not_found');
} catch (Throwable $exception) {
$this->logger->error($exception->getMessage());
throw new CustomUserMessageAuthenticationException('error.500');
}
}
/**
* @throws Exception
*/
public function passwordRecover(ResetPasswordDTO $dto): bool
{
$request = new PostRequest($this->carfitEndpoint['password_recover']);
$request->setBody([
'email' => $dto->email,
]);
return $this->sendRequest($request);
}
/**
* @throws Exception
*/
public function passwordVerify(ResetPasswordDTO $dto): bool
{
$request = new GetRequest(str_replace('{hash}', $dto->hash, $this->carfitEndpoint['password_hash']));
return $this->sendRequest($request);
}
/**
* @throws Exception
*/
public function resetPassword(ResetPasswordDTO $dto): bool
{
$request = new PostRequest(str_replace('{hash}', $dto->hash, $this->carfitEndpoint['password_reset']));
$request->setBody([
'email' => $dto->email,
'password' => $dto->password,
]);
return $this->sendRequest($request);
}
/**
* @throws Exception
*/
public function register(RegisterDTO $dto): bool
{
$request = new PostRequest($this->carfitEndpoint['register']);
$request->setBody([
'email' => $dto->email,
'password' => $dto->password,
]);
return $this->sendRegisterRequest($request);
}
/**
* @throws Exception
*/
public function registerCheck(RegisterDTO $dto): Client
{
$request = new PostRequest($this->carfitEndpoint['register_confirm']);
$request->setBody([
'email' => $dto->email,
'code' => $dto->code,
]);
$outputDto = new AuthOutputDTO();
try {
$content = $this->call($request);
$outputDto->token = $content['token'];
} catch (ClientException $exception) {
if (Response::HTTP_BAD_REQUEST == $exception->getCode()) {
throw new ExpiredCodeException('register.code.expired');
} else {
throw new BadRequestHttpException($exception->getMessage());
}
} catch (Throwable $exception) {
$this->logger->error($exception->getMessage());
throw new Exception('Internal Server Error! A error occurred while working on the request.');
}
/* @todo remove it */
return ClientMapper::fromAuthDTO($outputDto);
}
/**
* @throws Exception
*/
public function registerResend(RegisterDTO $dto): bool
{
$request = new PostRequest($this->carfitEndpoint['register_resend']);
$request->setBody([
'email' => $dto->email,
]);
return $this->sendRequest($request);
}
/**
* @throws TransportExceptionInterface
* @throws Throwable
* @throws ServerExceptionInterface
* @throws RedirectionExceptionInterface
* @throws DecodingExceptionInterface
* @throws ClientExceptionInterface
*/
public function logout(string $token): bool
{
$request = new DeleteRequest($this->carfitEndpoint['logout']);
$request->setAuthorization($token);
return $this->sendRequest($request);
}
/**
* @throws ClientFromMediaNotFoundException
*/
public function userMediaLogin(MediaDTO $dto): ?Client
{
$request = new PostRequest(str_replace('{provider}', $dto->provider, $this->carfitEndpoint['login_media']));
$request->setBody(['token' => $dto->token]);
try {
$content = $this->call($request);
$outputDto = new AuthOutputDTO();
$outputDto->token = $content['token'];
return ClientMapper::fromAuthDTO($outputDto);
} catch (ClientException $exception) {
throw new ClientFromMediaNotFoundException('auth.not_found');
} catch (Throwable $exception) {
$this->logger->error($exception->getMessage());
throw new CustomUserMessageAuthenticationException('error.500');
}
}
public function userMediaRegister(MediaDTO $dto): bool
{
$request = new PostRequest($this->carfitEndpoint['register_media']);
$request->setBody([
'token' => $dto->token
]);
return $this->sendRegisterRequest($request);
}
/**
* @throws Exception
*/
private function sendRegisterRequest(PostRequest $request): bool
{
try {
return $this->sendRequest($request);
} catch (ClientException $exception) {
$this->logger->error($exception->getMessage());
if (Response::HTTP_CONFLICT == $exception->getCode()) {
throw new BadRequestHttpException('email.already_taken');
} else {
throw new BadRequestHttpException($exception->getMessage());
}
} catch (Throwable $exception) {
$this->logger->error($exception->getMessage());
throw new Exception('Internal Server Error! A error occurred while working on the request.');
}
}
}