Failed Conditions
Push — master ( c6baf0...a3629e )
by Florent
16:19
created

Client   A

Complexity

Total Complexity 39

Size/Duplication

Total Lines 197
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 9

Importance

Changes 0
Metric Value
wmc 39
lcom 1
cbo 9
dl 0
loc 197
rs 9.28
c 0
b 0
f 0

25 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A getSchema() 0 4 1
A getClientId() 0 9 2
A getOwnerId() 0 4 1
A setOwnerId() 0 4 1
A setParameter() 0 4 1
A markAsDeleted() 0 4 1
A isDeleted() 0 4 1
A isGrantTypeAllowed() 0 9 3
A isResponseTypeAllowed() 0 9 3
A isPublic() 0 4 1
A getTokenEndpointAuthenticationMethod() 0 8 2
A getClientCredentialsExpiresAt() 0 8 2
A areClientCredentialsExpired() 0 8 2
A getPublicId() 0 8 2
A has() 0 4 1
A get() 0 8 2
A all() 0 7 1
A jsonSerialize() 0 13 2
A apply() 0 12 4
A getEventMap() 0 9 1
A applyClientCreatedEvent() 0 6 1
A applyClientOwnerChangedEvent() 0 4 1
A applyClientDeletedEvent() 0 4 1
A applyClientParametersUpdatedEvent() 0 4 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\Core\Client;
15
16
use OAuth2Framework\Component\Core\Client\Event as ClientEvent;
17
use OAuth2Framework\Component\Core\DataBag\DataBag;
18
use OAuth2Framework\Component\Core\Domain\DomainObject;
19
use OAuth2Framework\Component\Core\Event\Event;
20
use OAuth2Framework\Component\Core\ResourceOwner\ResourceOwner;
21
use OAuth2Framework\Component\Core\ResourceOwner\ResourceOwnerId;
22
use OAuth2Framework\Component\Core\UserAccount\UserAccountId;
23
24
/**
25
 * Class ClientCredentials.
26
 *
27
 * This class is used for every client types.
28
 * A client is a resource owner with a set of allowed grant types and can perform requests against
29
 * available endpoints.
30
 */
