Failed Conditions
Push — master ( c24b3a...b512e9 )
by Florent
14:42
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
     * @param AccessTokenId $accessTokenId
97
     *
98
     * @return RefreshToken
99
     */
100
    public function addAccessToken(AccessTokenId $accessTokenId): self
101
    {
102
        $id = $accessTokenId->getValue();
103
        if (array_key_exists($id, $this->accessTokenIds)) {
104
            return $this;
105
        }
106
107
        $clone = clone $this;
108
        $clone->accessTokenIds[$id] = $accessTokenId;
109
        $event = RefreshTokenEvent\AccessTokenAddedToRefreshTokenEvent::create($clone->getTokenId(), $accessTokenId);
110
        $clone->record($event);
111
112
        return $clone;
113
    }
114
115
    /**
116
     * @return AccessTokenId[]
117
     */
118
    public function getAccessTokenIds(): array
119
    {
120
        return $this->accessTokenIds;
121
    }
122
123
    /**
124
     * @return array
125
     */
126
    public function getResponseData(): array
127
    {
128
        $data = $this->getParameters();
129
        $data = $data->with('access_token', $this->getTokenId()->getValue());
130
        $data = $data->with('expires_in', $this->getExpiresIn());
131
        if (!empty($this->getTokenId())) {
132
            $data = $data->with('refresh_token', $this->getTokenId());
133
        }
134
135
        return $data->all();
136
    }
137
138
    /**
139
     * {@inheritdoc}
140
     */
141
    public static function createFromJson(\stdClass $json): DomainObject
142
    {
143
        $refreshTokenId = RefreshTokenId::create($json->refresh_token_id);
144
        $resourceServerId = null !== $json->resource_server_id ? ResourceServerId::create($json->resource_server_id) : null;
145
        $accessTokenIds = [];
146
        foreach ($json->access_token_ids as $access_token_id) {
147
            $accessTokenIds[$access_token_id] = AccessTokenId::create($access_token_id);
148
        }
149
150
        $expiresAt = \DateTimeImmutable::createFromFormat('U', (string) $json->expires_at);
151
        $clientId = ClientId::create($json->client_id);
152
        $parameters = DataBag::create((array) $json->parameters);
153
        $metadatas = DataBag::create((array) $json->metadatas);
154
        $revoked = $json->is_revoked;
155
        $resourceOwnerClass = $json->resource_owner_class;
156
        $resourceOwnerId = $resourceOwnerClass::create($json->resource_owner_id);
157
158
        $refreshToken = new self();
159
        $refreshToken->refreshTokenId = $refreshTokenId;
160
        $refreshToken->accessTokenIds = $accessTokenIds;
161
        $refreshToken->resourceServerId = $resourceServerId;
162
163
        $refreshToken->expiresAt = $expiresAt;
164
        $refreshToken->clientId = $clientId;
165
        $refreshToken->parameters = $parameters;
166
        $refreshToken->metadatas = $metadatas;
167
        $refreshToken->revoked = $revoked;
168
        $refreshToken->resourceOwnerId = $resourceOwnerId;
169
170
        return $refreshToken;
171
    }
172
173
    /**
174
     * {@inheritdoc}
175
     */
176
    public function jsonSerialize()
177
    {
178
        $data = parent::jsonSerialize() + [
179
                'refresh_token_id' => $this->getTokenId()->getValue(),
180
                'access_token_ids' => array_keys($this->getAccessTokenIds()),
181
                'resource_server_id' => $this->getResourceServerId() ? $this->getResourceServerId()->getValue() : null,
182
            ];
183
184
        return $data;
185
    }
186
187
    /**
188
     * @return bool
189
     */
190
    public function isRevoked(): bool
191
    {
192
        return $this->revoked;
193
    }
194
195
    /**
196
     * @return RefreshToken
197
     */
198
    public function markAsRevoked(): self
199
    {
200
        $clone = clone $this;
201
        $clone->revoked = true;
202
        $event = RefreshTokenEvent\RefreshTokenRevokedEvent::create($clone->getTokenId());
203
        $clone->record($event);
204
205
        return $clone;
206
    }
207
208
    /**
209
     * @param Event $event
210
     *
211
     * @return RefreshToken
212
     */
213
    public function apply(Event $event): self
214
    {
215
        $map = $this->getEventMap();
216
        if (!array_key_exists($event->getType(), $map)) {
217
            throw new \InvalidArgumentException('Unsupported event.');
218
        }
219
        if (null !== $this->refreshTokenId && $this->refreshTokenId->getValue() !== $event->getDomainId()->getValue()) {
220
            throw new \RuntimeException('Event not applicable for this refresh token.');
221
        }
222
        $method = $map[$event->getType()];
223
224
        return $this->$method($event);
225
    }
226
227
    /**
228
     * @return array
229
     */
230
    private function getEventMap(): array
231
    {
232
        return [
233
            RefreshTokenEvent\RefreshTokenCreatedEvent::class => 'applyRefreshTokenCreatedEvent',
234
            RefreshTokenEvent\AccessTokenAddedToRefreshTokenEvent::class => 'applyAccessTokenAddedToRefreshTokenEvent',
235
            RefreshTokenEvent\RefreshTokenRevokedEvent::class => 'applyRefreshTokenRevokedEvent',
236
        ];
237
    }
238
239
    /**
240
     * @param RefreshTokenEvent\RefreshTokenCreatedEvent $event
241
     *
242
     * @return RefreshToken
243
     */
244
    protected function applyRefreshTokenCreatedEvent(RefreshTokenEvent\RefreshTokenCreatedEvent $event): self
245
    {
246
        $clone = clone $this;
247
        $clone->refreshTokenId = $event->getRefreshTokenId();
248
        $clone->resourceOwnerId = $event->getResourceOwnerId();
249
        $clone->clientId = $event->getClientId();
250
        $clone->parameters = $event->getParameters();
251
        $clone->metadatas = $event->getMetadatas();
252
        $clone->expiresAt = $event->getExpiresAt();
253
        $clone->resourceServerId = $event->getResourceServerId();
254
255
        return $clone;
256
    }
257
258
    /**
259
     * @param RefreshTokenEvent\AccessTokenAddedToRefreshTokenEvent $event
260
     *
261
     * @return RefreshToken
262
     */
263
    protected function applyAccessTokenAddedToRefreshTokenEvent(RefreshTokenEvent\AccessTokenAddedToRefreshTokenEvent $event): self
264
    {
265
        $clone = clone $this;
266
        $clone->accessTokenIds[$event->getAccessTokenId()->getValue()] = $event->getAccessTokenId();
267
268
        return $clone;
269
    }
270
271
    /**
272
     * @param RefreshTokenEvent\RefreshTokenRevokedEvent $event
273
     *
274
     * @return RefreshToken
275
     */
276
    protected function applyRefreshTokenRevokedEvent(RefreshTokenEvent\RefreshTokenRevokedEvent $event): self
277
    {
278
        $clone = clone $this;
279
        $clone->revoked = true;
280
281
        return $clone;
282
    }
283
}
284