Completed
Push — develop ( 098751...1bc9e0 )
by Alejandro
16s queued 12s
created

AuthenticationMiddleware::apiKeyFromRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Shlinkio\Shlink\Rest\Middleware;
6
7
use Fig\Http\Message\RequestMethodInterface;
8
use Fig\Http\Message\StatusCodeInterface;
9
use Mezzio\Router\RouteResult;
10
use Psr\Http\Message\ResponseInterface as Response;
11
use Psr\Http\Message\ServerRequestInterface as Request;
12
use Psr\Http\Server\MiddlewareInterface;
13
use Psr\Http\Server\RequestHandlerInterface;
14
use Shlinkio\Shlink\Rest\Exception\MissingAuthenticationException;
15
use Shlinkio\Shlink\Rest\Exception\VerifyAuthenticationException;
16
use Shlinkio\Shlink\Rest\Service\ApiKeyServiceInterface;
17
18
use function Functional\contains;
19
20
class AuthenticationMiddleware implements MiddlewareInterface, StatusCodeInterface, RequestMethodInterface
21
{
22
    public const API_KEY_HEADER = 'X-Api-Key';
23 6
24
    private ApiKeyServiceInterface $apiKeyService;
25 6
    private array $routesWhitelist;
26 6
27 6
    public function __construct(ApiKeyServiceInterface $apiKeyService, array $routesWhitelist)
28
    {
29 6
        $this->apiKeyService = $apiKeyService;
30
        $this->routesWhitelist = $routesWhitelist;
31
    }
32 6
33
    public function process(Request $request, RequestHandlerInterface $handler): Response
34 6
    {
35 6
        /** @var RouteResult|null $routeResult */
36 6
        $routeResult = $request->getAttribute(RouteResult::class);
37 6
        if (
38
            $routeResult === null
39 4
            || $routeResult->isFailure()
40
            || $request->getMethod() === self::METHOD_OPTIONS
41
            || contains($this->routesWhitelist, $routeResult->getMatchedRouteName())
42 2
        ) {
43 2
            return $handler->handle($request);
44 2
        }
45
46 2
        $apiKey = self::apiKeyFromRequest($request);
47
        if (empty($apiKey)) {
48
            throw MissingAuthenticationException::fromExpectedTypes([self::API_KEY_HEADER]);
49
        }
50
51
        if (! $this->apiKeyService->check($apiKey)) {
52
            throw VerifyAuthenticationException::forInvalidApiKey();
53
        }
54
55
        return $handler->handle($request);
56
    }
57
58
    public static function apiKeyFromRequest(Request $request): string
59
    {
60
        return $request->getHeaderLine(self::API_KEY_HEADER);
61
    }
62
}
63