31
class Client implements ResourceOwner, DomainObject
32
{
33
    private $clientId;
34
    private $ownerId;
35
    protected $parameter;
36
    private $deleted;
37
38
    public function __construct(ClientId $clientId, DataBag $parameters, ?UserAccountId $ownerId)
39
    {
40
        $this->clientId = $clientId;
41
        $this->parameter = $parameters;
42
        $this->ownerId = $ownerId;
43
        $this->deleted = false;
44
    }
45
46
    public static function getSchema(): string
47
    {
48
        return 'https://oauth2-framework.spomky-labs.com/schemas/model/client/1.0/schema';
49
    }
50
51
    public function getClientId(): ClientId
52
    {
53
        $id = $this->getPublicId();
54
        if (!$id instanceof ClientId) {
55
            throw new \RuntimeException('Client not initialized.');
56
        }
57
58
        return $id;
59
    }
60
61
    public function getOwnerId(): ?UserAccountId
62
    {
63
        return $this->ownerId;
64
    }
65
66
    public function setOwnerId(UserAccountId $ownerId): void
67
    {
68
        $this->ownerId = $ownerId;
69
    }
70
71
    public function setParameter(DataBag $parameter): void
72
    {
73
        $this->parameter = $parameter;
74
    }
75
76
    public function markAsDeleted(): void
77
    {
78
        $this->deleted = true;
79
    }
80
81
    public function isDeleted(): bool
82
    {
83
        return $this->deleted;
84
    }
85
86
    public function isGrantTypeAllowed(string $grant_type): bool
87
    {
88
        $grant_types = $this->has('grant_types') ? $this->get('grant_types') : [];
89
        if (!\is_array($grant_types)) {
90
            throw new \InvalidArgumentException('The metadata "grant_types" must be an array.');
91
        }
92
93
        return \in_array($grant_type, $grant_types, true);
94
    }
95
96
    public function isResponseTypeAllowed(string $response_type): bool
97
    {
98
        $response_types = $this->has('response_types') ? $this->get('response_types') : [];
99
        if (!\is_array($response_types)) {
100
            throw new \InvalidArgumentException('The metadata "response_types" must be an array.');
101
        }
102
103
        return \in_array($response_type, $response_types, true);
104
    }
105
106
    public function isPublic(): bool
107
    {
108
        return 'none' === $this->getTokenEndpointAuthenticationMethod();
109
    }
110
111
    public function getTokenEndpointAuthenticationMethod(): string
112
    {
113
        if ($this->has('token_endpoint_auth_method')) {
114
            return $this->get('token_endpoint_auth_method');
115
        }
116
117
        return 'client_secret_basic';
118
    }
119
120
    public function getClientCredentialsExpiresAt(): int
121
    {
122
        if ($this->has('client_secret_expires_at')) {
123
            return $this->get('client_secret_expires_at');
124
        }
125
126
        return 0;
127
    }
128
129
    public function areClientCredentialsExpired(): bool
130
    {
131
        if (0 === $this->getClientCredentialsExpiresAt()) {
132
            return false;
133
        }
134
135
        return \time() > $this->getClientCredentialsExpiresAt();
136
    }
137
138
    public function getPublicId(): ResourceOwnerId
139
    {
140
        if (null === $this->clientId) {
141
            throw new \RuntimeException('Client not initialized.');
142
        }
143
144
        return $this->clientId;
145
    }
146
147
    public function has(string $key): bool
148
    {
149
        return $this->parameter->has($key);
150
    }
151
152
    public function get(string $key)
153
    {
154
        if (!$this->has($key)) {
155
            throw new \InvalidArgumentException(\sprintf('Configuration value with key "%s" does not exist.', $key));
156
        }
157
158
        return $this->parameter->get($key);
159
    }
160
161
    public function all(): array
162
    {
163
        $all = $this->parameter->all();
164
        $all['client_id'] = $this->getPublicId()->getValue();
165
166
        return $all;
167
    }
168
169
    public function jsonSerialize()
170
    {
171
        $data = [
172
            '$schema' => $this->getSchema(),
173
            'type' => \get_class($this),
174
            'client_id' => $this->getPublicId()->getValue(),
175
            'owner_id' => $this->getOwnerId() ? $this->getOwnerId()->getValue() : null,
176
            'parameters' => (object) $this->all(),
177
            'is_deleted' => $this->isDeleted(),
178
        ];
179
180
        return $data;
181
    }
182
183
    public function apply(Event $event): void
184
    {
185
        $map = $this->getEventMap();
186
        if (!\array_key_exists($event->getType(), $map)) {
187
            throw new \InvalidArgumentException('Unsupported event.');
188
        }
189
        if (null !== $this->clientId && $this->clientId->getValue() !== $event->getDomainId()->getValue()) {
190
            throw new \InvalidArgumentException('Event not applicable for this client.');
191
        }
192
        $method = $map[$event->getType()];
193
        $this->$method($event);
194
    }
195
196
    private function getEventMap(): array
197
    {
198
        return [
199
            ClientEvent\ClientCreatedEvent::class => 'applyClientCreatedEvent',
200
            ClientEvent\ClientOwnerChangedEvent::class => 'applyClientOwnerChangedEvent',
201
            ClientEvent\ClientDeletedEvent::class => 'applyClientDeletedEvent',
202
            ClientEvent\ClientParametersUpdatedEvent::class => 'applyClientParametersUpdatedEvent',
203
        ];
204
    }
205
206
    protected function applyClientCreatedEvent(ClientEvent\ClientCreatedEvent $event): void
207
    {
208
        $this->clientId = $event->getClientId();
209
        $this->ownerId = $event->getOwnerId();
210
        $this->parameter = $event->getParameters();
211
    }
212
213
    protected function applyClientOwnerChangedEvent(ClientEvent\ClientOwnerChangedEvent $event): void
214
    {
215
        $this->ownerId = $event->getNewOwnerId();
216
    }
217
218
    protected function applyClientDeletedEvent(ClientEvent\ClientDeletedEvent $event): void
219
    {
220
        $this->deleted = true;
221
    }
222
223
    protected function applyClientParametersUpdatedEvent(ClientEvent\ClientParametersUpdatedEvent $event): void
224
    {
225
        $this->parameter = $event->getParameters();
226
    }
227
}
228