Failed Conditions
Push — master ( b8d841...bc596e )
by Florent
28:20
created

WebFingerEndpoint::getIdentifier()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * The MIT License (MIT)
7
 *
8
 * Copyright (c) 2014-2018 Spomky-Labs
9
 *
10
 * This software may be modified and distributed under the terms
11
 * of the MIT license.  See the LICENSE file for details.
12
 */
13
14
namespace OAuth2Framework\Component\WebFingerEndpoint;
15
16
use Http\Message\ResponseFactory;
17
use OAuth2Framework\Component\WebFingerEndpoint\IdentifierResolver\Identifier;
18
use OAuth2Framework\Component\WebFingerEndpoint\IdentifierResolver\IdentifierResolverManager;
19
use Psr\Http\Message\ResponseInterface;
20
use Psr\Http\Message\ServerRequestInterface;
21
use Psr\Http\Server\MiddlewareInterface;
22
use Psr\Http\Server\RequestHandlerInterface;
23
24
final class WebFingerEndpoint implements MiddlewareInterface
25
{
26
    private $responseFactory;
27
28
    private $identifierResolverManager;
29
30
    private $resourceRepository;
31
32
    public function __construct(ResponseFactory $responseFactory, ResourceRepository $resourceRepository, IdentifierResolverManager $identifierResolverManager)
33
    {
34
        $this->resourceRepository = $resourceRepository;
35
        $this->responseFactory = $responseFactory;
36
        $this->identifierResolverManager = $identifierResolverManager;
37
    }
38
39
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
40
    {
41
        try {
42
            $resource = $this->getResource($request);
43
            $identifier = $this->getIdentifier($resource);
44
            $resourceDescriptor = $this->resourceRepository->find($resource, $identifier);
45
            if (null === $resourceDescriptor) {
46
                throw new \InvalidArgumentException(\sprintf('The resource identified with "%s" does not exist or is not supported by this server.', $resource), 400);
47
            }
48
49
            $filteredResourceDescriptor = $this->filterLinks($request, $resourceDescriptor);
50
            $response = $this->responseFactory->createResponse(200);
51
            $headers = [
52
                'Content-Type' => 'application/jrd+json; charset=UTF-8',
53
            ];
54
            $response->getBody()->write(\json_encode($filteredResourceDescriptor, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
55
        } catch (\InvalidArgumentException $e) {
56
            $response = $this->responseFactory->createResponse($e->getCode());
57
            $headers = [
58
                'Content-Type' => 'application/json; charset=UTF-8',
59
            ];
60
            $response->getBody()->write(\json_encode(['error' => 'invalid_request', 'error_description' => $e->getMessage()], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
61
        }
62
        foreach ($headers as $k => $v) {
63
            $response = $response->withHeader($k, $v);
64
        }
65
66
        return $response;
67
    }
68
69
    /**
70
     * @throws \InvalidArgumentException
71
     */
72
    private function getIdentifier(string $resource): Identifier
73
    {
74
        try {
75
            return $this->identifierResolverManager->resolve($resource);
76
        } catch (\Exception $e) {
77
            throw new \InvalidArgumentException(\sprintf('The resource identified with "%s" does not exist or is not supported by this server.', $resource), 400, $e);
78
        }
79
    }
80
81
    /**
82
     * @throws \InvalidArgumentException
83
     */
84
    private function getResource(ServerRequestInterface $request): string
85
    {
86
        $query_params = $request->getQueryParams() ?? [];
87
        if (!\array_key_exists('resource', $query_params)) {
88
            throw new \InvalidArgumentException('The parameter "resource" is mandatory.', 400);
89
        }
90
91
        return $query_params['resource'];
92
    }
93
94
    /**
95
     * @throws \InvalidArgumentException
96
     */
97
    private function filterLinks(ServerRequestInterface $request, ResourceDescriptor $resourceDescriptor): array
98
    {
99
        $data = $resourceDescriptor->jsonSerialize();
100
101
        $rels = $this->getRels($request);
102
        if (empty($rels) || !array_key_exists('links', $data) || empty($data['links'])) {
103
            return $data;
104
        }
105
106
        $data['links'] = array_filter($data['links'], function (Link $link) use ($rels): ?Link {
107
            if (\in_array($link->getRel(), $rels, true)) {
108
                return $link;
109
            }
110
111
            return null;
112
        });
113
        if (empty($data['links'])) {
114
            unset($data['links']);
115
        }
116
117
        return $data;
118
    }
119
120
    /**
121
     * @return string[]
122
     */
123
    private function getRels(ServerRequestInterface $request): array
124
    {
125
        $queryParams = $request->getQueryParams();
126
        if (!array_key_exists('rel', $queryParams)) {
127
            return [];
128
        }
129
130
        switch (true) {
131
            case \is_string($queryParams['rel']):
132
                return [$queryParams['rel']];
133
            case \is_array($queryParams['rel']):
134
                return $queryParams['rel'];
135
            default:
136
                return [];
137
        }
138
    }
139
}
140