Failed Conditions
Push — master ( 4fec28...cca42a )
by Florent
04:20
created

RefreshToken::getRefreshTokenId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 0
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\RefreshTokenGrant;
15
16
use OAuth2Framework\Component\RefreshTokenGrant\Event as RefreshTokenEvent;
17
use OAuth2Framework\Component\Core\AccessToken\AccessTokenId;
18
use OAuth2Framework\Component\Core\Client\ClientId;
19
use OAuth2Framework\Component\Core\DataBag\DataBag;
20
use OAuth2Framework\Component\Core\Event\Event;
21
use OAuth2Framework\Component\Core\ResourceOwner\ResourceOwnerId;
22
use OAuth2Framework\Component\Core\ResourceServer\ResourceServerId;
23
use OAuth2Framework\Component\Core\Token\Token;
24
use OAuth2Framework\Component\Core\Token\TokenId;
25
use OAuth2Framework\Component\Core\Domain\DomainObject;
26
27
class RefreshToken extends Token
28
{
29
    /**
30
     * @var RefreshTokenId|null
31
     */
32
    private $refreshTokenId = null;
33
34
    /**
35
     * @var AccessTokenId[]
36
     */
37
    private $accessTokenIds = [];
38
39
    /**
40
     * @return RefreshToken
41
     */
42
    public static function createEmpty(): self
43
    {
44
        return new self();
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     */
50
    public static function getSchema(): string
51
    {
52
        return 'https://oauth2-framework.spomky-labs.com/schemas/model/refresh-token/1.0/schema';
53
    }
54
55
    /**
56
     * @param RefreshTokenId        $refreshTokenId
57
     * @param ResourceOwnerId       $resourceOwnerId
58
     * @param ClientId              $clientId
59
     * @param DataBag               $parameters
60
     * @param DataBag               $metadatas
61
     * @param \DateTimeImmutable    $expiresAt
62
     * @param ResourceServerId|null $resourceServerId
63
     *
64
     * @return RefreshToken
65
     */
66
    public function create(RefreshTokenId $refreshTokenId, ResourceOwnerId $resourceOwnerId, ClientId $clientId, DataBag $parameters, DataBag $metadatas, \DateTimeImmutable $expiresAt, ? ResourceServerId $resourceServerId): self
67
    {
68
        $clone = clone $this;
69
        $clone->refreshTokenId = $refreshTokenId;
70
        $clone->resourceOwnerId = $resourceOwnerId;
71
        $clone->clientId = $clientId;
72
        $clone->parameters = $parameters;
73
        $clone->metadatas = $metadatas;
74
        $clone->expiresAt = $expiresAt;
75
        $clone->resourceServerId = $resourceServerId;
76
77
        $event = RefreshTokenEvent\RefreshTokenCreatedEvent::create($refreshTokenId, $resourceOwnerId, $clientId, $parameters, $metadatas, $expiresAt, $resourceServerId);
78
        $clone->record($event);
79
80
        return $clone;
81
    }
82
83
    /**
84
     * {@inheritdoc}
85
     */
86
    public function getTokenId(): TokenId
87
    {
88
        if (null === $this->refreshTokenId) {
89
            throw new \LogicException('Refresh token not initialized.');
90
        }
91
92
        return $this->refreshTokenId;
93
    }
94
95
    /**
96
     * @return RefreshTokenId
97
     */
98
    public function getRefreshTokenId(): RefreshTokenId
99
    {
100
        $id = $this->getTokenId();
101
        if (!$id instanceof RefreshTokenId) {
102
            throw new \LogicException('Refresh token not initialized.');
103
        }
104
105
        return $this->refreshTokenId;
106
    }
107
108
    /**
109
     * @param AccessTokenId $accessTokenId
110
     *
111
     * @return RefreshToken
112
     */
113
    public function addAccessToken(AccessTokenId $accessTokenId): self
114
    {
115
        $id = $accessTokenId->getValue();
116
        if (array_key_exists($id, $this->accessTokenIds)) {
117
            return $this;
118
        }
119
120
        $clone = clone $this;
121
        $clone->accessTokenIds[$id] = $accessTokenId;
122
        $event = RefreshTokenEvent\AccessTokenAddedToRefreshTokenEvent::create($clone->getRefreshTokenId(), $accessTokenId);
123
        $clone->record($event);
124
125
        return $clone;
126
    }
127
128
    /**
129
     * @return AccessTokenId[]
130
     */
131
    public function getAccessTokenIds(): array
132
    {
133
        return $this->accessTokenIds;
134
    }
135
136
    /**
137
     * @return array
138
     */
139
    public function getResponseData(): array
140
    {
141
        $data = $this->getParameters();
142
        $data = $data->with('access_token', $this->getTokenId()->getValue());
143
        $data = $data->with('expires_in', $this->getExpiresIn());
144
        if (!empty($this->getTokenId())) {
145
            $data = $data->with('refresh_token', $this->getTokenId());
146
        }
147
148
        return $data->all();
149
    }
150
151
    /**
152
     * {@inheritdoc}
153
     */
154
    public static function createFromJson(\stdClass $json): DomainObject
155
    {
156
        $refreshTokenId = RefreshTokenId::create($json->refresh_token_id);
157
        $resourceServerId = null !== $json->resource_server_id ? ResourceServerId::create($json->resource_server_id) : null;
158
        $accessTokenIds = [];
159
        foreach ($json->access_token_ids as $access_token_id) {
160
            $accessTokenIds[$access_token_id] = AccessTokenId::create($access_token_id);
161
        }
162
163
        $expiresAt = \DateTimeImmutable::createFromFormat('U', (string) $json->expires_at);
164
        $clientId = ClientId::create($json->client_id);
165
        $parameters = DataBag::create((array) $json->parameters);
166
        $metadatas = DataBag::create((array) $json->metadatas);
167
        $revoked = $json->is_revoked;
168
        $resourceOwnerClass = $json->resource_owner_class;
169
        $resourceOwnerId = $resourceOwnerClass::create($json->resource_owner_id);
170
171
        $refreshToken = new self();
172
        $refreshToken->refreshTokenId = $refreshTokenId;
173
        $refreshToken->accessTokenIds = $accessTokenIds;
174
        $refreshToken->resourceServerId = $resourceServerId;
175
176
        $refreshToken->expiresAt = $expiresAt;
177
        $refreshToken->clientId = $clientId;
178
        $refreshToken->parameters = $parameters;
179
        $refreshToken->metadatas = $metadatas;
180
        $refreshToken->revoked = $revoked;
181
        $refreshToken->resourceOwnerId = $resourceOwnerId;
182
183
        return $refreshToken;
184
    }
185
186
    /**
187
     * {@inheritdoc}
188
     */
189
    public function jsonSerialize()
190
    {
191
        $data = parent::jsonSerialize() + [
192
                'refresh_token_id' => $this->getTokenId()->getValue(),
193
                'access_token_ids' => array_keys($this->getAccessTokenIds()),
194
                'resource_server_id' => $this->getResourceServerId() ? $this->getResourceServerId()->getValue() : null,
195
            ];
196
197
        return $data;
198
    }
199
200
    /**
201
     * @return bool
202
     */
203
    public function isRevoked(): bool
204
    {
205
        return $this->revoked;
206
    }
207
208
    /**
209
     * @return RefreshToken
210
     */
211
    public function markAsRevoked(): self
212
    {
213
        $clone = clone $this;
214
        $clone->revoked = true;
215
        $event = RefreshTokenEvent\RefreshTokenRevokedEvent::create($clone->getRefreshTokenId());
216
        $clone->record($event);
217
218
        return $clone;
219
    }
220
221
    /**
222
     * @param Event $event
223
     *
224
     * @return RefreshToken
225
     */
226
    public function apply(Event $event): self
227
    {
228
        $map = $this->getEventMap();
229
        if (!array_key_exists($event->getType(), $map)) {
230
            throw new \InvalidArgumentException('Unsupported event.');
231
        }
232
        if (null !== $this->refreshTokenId && $this->refreshTokenId->getValue() !== $event->getDomainId()->getValue()) {
233
            throw new \RuntimeException('Event not applicable for this refresh token.');
234
        }
235
        $method = $map[$event->getType()];
236
237
        return $this->$method($event);
238
    }
239
240
    /**
241
     * @return array
242
     */
243
    private function getEventMap(): array
244
    {
245
        return [
246
            RefreshTokenEvent\RefreshTokenCreatedEvent::class => 'applyRefreshTokenCreatedEvent',
247
            RefreshTokenEvent\AccessTokenAddedToRefreshTokenEvent::class => 'applyAccessTokenAddedToRefreshTokenEvent',
248
            RefreshTokenEvent\RefreshTokenRevokedEvent::class => 'applyRefreshTokenRevokedEvent',
249
        ];
250
    }
251
252
    /**
253
     * @param RefreshTokenEvent\RefreshTokenCreatedEvent $event
254
     *
255
     * @return RefreshToken
256
     */
257
    protected function applyRefreshTokenCreatedEvent(RefreshTokenEvent\RefreshTokenCreatedEvent $event): self
258
    {
259
        $clone = clone $this;
260
        $clone->refreshTokenId = $event->getRefreshTokenId();
261
        $clone->resourceOwnerId = $event->getResourceOwnerId();
262
        $clone->clientId = $event->getClientId();
263
        $clone->parameters = $event->getParameters();
264
        $clone->metadatas = $event->getMetadatas();
265
        $clone->expiresAt = $event->getExpiresAt();
266
        $clone->resourceServerId = $event->getResourceServerId();
267
268
        return $clone;
269
    }
270
271
    /**
272
     * @param RefreshTokenEvent\AccessTokenAddedToRefreshTokenEvent $event
273
     *
274
     * @return RefreshToken
275
     */
276
    protected function applyAccessTokenAddedToRefreshTokenEvent(RefreshTokenEvent\AccessTokenAddedToRefreshTokenEvent $event): self
277
    {
278
        $clone = clone $this;
279
        $clone->accessTokenIds[$event->getAccessTokenId()->getValue()] = $event->getAccessTokenId();
280
281
        return $clone;
282
    }
283
284
    /**
285
     * @param RefreshTokenEvent\RefreshTokenRevokedEvent $event
286
     *
287
     * @return RefreshToken
288
     */
289
    protected function applyRefreshTokenRevokedEvent(RefreshTokenEvent\RefreshTokenRevokedEvent $event): self
290
    {
291
        $clone = clone $this;
292
        $clone->revoked = true;
293
294
        return $clone;
295
    }
296
}
297