Failed Conditions
Push — master ( 437f03...a35595 )
by Sébastien
02:42
created

ApiTokenLoginHandler::handle()   B

Complexity

Conditions 7
Paths 12

Size

Total Lines 50
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
cc 7
eloc 29
nc 12
nop 1
dl 0
loc 50
ccs 0
cts 33
cp 0
crap 56
rs 8.5226
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Handler;
6
7
use App\Security\ContredanseProductAccess;
8
use App\Security\Exception\NoProductAccessException;
9
use App\Security\Exception\ProductAccessExpiredException;
10
use App\Security\Exception\ProductPaymentIssueException;
11
use App\Security\UserProviderInterface;
12
use App\Service\Auth\AuthenticationManager;
13
use App\Service\Auth\Exception\AuthExceptionInterface;
14
use App\Service\Token\Exception\TokenValidationExceptionInterface;
15
use App\Service\Token\TokenManager;
16
use Fig\Http\Message\StatusCodeInterface;
17
use Psr\Http\Message\ResponseInterface;
18
use Psr\Http\Message\ServerRequestInterface;
19
use Psr\Http\Server\RequestHandlerInterface;
20
use Zend\Diactoros\Response\JsonResponse;
21
use Zend\Diactoros\Response\TextResponse;
22
23
class ApiTokenLoginHandler implements RequestHandlerInterface
24
{
25
    /**
26
     * @var UserProviderInterface
27
     */
28
    private $userProvider;
29
30
    /**
31
     * @var TokenManager
32
     */
33
    private $tokenManager;
34
35
    /**
36
     * @var array<string, mixed>
37
     */
38
    private $authParams;
39
40
    /*
41
     * @var ContredanseProductAccess
42
     */
43
    private $productAccess;
44
45
    /**
46
     * @param array<string, mixed> $authParams
47
     */
48
    public function __construct(UserProviderInterface $userProvider, TokenManager $tokenManager, ContredanseProductAccess $productAccess, array $authParams = [])
49
    {
50
        $this->userProvider  = $userProvider;
51
        $this->tokenManager  = $tokenManager;
52
        $this->authParams    = $authParams;
53
        $this->productAccess = $productAccess;
54
    }
55
56
    public function handle(ServerRequestInterface $request): ResponseInterface
57
    {
58
		$authExpiry = $this->authParams['token_expiry'] ?? TokenManager::DEFAULT_EXPIRY;
59
60
		$method = $request->getMethod();
61
		if ($method !== 'POST') {
62
			throw new \RuntimeException('Unsupported http method');
63
		}
64
		// Authorization...
65
		//
66
		// Valid users are
67
		// - either admins
68
		// - or valid paying users
69
		//
70
71
		$body     = $request->getParsedBody();
72
		$email    = trim($body['email'] ?? '');
73
		$password = trim($body['password'] ?? '');
74
75
		// @todo Must be removed when production
76
		if ($email === '[email protected]' && $password === 'demo') {
77
			// This is for demo only
78
			return $this->getResponseWithAccessToken('[email protected]', $authExpiry);
79
		}
80
81
		$authenticationManager = new AuthenticationManager($this->userProvider);
82
83
		try {
84
			// Authenticate, wil throw exception if failed
85
			$user = $authenticationManager->getAuthenticatedUser($email, $password);
86
87
			// Ensure authorization
88
			$this->productAccess->ensureAccess(ContredanseProductAccess::PAXTON_PRODUCT, $user);
89
90
			return $this->getResponseWithAccessToken($user->getDetail('user_id'), $authExpiry);
91
		} catch (AuthExceptionInterface $e) {
92
			return (new JsonResponse([
93
				'success' => false,
94
				'reason'  => $e->getReason()
95
			]))->withStatus($e->getStatusCode());
96
		} catch (NoProductAccessException | ProductPaymentIssueException | ProductAccessExpiredException $e) {
97
			return (new JsonResponse([
98
				'success' => false,
99
				'reason'  => $e->getMessage(),
100
			]))->withStatus(StatusCodeInterface::STATUS_UNAUTHORIZED);
101
		} catch (\Throwable $e) {
102
			return (new JsonResponse([
103
				'success' => false,
104
				'reason'  => $e->getMessage()
105
			]))->withStatus(StatusCodeInterface::STATUS_BAD_REQUEST);
106
		}
107
    }
108
109
110
    private function getResponseWithAccessToken(string $user_id, int $authExpiry): ResponseInterface
111
    {
112
        $token = $this->tokenManager->createNewToken([
113
            'user_id' => $user_id
114
            //'email'    => $email,
115
        ], $authExpiry);
116
117
        return (new JsonResponse([
118
            'access_token' => (string) $token,
119
            'token_type'   => 'api_auth',
120
            'success'      => true,
121
        ]))->withStatus(StatusCodeInterface::STATUS_OK);
122
    }
123
}
124